【Follow me第二季第1期】任务报告汇总
[复制链接]
本帖最后由 disk0 于 2024-10-8 20:00 编辑
一 、3-5分钟短视频
https://training.eeworld.com.cn/video/40788
(1)简短的自我介绍
大家好,我是disk0,是一个Python 的初学者,也是micropython 和circuitpython 的爱好者
(2)展示任务所用全部物料实物
(3)设计思路(用下单器件的哪些模块实现了哪些功能)
主要使用使用CPX 的板载传感器(温度,亮度,三轴,蜂鸣器)完成 指定的任务
(4)各任务功能演示,需要在对应视频片段开始前,说明对应任务名称
详见视频介绍
二、任务实现详情
任务对应帖子如下:
【Follow me第二季第1期】开箱 https://bbs.eeworld.com.cn/thread-1289907-1-1.html
任务清单:
一、入门任务(必做):开发环境搭建,板载LED点亮
IDE
开发环境最早计划使用习惯的Thonny,但是后来发现我手里的CPX 在Thonny中,调试存在问题,后来使用官方推荐的Mu
CircuitPython下载
首先到官网下载UF2文件 https://circuitpython.org/board/circuitplayground_express/
P.S. 不建议使用 CHINESE (PINYIN) 版本哦,因为并不是汉字的系统,而是拼音字母,是非常可怕的
CircuitPython烧录
双击 开发板中心的 RESET 按键,板载的10个彩色灯珠(neopixel)会闪烁,最后停留在全部绿色的状态
这个时候 打开 我的电脑,会发现有一个 CPLAYBOOT 的盘
双击进入,把下载的UF2 文件复制,就会自动烧录了
烧录完成后,重启启动开发板,开启 Mu,就可以在状态栏看到已经成功连接了
CPX 有两种(LED 和 neopixel)一共 12颗灯珠。
其中 USB 口右侧的On 是电源指示灯,一般不用于编程。
所以本次任务,编程对象是 USB 口左侧的 D13 的LED灯珠。
import board
import digitalio
import time
led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
while True:
print("Hello, EEworld!")
led.value = not led.value
time.sleep(0.5)
主要逻辑
初始化LED灯后,在大循环中,打印一段内容,并 改变 led的value也是就是灯的亮和灭,最后sleep 进入下一次循环
尾巴
细心的朋友会发现,为什么D13 针脚没有出现在代码中?
让我在交互环境中运行
import board;help(board)
你会看到CircuitPython 已经对主板的一些定义和别名
这就是没有出现D13的原因。
不仅是LED,其他的一些板载传感器也都已经被CircuitPython定义好了,更多的大家可以自己查看。
这,也是我为何是喜欢CircuitPython的原因之一。
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
任务理解
任务中的 “炫彩LED”,是指 NeoPixel 灯带,虽然有10颗灯珠,其实只使用了MCU的一个IO,而且可以通过程序控制任何一个的颜色和明暗。
import time
import board
import neopixel
# 自定义常量
BOARD_NEO_QTY = 10
BOARD_NEQ_BRI = 0.008
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)
# 初始化 NeoPixel
pixels = neopixel.NeoPixel(board.NEOPIXEL, BOARD_NEO_QTY, brightness=BOARD_NEQ_BRI,auto_write=False)
# 每0.5秒,按顺序改变一个灯珠的颜色
def color_chase(color, wait):
for i in range(10):
pixels[i] = color
time.sleep(0.1)
pixels.show()
time.sleep(0.4)
while True:
color_chase(RED, 0.1)
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)
主要逻辑
1. 导入必须要库 time board 和主角 neopixel
2. 定义项目常量:灯珠数量,亮度 和颜色
3. 初始化
pixels = neopixel.NeoPixel(board.NEOPIXEL, BOARD_NEO_QTY, brightness=BOARD_NEQ_BRI,auto_write=False)
4. 定义跑马灯 函数
5. 大循环 中 切换不同的颜色,最后关闭
展示
请参考展示视频
基础任务二:监测环境温度和光线,通过板载LED展示舒适程度
任务理解
热敏电阻温度传感器 A9 和 光线传感器 A8 ,都已经集成在了主板,获取两个传感器的值映射到NeoPixel灯带
import time
import board
import neopixel
import analogio
import simpleio
import adafruit_thermistor
# 自定义常量
BOARD_NEO_QTY = 10
BOARD_NEQ_BRI = 0.008
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)
# 灯带初始化
pixels = neopixel.NeoPixel(board.NEOPIXEL, BOARD_NEO_QTY,brightness=BOARD_NEQ_BRI,auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
# 传感器
sensor_light = analogio.AnalogIn(board.LIGHT)
sensor_temp = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
# 定义颜色序列
brightness_colors = [GREEN, YELLOW, RED]
temperature_colors = [BLUE, YELLOW, RED]
while True:
# 获取环境的亮度和温度
peak_light = simpleio.map_range(sensor_light.value, 2000, 62000, 0, 5)
peak_temp = simpleio.map_range(sensor_temp.temperature, 33, 33.5, 0, 5)
print("light.value:", sensor_light.value)
print("--peak_light ", int(peak_light))
print("temp.value:", sensor_temp.temperature)
print("**peak_temp ", int(peak_temp))
# 右侧灯珠表示 亮度
for i in range(0, 5, 1):
if i <= peak_light:
pixels[i] = GREEN
if peak_light > 2 and i >= 2:
pixels[i] = YELLOW
if peak_light > 3 and i >= 3:
pixels[i] = RED
else:
pixels[i] = OFF
# 左侧灯珠表示 温度
for j in range(9, 4, -1):
if j >= 9 - peak_temp:
pixels[j] = BLUE
if peak_temp > 2 and j <= 7:
pixels[j] = YELLOW
if peak_temp > 3 and j <= 6:
pixels[j] = RED
else:
pixels[j] = OFF
pixels.show()
time.sleep(0.1)
主要逻辑
1. 初始化传感器前的部分,和前面是基本一致
2. 初始化 光线传感器 和 温度传感器
3.1 大循环 中,首先把两个传感器的值 在 范围内映射到 5 个灯珠
3.2 按照2个传感器的值,分别显示在左右两排 NeoPixel灯带
展示
补光灯开启
尾巴
CircuitPython 开发无需 编写大量的 驱动,甚至连针脚都已经被环境定义好,使用起来很方便
基础任务三 :板载LED展示,检测到入侵时,发起声音报警
任务理解
CPX 开发板上虽然有各种传感器,但是 距离传感器并没有出现在开发板上。
所以这个任务,我使用的是环境光传感器A8 来感应物体的接近,
在亮度降低到阈值时,亮红色灯带,蜂鸣器A0 发出警报声音
代码部分
1. 蜂鸣器 speaker.py 【来源 】
import time
import array
import math
import board
import digitalio
from audiocore import RawSample
from audioio import AudioOut
FREQUENCY = 550 # 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
audio = AudioOut(board.SPEAKER)
def make_sound():
sine_wave_sample = RawSample(sine_wave)
# A single sine wave sample is hundredths of a second long. If you set loop=False, it will play
# a single instance of the sample (a quick burst of sound) and then silence for the rest of the
# duration of the time.sleep(). If loop=True, it will play the single instance of the sample
# continuously for the duration of the time.sleep().
audio.play(sine_wave_sample, loop=True) # Play the single sine_wave sample continuously...
time.sleep(1) # for the duration of the sleep (in seconds)
audio.stop() # and then stop.
code.py
import time
import board
import neopixel
import analogio
from speaker import make_sound
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.01, auto_write=False)
pixels.fill((0, 0, 0))
pixels.show()
light = analogio.AnalogIn(board.LIGHT)
while True:
print(light.value)
if light.value < 2000:
print('light.value under 2000')
for i in range(0, 10, 1):
pixels[i] = (255, 0, 0)
pixels.show()
make_sound()
else:
for i in range(0, 10, 1):
pixels[i] = (0, 255, 0)
pixels.show()
time.sleep(0.01)
主要逻辑
1. speaker.py 来自官方案例,主要定义了make_sound 来使用蜂鸣器
2. 主代码中,主要获取环境光传感器值,低于2000的时候,改变 灯珠颜色,并发出警报
展示
请参考展示视频
进阶任务(必做):制作不倒翁
任务理解
展示不倒翁运动过程中的不同灯光效果,这个时候需要用到 板载的三轴运动传感器 (LIS3DH),计算板载姿势,对应到灯珠亮起
import time
import math
import board
import busio
import neopixel
import adafruit_lis3dh
# 初始化I2C接口
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA)
# 初始化LIS3DH传感器
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, address=0x19)
# 初始化Neopixel灯带
num_pixels = 10
pixels = neopixel.NeoPixel(board.NEOPIXEL, num_pixels, brightness=.05, auto_write=False)
def get_tilt_index(x, y):
"""根据传感器数据计算倾斜方向的灯珠索引"""
# 计算倾斜的角度(以度为单位)
angle = math.atan2(y, x) * 180 / math.pi
if angle < 0:
angle += 360
# 将角度映射到12个灯珠上,每个灯珠覆盖30度范围
index = int((angle + 15) // 30) % num_pixels
return index
while True:
# 读取加速度值
x, y, z = lis3dh.acceleration
# 获取倾斜方向的灯珠索引
index = get_tilt_index(x, y)
# 关闭所有灯
pixels.fill((0, 0, 0))
# 点亮对应的灯珠
pixels[index] = (255, 0, 0)
# 更新Neopixel灯带
pixels.show()
# 延时0.2s
time.sleep(0.2)
主要逻辑
1. 初始化 lis3dh 传感器 和 NeoPixel 灯带.
2. 使用计算函数,把三轴数据转化成 角度,然后匹配到10灯珠
使用了12个方向,映射到10颗灯
3. 大循环中读取运动传感器值 并 更新 对应的灯珠
展示
动态请参考展示视频
自选任务 :SH1107 OLDE屏幕使用
任务理解
在下单阶段,差额部分下单了M5的SH1107
因为CPX没有显示模块,让传感器的读值可以更直观
代码部分
import board
import displayio
import terminalio
from adafruit_display_text import label
import adafruit_displayio_sh1107
import gc
import os
import busio
import random
import time
import analogio
import adafruit_thermistor
gc.enable()
# release any currently configured displays
displayio.release_displays()
# Setup I2C
i2c = busio.I2C(board.SCL, board.SDA) # uses board.SCL and board.SDA
display_bus = displayio.I2CDisplay(i2c, device_address=0x3C)
# SH1107 is vertically oriented 64x128
WIDTH = 128
HEIGHT = 64
display = adafruit_displayio_sh1107.SH1107(
display_bus, width=WIDTH, height=HEIGHT, rotation=0
)
splash = displayio.Group()
display.root_group = splash
default_text = " "*7
text_area = label.Label(terminalio.FONT, text=default_text, scale=2, color=0xFFFFFF, x=0, y=10)
display.root_group =text_area
sensor_light = analogio.AnalogIn(board.LIGHT)
sensor_temp = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950)
while True:
gc.collect()
print('mem_free',gc.mem_free())
temp_value = str(round(sensor_temp.temperature,1))
light_value = str(sensor_light.value)
show_value = temp_value + '/' + light_value
# show_value = 'T/L' + '\n' + show_value
text_new= show_value
text_area.text = text_new
time.sleep(1)
主要逻辑
1. 主要部分是传感器读取,细节请参考
2. 头部需要 在lib文件夹中引入 adafruit_display_text 和 adafruit_displayio_sh1107
3. Line 33~42 主要实例化 显示部分,最后在大循环中定时把传感器的值跟新到显示区域的text
展示
对本活动的心得体会(包括意见或建议)
- CPX 开发板小巧可爱,支持传感器丰富,开发方式多样
- CPX的缺点:资源相对紧凑,GPIO接口相对特殊(需要鳄鱼夹线);micro USB 接口略显落伍
- 通过各项任务,更加熟悉了CircuitPython 的易用性(各种针脚几乎不用关系,直接调用传感器的名字就行)
- 任务中I2C的通讯协议比较多,在有已经开发好的驱动库支持下,使用起来比其他通讯协议来说更简单便捷
三、可编译下载的代码
https://download.eeworld.com.cn/detail/disk0/634070
|