Follow me第二季第1期 Adafruit Circuit Playground Express汇总
[复制链接]
本帖最后由 wolegequ2015 于 2024-10-11 05:08 编辑
第二次参加Follow me活动了,这次使用Adafruit Circuit Playground Express这块板子,对开源硬件和circuit有了更深入了解,参考资料丰富。从中学习到不少知识技能。期望后面能继续参加更多活动
视频介绍
物料清单
主要用到的物料有
1.Adafruit Circuit Playground Express
2.M5STAMPS3
因为Adafruit Circuit Playground Express板子外设资源十分丰富,完成任务可以完全靠板子上外设,但是我想拓展增加联网的功能,所以增加了一块M5STAMPS3,用于网络连接。
.本次完成任务的实物展示如下:
除了两个板子,还需要自备一个半圆外壳用于制作不倒翁。
入门任务
这次参加活动我使用的是circuitPython这个编程语言。板子上已经集成了一个led,通过图示可以看出led连接到Pin13。初始化led后,每隔一秒钟翻转io口的电平。实现led的驱动。
初始化io口为输送模式,代码和流程图如下。使用sleep函数,每隔一秒钟翻转一次io口电平。
import time
import board
import digitalio
led = digitalio.DigitalInOut(board.D13)
led.switch_to_output()
button = digitalio.DigitalInOut(board.BUTTON_A)
button.switch_to_input(pull=digitalio.Pull.DOWN)
while True:
if led.value: # button is pushed
led.value = False
else:
led.value = True
#led.value = ~led.value
time.sleep(1)
任务一 控制板载炫彩LED
板子已经集成了10个单总线led。控制板载的ws2812灯珠主要用到的库是neopixel,这个库固件已经集成导入即可使用。初始化的灯珠为10个,使用Circuit Python的好处是可以不关注引脚和原理图,。初始化能一键配置好。用户只需要考虑应用的设计。
这里参考官方的例程,通过流水灯的方式逐步点亮所有的led灯。当一个颜色循环结束后,切换颜色进行下一轮的循环。
代码和流程图如下。
import time
import board
from rainbowio import colorwheel
import neopixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
# choose which demos to play
# 1 means play, 0 means don't!
color_chase_demo = 1
flash_demo = 1
rainbow_demo = 1
rainbow_cycle_demo = 1
def color_chase(color, wait):
for i in range(10):
pixels[i] = color
time.sleep(wait)
pixels.show()
time.sleep(0.5)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
OFF = (0, 0, 0)
while True:
if color_chase_demo:
color_chase(RED, 0.1) # Increase the number to slow down the color chase
color_chase(YELLOW, 0.1)
color_chase(GREEN, 0.1)
color_chase(CYAN, 0.1)
color_chase(BLUE, 0.1)
color_chase(PURPLE, 0.1)
color_chase(OFF, 0.1)
在任务一中,尝试使用网络功能来实现无线控制led灯点亮和关闭,这里需要使用到M5STAMPS3这块板子,由于我对circuitpython wifi部分并不熟悉,这里对M5STAMPS3使用arduino进行程序开发
首先用M5STAMPS3创建一个热点,手机连上热点后,访问http://192.168.4.1/H或者http://192.168.4.1/L网址,即可控制M5STAMPS3的3号引脚输出高或低电平。
M5STAMPS3部分程序如下:
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define LED_BUILTIN 3 // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED
// Set these to your desired credentials.
const char *ssid = "MERCURY_3BE8111";
const char *password = "asdf1245";
WiFiServer server(80);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
// You can remove the password parameter if you want the AP to be open.
// a valid password must have more than 7 characters
if (!WiFi.softAP(ssid, password)) {
log_e("Soft AP creation failed.");
while(1);
}
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>");
client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(LED_BUILTIN, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
Adafruit Circuit Playground Express的A1脚连接到M5STAMPS3的3脚,当A1脚检测到高电平时,打开LED,低电平时关闭LED。
Adafruit Circuit Playground Express部分程序如下:
import time
import board
import digitalio
from rainbowio import colorwheel
import neopixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
color_chase_demo = 1
flash_demo = 1
rainbow_demo = 1
rainbow_cycle_demo = 1
def color_chase(color, wait):
for i in range(10):
pixels[i] = color
time.sleep(wait)
pixels.show()
time.sleep(0.5)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
OFF = (0, 0, 0)
led = digitalio.DigitalInOut(board.D13)
led.switch_to_output()
button = digitalio.DigitalInOut(board.A1)
button.switch_to_input(pull=digitalio.Pull.UP)
while True:
if button.value: # button is pushed
led.value = True
color_chase(YELLOW, 0.1)
else:
led.value = False
#led.value = ~led.value
color_chase(OFF, 0.1)
time.sleep(0.1)
程序流程图如下:
实物LED打开状态:
实物LED关闭状态:
任务二 监测环境温度和光线
监测环境的温度和光线,这里用到的是板载的温度传感器和光线传感器。 Circle Python内部已经集成了这个温度传感器的和光线传感器的驱动库。
温度传感器的例程可以转换成摄氏度和华氏度,这里使用最常用的单位摄氏度。这里舒适度转换的方式是以25度为基准,当温度越接近38度时,红色led的亮度越高,提醒人打开空调降温。。
光照传感器,是通过abc来读取传感器的电压值。从数据可以看出。光的强度越高的时候,ADC采集到的电压也越高。这里舒适度的显示方式是反向的,当光线强度较高的时候led熄灭。当光线不足时,led亮起提示人注意开灯。
代码和流程图如下。
import time
import board
import neopixel
import analogio
import adafruit_thermistor
from rainbowio import colorwheel
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.05, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
thermistor = adafruit_thermistor.Thermistor(
board.TEMPERATURE, 10000, 10000, 25, 3950)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
light = analogio.AnalogIn(board.LIGHT)
while True:
temp_c = thermistor.temperature
print(light.value)
l=(int(255*(65535-light.value/65535)),int(255*(65535-light.value/65535)),int(255*(65535-light.value/65535)))
print(l[0])
tem=(temp_c-25)/13
RED = (int(tem*255), 0, 0)
pixels[1]=RED
pixels[2]=l
pixels.show()
time.sleep(1)
任务三 接近检测
接近检测中,我使用了上一个任务的光照传感器。报警使用板载扬声器和LED。为了应对在不同光照条件下检测需求,防止误触发。首先上电后会先采集当前环环境的光照强度。因为自然的光照强度并不会突然发生变化。当有物体靠近时光照强度会发生剧烈的变化。设定阈值,当检测数据超过阈值时,发出警报。
警报是通过板载的扬声器。发出类似蜂鸣器的警报声。频率为440赫兹。当触发警报时,警报响5秒钟。并且led发红光警报。
代码和流程图如下。
import time
import array
import math
import board
import digitalio
import analogio
from rainbowio import colorwheel
import neopixel
try:
from audiocore import RawSample
except ImportError:
from audioio import RawSample
try:
from audioio import AudioOut
except ImportError:
try:
from audiopwmio import PWMAudioOut as AudioOut
except ImportError:
pass # not always supported by every board!
FREQUENCY = 440 # 440 Hz middle 'A'
SAMPLERATE = 8000 # 8000 samples/second, recommended!
# Generate one period of sine wav.
length = SAMPLERATE // FREQUENCY
sine_wave = array.array("H", [0] * length)
for i in range(length):
sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15)
# Enable the speaker
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.direction = digitalio.Direction.OUTPUT
speaker_enable.value = True
RED = (255, 0, 0)
OFF = (0, 0, 0)
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
def color_chase(color, wait):
for i in range(10):
pixels[i] = color
time.sleep(wait)
pixels.show()
time.sleep(0.5)
audio = AudioOut(board.SPEAKER)
sine_wave_sample = RawSample(sine_wave)
light = analogio.AnalogIn(board.LIGHT)
temp=light.value
while True:
#audio.play(sine_wave_sample, loop=True) # Play the single sine_wave sample continuously...
print(light.value)
if (abs(light.value-temp))>2000:
color_chase(RED, 0)
audio.play(sine_wave_sample, loop=True)
time.sleep(5) # for the duration of the sleep (in seconds)
audio.stop() # and then stop.
temp=light.value
color_chase(OFF, 0)
else:
temp=light.value
time.sleep(1)
color_chase(OFF, 0)
任务四 不倒翁设计
不倒翁硬件部分是通过一个半圆的球。这里需要用到板载的加速度传感器。以及板载的串行灯珠。使用加速度传感器检测当前的倾斜角度。并使用led显示在当前倾斜的最中心线最低点在哪个角。
加速度的传感器检测到的是xyz三个角的倾角。这里需要通过数学转换。如下图转换成向量。然后根据向量再点亮具体的led灯。这里需要注意的是,为了防止误触发,需要对角度啊设置一个阈值。当检测到x或者y超过某个范围之后才开始。触发led的指示灯。
代码流程图如下
import time
import board
import busio
import adafruit_lis3dh
import math
import array
from rainbowio import colorwheel
import neopixel
# import neopixel_off
OFF = (0, 0, 0)
RED = (255, 0, 0)
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.2, auto_write=False)
# i2c = board.I2C()
# lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c)
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)
# Set range of accelerometer (can be RANGE_2_G, RANGE_4_G, RANGE_8_G or RANGE_16_G).
lis3dh.range = adafruit_lis3dh.RANGE_2_G
a1=0
while True:
# Read accelerometer values (in m / s ^ 2). Returns a 3-tuple of x, y,
# z axis values. Divide them by 9.806 to convert to Gs.
x, y, z = [
value / adafruit_lis3dh.STANDARD_GRAVITY for value in lis3dh.acceleration
]
print("x = %0.3f G, y = %0.3f G, z = %0.3f G" % (x, y, z))
if (abs(x) > 0.3) or (abs(y) > 0.3):
if x > 0:
if y < 0:
y = -y
a1 = math.atan(x / y)
else:
a1 = 1.57 + math.atan(y / x)
print(a1)
print(12 * a1 / 6.28)
# a1=math.atan(x/y)
elif x < 0:
x = -x
print("x = %0.3f G, y = %0.3f G, z = %0.3f G" % (x, y, z))
if y < 0:
y = -y
a1 = 4.71 + math.atan(y / x)
else:
a1 = 3.14 + math.atan(x / y)
print(a1)
print(10 * a1 / 6.28)
b=int(10 * a1 / 6.28)
print(b)
for i in range(10):
pixels[i] = OFF
pixels[b] =RED
pixels.show()
else:
b=0
# print(a1)
# print(12*a1/6.28)
# Small delay to keep things responsive but give time for interrupt processing.
# print(math.asin(1))
for i in range(10):
pixels[i] = OFF
pixels.show()
time.sleep(0.2)
项目源码
https://download.eeworld.com.cn/detail/wolegequ2015/634254
心得体会
之前对Circuit Python的使用并不多,经过参加这次的活动,发现这门语言对于开发来说是十分便捷的,然常用的库都有,相对于之前用c来开发单片机,速度有明显的提升,对于一些原型概念设计场景,效果明显优于传统开发工具。Adafruit的库和开发工具一如既往的优秀。
|