- 2024-11-14
-
加入了学习《DigiKey 应用说:Raspberry Pi 5 在视频直播中的应用》,观看 Raspberry Pi 5 在视频直播中的应用
-
加入了学习《Follow me第二季第1期》,观看 创意任务二:章鱼哥
- 2024-08-31
-
加入了学习《Follow me第二季第1期》,观看 完整版
-
加入了学习《Follow me第二季第1期》,观看 基础任务三(必做):接近检测
-
加入了学习《Follow me第二季第1期》,观看 创意任务三:触摸钢琴
-
加入了学习《Follow me第二季第1期》,观看 创意任务一:可穿戴装饰——报警器
-
加入了学习《Follow me第二季第1期》,观看 进阶任务(必做):制作不倒翁——摇摇马
-
加入了学习《Follow me第二季第1期》,观看 基础任务二(必做):监测环境温度和光线
-
加入了学习《Follow me第二季第1期》,观看 入门任务(必做):开发环境搭建,板载LED点亮 基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
-
发表了主题帖:
【Follow me第二季第1期】创意任务三:触摸钢琴
本帖最后由 nemon 于 2024-8-31 19:15 编辑
创意任务三原题要求是做“水果钢琴”——通过触摸水果弹奏音乐,并配合灯光效果。我没准备水果,只是靠触摸完成功能,所以只能叫“琴”。
没有水果,做题打折有点不好意思,所以加了个示范功能:按下按键A后,会播放“小星星”这首曲子,并点亮对应的灯。
这次我没有播放文件,而是用官方库的start_tone功能,这个库只要告诉它Hz数,就会播放对应的音调。不用的时候,执行stop_tone就可以停止。
于是代码又是很简单:
from adafruit_circuitplayground import cp
import time
HZ = ( 262,294,330,349,392,440,494)
LT = ( 6,8,9,0,1,3,5)
cp.pixels.fill( ( 0,0,0 ) )
while True:
#break
print( cp.touch_A1,cp.touch_A2,cp.touch_A3,cp.touch_A4,cp.touch_A5,cp.touch_A6 )
if cp.touch_A1:
cp.start_tone( HZ[0] )
cp.pixels[ LT[0] ]= ( 0,255,0 )
elif cp.touch_A2:
cp.start_tone( HZ[1] )
cp.pixels[ LT[1] ]= ( 0,255,0 )
elif cp.touch_A3:
cp.start_tone( HZ[2] )
cp.pixels[ LT[2] ]= ( 0,255,0 )
elif cp.touch_A4:
cp.start_tone( HZ[3] )
cp.pixels[ LT[3] ]= ( 0,255,0 )
elif cp.touch_A5:
cp.start_tone( HZ[4] )
cp.pixels[ LT[4] ]= ( 0,255,0 )
elif cp.touch_A6:
cp.start_tone( HZ[5] )
cp.pixels[ LT[5] ]= ( 0,255,0 )
else:
cp.stop_tone()
cp.pixels.fill( ( 0,0,0 ) )
time.sleep(0.3)
完成效果见视频:
-
发表了主题帖:
【Follow me第二季第1期】创意任务二:章鱼哥
本帖最后由 nemon 于 2024-8-31 19:14 编辑
创意任务二的任务是做一个章鱼哥,章鱼哥的触角根据环境声音的大小舒展或者收缩。
为了让触角的舒张和收缩幅度相同,我没有用360度舵机,改用ULN2003驱动的28BYJ48步进电机。
为了能操作省事,先写了一个文件Stepper28BYJ48_ULN2003.py,里面定义了操作步进电机的类。
初始化的时候,把控制的引脚传进去,之后每次走一步,都只要传方向和速度。
import board,digitalio
import time
'''
EXAMPLE:
import Stepper28BYJ48_ULN2003
stepper = Stepper28BYJ48_ULN2003( board.A3 , board.A2 , board.A1 , board.A0 )
for i in range(4076):
stepper.steper_one_step(1,100000)
'''
class Stepper28BYJ48_ULN2003:
_DELAY_T = 0.15
_POS_ARRY =(
(False , True ,True ,True ),# A
(False , False ,True ,True ),# AB
(True , False ,True ,True ),# B
(True , False ,False ,True ),# BC
(True , True ,False ,True ),# C
(True , True ,False ,False),# CD
(True , True ,True ,False),# D
(False , True ,True ,False),# DA
)
# init
def __init__(self,pin_a,pin_b,pin_c,pin_d):
#self.speed = 1000
#self.direction = 1
self.pos = -1
self.pins = [ digitalio.DigitalInOut(p) for p in (pin_a,pin_b,pin_c,pin_d) ]
for p in self.pins:
p.switch_to_output()
# step
def steper_one_step(self,d=1,speed=1000):
self.pos += d #self.direction
self.pos %= len(self._POS_ARRY)
print(self.pos)
#ctr_a.value , ctr_b.value , ctr_c.value , ctr_d.value = self._POS_ARRY[pos]
for i in range(len(self.pins)):
self.pins[i].value = self._POS_ARRY[self.pos][i]
#time.sleep(self._DELAY_T/self.speed)
time.sleep(self._DELAY_T/abs(speed))
检测声音大小,可以用audiobusio库,喂给它一个缓冲区,就可以返回一系列模拟值。
精简了一下官网代码,就可以实现检测声音大小:
import audiobusio,board,array,math,time
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16)
samples = array.array("H", [0] * 320)
while True:
mic.record(samples, len(samples))
minbuf = int( sum(samples) / len(samples) )
samples_sum = sum([ float(sample - minbuf) * (sample - minbuf) for sample in samples] )
print( sum(samples) , minbuf , math.sqrt(samples_sum / len(samples)) )
time.sleep(0.5)
章鱼触手收回去之后,按一下开关,就会又伸展开来,因为用的是步进电机,所以只要没有失步,反向相同的步数后,会回到原位。
最后完整的代码是这样的:
import board,time
from Stepper28BYJ48_ULN2003 import Stepper28BYJ48_ULN2003 as st
import audiobusio,board,array,math
import digitalio
from adafruit_circuitplayground import cp
N = 1/4
stepper = st( board.A3 , board.A2 , board.A1 , board.A6 )
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16)
samples = array.array("H", [0] * 320)
button = digitalio.DigitalInOut(board.A5)
button.switch_to_input(pull=digitalio.Pull.DOWN)
while True:
mic.record(samples, len(samples))
minbuf = int( sum(samples) / len(samples) )
samples_sum = sum([ float(sample - minbuf) * (sample - minbuf) for sample in samples] )
val = math.sqrt(samples_sum / len(samples))
print( sum(samples) , minbuf , val )
if val > 300 :
print('danger!')
cp.play_file('danger.wav')
for i in range(4076 * N):
if i%100==0:
print(i,end=' :-> ')
stepper.steper_one_step(-1,100000)
time.sleep(2)
while button.value :
time.sleep(0.05)
print('safe.')
cp.play_file('shoping.wav')
for i in range(4076 * N):
if i%100==0:
print(i,end=' :-> ')
stepper.steper_one_step( 1,100000)
time.sleep(2)
time.sleep(0.1)
章鱼的身体是用杯子改的,把杯壁翦成8条,折叠打孔。然后把步进电机固定在杯子底部,在轴上装一个瓶子盖,在瓶盖周围打上8个孔,用棉线穿过空之后,再穿过折叠的杯壁的孔,绕到触手末端,就完成了。
运行效果是这样的:
-
发表了主题帖:
【Follow me第二季第1期】创意任务一:有创意的可穿戴装饰
本帖最后由 nemon 于 2024-8-31 19:10 编辑
创意任务一的要求是,做一个可穿戴装饰。
我的想法是做一个报警器:平时显示彩虹色,按下A键进入报警模式红蓝交替闪烁并播放报警音,直到按B键恢复正常。
from adafruit_circuitplayground import cp
import time
i = 0
while True:
if cp.button_a :
cp.pixels.brightness = 1
while not cp.button_b :
for j in range(5):
cp.pixels[j+0]=( 255,0,0 )
cp.pixels[j+5]=( 0,0,255 )
for j in range(1):
cp.play_file('alert.wav')
for j in range(5):
cp.pixels[j+0]=( 0,0,255 )
cp.pixels[j+5]=( 255,0,0 )
for j in range(1):
cp.play_file('alert.wav')
else:
#cp.pixels.fill( ( 0,0,0 ) )
cp.pixels.brightness = 0.2
for j in range(10):
cp.pixels[j]=( 25*(i%10), 0+25*((j-i)%10) , 255-25*((j-i)%10) )
i = (i+1)%10
time.sleep(0.01)
运行效果见视频:
-
发表了主题帖:
【Follow me第二季第1期】进阶任务:制作不倒翁
本帖最后由 nemon 于 2024-8-31 19:08 编辑
进阶任务的要求是——制作不倒翁,展示不倒翁运动过程中的不同灯光效果
找了一个西点盒,用泡沫塑料剪了马头和马尾,插到盒子上,然后给盒子里装上重物,不倒翁“摇摇马”就做好了。
Adafruit Circuit Playground Express上有三轴加速度传感器,用acceleration就可以读出x、y、z的加速度。
我把3轴x、y、z的平方和加起来,估算当前的总体加速度。因为有重力加速度,所以会有个基准的值,我也不管基准是多少了,只要这个平方和大于110,就认为开始晃了。
这次推荐购买360度舵机,我拿来给“摇摇马”做背景了——当马被动的摇起来,舵机也会带动背景旋转,炫彩灯亮起,同时播放这个声音(强烈推荐非上班时间听):
控制舵机,用pwm就可以,要引入pwmio库。代码如下:
from adafruit_circuitplayground import cp
import board,pwmio,time
pwm = pwmio.PWMOut(board.A1, frequency=50, duty_cycle=0)
def servo360_go(diriction=0,speed=0):
if diriction == 0 :
pwm.duty_cycle=0
elif diriction>0:
pwm.duty_cycle = 5000 + min(diriction *speed , 4500)
else:
pwm.duty_cycle = 5000 + max(diriction *speed , -4500)
servo360_go(0)
while True:
x, y, z = cp.acceleration
v = x*x+y*y+z*z
print("x:%0.4f,y:%0.4f,z:%0.4f => %0.4f" % (x, y, z , v ))
servo360_go(0)
if v > 110:
servo360_go(-25,20)
for j in range(10):
cp.pixels[j]=( 0, 0+25*j , 255-25*j )
cp.play_file('grandpa.wav')
servo360_go(25,40)
time.sleep(0.5)
cp.pixels.fill( (0,0,0) )
time.sleep(0.2)
运行效果见视频:
-
发表了主题帖:
【Follow me第二季第1期】基础任务三:接近检测
本帖最后由 nemon 于 2024-8-31 19:07 编辑
基础任务三的要求是:设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警。
开始的时候,我看了下视频培训的提示,说是可以用红外传感器的库来实现。可是我看了下ir库,发现功能是编解码。又看到有的网友用红外发射后再读取的方法,试了下效果不太好。于是就改用超声波来做。
超声波模块的用法是读取返回波的用时,然后乘以声速,计算出距离。这种方式也会受空气温度密度的影响,但是比红外准多了。
用的时候只要用VOUT供5V电,再占用2个IO就可以了:
import board,digitalio
import time
from adafruit_circuitplayground import cp
echo_pin = digitalio.DigitalInOut(board.A1)
trigger_pin = digitalio.DigitalInOut(board.A2)
trigger_pin.switch_to_output()
def get_distance():
trigger_pin.value = True
time.sleep(0.00001)
trigger_pin.value = False
while echo_pin.value == False:
pass
start_time = time.monotonic()
while echo_pin.value == True:
pass
end_time = time.monotonic()
elapsed_time = end_time - start_time
distance = elapsed_time * 34300
return distance
while True:
distance_cm = get_distance()
m = distance_cm / 100
inches = distance_cm / 254
print(f"Distance: {m}m | {distance_cm} cm")
cp.pixels.fill( (0,0,0) )
if distance_cm <20:
cp.pixels.fill( (255,0,0) )
cp.play_file('distance.wav')
time.sleep(0.5)
当距离小于20cm时,亮起红灯,并播放“注意保持距离”。
播放用的是标准库的play_file方法。按照官网的介绍 (https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/play-file),声音文件支持PCM 16-bit 单声道 WAV格式,采样率22KHz。于是用goldwave5做了一下转换。顺便说一下,官网介绍的转换工具没goldwave5好用。
最后效果是这样的:
-
发表了主题帖:
【Follow me第二季第1期】基础任务二:监测环境温度和光线
本帖最后由 nemon 于 2024-8-31 19:06 编辑
基础任务二的要求是“监测环境温度和光线,通过板载LED展示舒适程度”。
依旧使用adafruit_circuitplayground库,通过temperature和light可以读到温度和亮度,然后转换一下。
我的想法是,用炫彩led的亮度来表示环境亮度、用点亮的数量来表示温度。
代码也简单:
import time,math
from adafruit_circuitplayground import cp as my_cp
def task_2_temperature_light():
LED_CNT = 10
t = my_cp.temperature
l = my_cp.light
b = ( 1-min(255,l)/255 )*0.5
b = 0.3 * min( math.log(l)/math.log(10) ,2 )/2
n = min(LED_CNT, int( LED_CNT*t/50 ) )
my_cp.pixels.brightness = b
for i in range(LED_CNT):
if i>n:
my_cp.pixels[i+(10-LED_CNT)]=( 0,0,0 )
else:
my_cp.pixels[i+(10-LED_CNT)]=( 25*n,0,255-10*n )
time.sleep(0.1)
#print( ','.join([str(x) for x in [t,l,b,n]]))
print( {'t':t,'l':l,'b':b,'n':n})
while True:
task_2_temperature_light()
但是效果不太明显,于是把数据打出来看了下,发现温度亮度变化不大,所以现象不够明显。
-
发表了主题帖:
【Follow me第二季第1期】入门任务、基础任务一:点灯
本帖最后由 nemon 于 2024-8-31 19:06 编辑
拿到 Adafruit Circuit Playground Express 之后。首先上官网(https://learn.adafruit.com/adafruit-circuit-playground-express)转悠了一圈,就知道怎么上手了。
先刷个最新版的固件——所谓的拼音版,输出的竟然真的是拼音,看着实在累,所以就刷成英文版了:
然后装了个MU ( https://download.eeworld.com.cn/detail/nemon/634235 )
入门任务要求“开发环境搭建,板载LED点亮”,基础任务要求“控制板载炫彩LED,跑马灯点亮和颜色变换”,于是到板子上找资源。
Adafruit Circuit Playground Express上有1颗红色led,还有10颗三色全彩led,够用了。
官方有个 adafruit_circuitplayground 库,封装了板上的资源,led用red_led就能引用,炫彩灯用pixels来使用。
所以写出的代码很简单:
import time
from adafruit_circuitplayground import cp as my_cp
my_cp.pixels.brightness=0.1
while True:
for i in range(100):
for j in range(10):
my_cp.pixels[j]=( 25*(i%10), 0+25*((j-i)%10) , 255-25*((j-i)%10) )
if i%50==0:
my_cp.red_led = (i==0)
time.sleep(0.01)
print(i,end=' ')
CircuitPython的约定是code.py会自动执行,所以把上边的文件保存为code.py。
这里为了演示led,炫彩灯每转5圈改变一下亮灭。
效果是这样的:
-
加入了学习《Follow me第二季第1期》,观看 器材介绍
-
发表了主题帖:
【Follow me第二季第1期】任务提交:摇摇马、章鱼哥等
本帖最后由 nemon 于 2024-9-1 09:36 编辑
有幸参加了Follow me第二季第1期活动,大致把Adafruit Circuit Playground Express的主要功能都试了一下。按照活动要求,完成了全部任务。
一 、短视频
完整视频在 https://training.eeworld.com.cn/video/40818
视频分集说明:
说明
视频地址
帖子地址
器材介绍,展示任务所用全部物料实物
https://training.eeworld.com.cn/video/40809
入门任务(必做):开发环境搭建,板载LED点亮
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
https://training.eeworld.com.cn/video/40810
https://bbs.eeworld.com.cn/thread-1292109-1-1.html
基础任务二(必做):监测环境温度和光线
https://training.eeworld.com.cn/video/40811
https://bbs.eeworld.com.cn/thread-1292110-1-1.html
基础任务三(必做):接近检测
https://training.eeworld.com.cn/video/40812
https://bbs.eeworld.com.cn/thread-1292111-1-1.html
进阶任务(必做):制作不倒翁——摇摇马
https://training.eeworld.com.cn/video/40813
https://bbs.eeworld.com.cn/thread-1292115-1-1.html
创意任务一:可穿戴装饰——报警器
https://training.eeworld.com.cn/video/40814
https://bbs.eeworld.com.cn/thread-1292116-1-1.html
创意任务二:章鱼哥
https://training.eeworld.com.cn/video/40815
https://bbs.eeworld.com.cn/thread-1292117-1-1.html
创意任务三:触摸钢琴
https://training.eeworld.com.cn/video/40816
https://bbs.eeworld.com.cn/thread-1292119-1-1.html
以上合集在 https://training.eeworld.com.cn/course/68616
二、任务实现详情
1:器材介绍
按照活动要求和我的脑补,我购买了 Adafruit Circuit Playground Express 开发板、360度舵机、28BYJ-48步进电机和驱动器:
后来为了测距,又增加了超声波传感器。
这次把所有的项目都做了所以每个项目的介绍(项目简介;全部物料清单,含物料名称、实物图片;设计思路)都放在下面分别说明。
2:入门任务、基础任务一
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
我把入门任务和基础任务一放在一起做了。入门任务的要求是“开发环境搭建,板载LED点亮”,基础任务一的要求是“控制板载炫彩LED,跑马灯点亮和颜色变换”。
分析了一下,只需要用Adafruit Circuit Playground Express一块板子就可以完成。
板子上资源有1颗红色led,还有10颗三色全彩led,够用了。
官方有个 adafruit_circuitplayground 库,封装了板上的资源,led用red_led就能引用,炫彩灯用pixels来使用。
(2)软件流程图
(3)主要代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
import time
from adafruit_circuitplayground import cp as my_cp
my_cp.pixels.brightness=0.1
while True:
for i in range(100):
for j in range(10):
my_cp.pixels[j]=( 25*(i%10), 0+25*((j-i)%10) , 255-25*((j-i)%10) )
if i%50==0:
my_cp.red_led = (i==0)
time.sleep(0.01)
print(i,end=' ')
炫彩灯一直在轮流变色每转5圈,红色led改变一下亮灭。
图片没法演示动态效果,看视频:
3:基础任务二:监测环境温度和光线
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
基础任务二的要求是“监测环境温度和光线,通过板载LED展示舒适程度”。
Adafruit Circuit Playground Express板载资源丰富,温度、光线传感器都是现成的,继续用炫彩led。
软件依旧使用adafruit_circuitplayground库,通过temperature和light可以读到温度和亮度,然后转换一下。
我的想法是,用炫彩led的亮度来表示环境亮度、用点亮的数量来表示温度。
(2)软件流程图
(3)任务对应的主要代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
import time,math
from adafruit_circuitplayground import cp as my_cp
def task_2_temperature_light():
LED_CNT = 10
t = my_cp.temperature
l = my_cp.light
b = ( 1-min(255,l)/255 )*0.5
b = 0.3 * min( math.log(l)/math.log(10) ,2 )/2
n = min(LED_CNT, int( LED_CNT*t/50 ) )
my_cp.pixels.brightness = b
for i in range(LED_CNT):
if i>n:
my_cp.pixels[i+(10-LED_CNT)]=( 0,0,0 )
else:
my_cp.pixels[i+(10-LED_CNT)]=( 25*n,0,255-10*n )
time.sleep(0.1)
#print( ','.join([str(x) for x in [t,l,b,n]]))
print( {'t':t,'l':l,'b':b,'n':n})
while True:
task_2_temperature_light()
把数据打出来看了下,发现温度亮度变化不大,所以现象不够明显。
效果见视频:
4:基础任务三:接近检测
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
基础任务三的要求是:设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警。
开始的时候,我看了下视频培训的提示,说是可以用红外传感器的库来实现。按这个思路,只要用Adafruit Circuit Playground Express板就够了。可是我看了下irremot库,感觉功能主要是编解码。又看到有的网友用红外发射后再读取的方法,不知是不是我这太热了,试了下效果不太好。于是决定改用超声波来做。那么除了Adafruit Circuit Playground Express板,还得用一个HC-SR04超声波模块。
超声波模块的用法是读取返回波的用时,然后乘以声速,计算出距离。这种方式也会受空气温度密度的影响,但是比红外准多了。
用的时候只要用VOUT供5V电,再占用2个IO就可以了:
(2)软件流程图
(3)任务对应的主要代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
import board,digitalio
import time
from adafruit_circuitplayground import cp
# 超声波传感器连接到的引脚
echo_pin = digitalio.DigitalInOut(board.A1)
trigger_pin = digitalio.DigitalInOut(board.A2)
trigger_pin.switch_to_output()
def get_distance():
# 将trigger引脚设置为高电平至少10微秒来发送超声波
trigger_pin.value = True
time.sleep(0.00001)
trigger_pin.value = False
# 等待回声(echo)引脚变为高电平,这表示超声波已经发出
while echo_pin.value == False:
pass
# 记录超声波开始反弹时的时间
start_time = time.monotonic()
# 等待回声(echo)引脚变为低电平,这表示超声波反弹回来了
while echo_pin.value == True:
pass
# 记录超声波反射回来时的时间
end_time = time.monotonic()
# 计算超声波的往返时间,并将其转换为厘米
elapsed_time = end_time - start_time
distance = elapsed_time * 34300
return distance
while True:
# 读取距离并打印出来
distance_cm = get_distance()
m = distance_cm / 100
inches = distance_cm / 254
print(f"Distance: {m}m | {distance_cm} cm")
cp.pixels.fill( (0,0,0) )
if distance_cm <20:
cp.pixels.fill( (255,0,0) )
cp.play_file('distance.wav')
time.sleep(0.5)
超声波模块测距的代码,写了详细注释。
功能上的逻辑是当距离小于20cm时,亮起红灯,并播放“注意保持距离”。
这里补充说明一下播放声音文件,用的是标准库的play_file方法。按照官网的介绍 (https://learn.adafruit.com/circuitpython-made-easy-on-circuit-playground-express/play-file),声音文件支持PCM 16-bit 单声道 WAV格式,采样率22KHz。于是用goldwave5做了一下转换。
运行起来后,超声波模块指向上方,到房顶有好几米,所以不会报警。当把手挡到超声波模块上时,灯亮、播放“注意保持距离”的声音,效果如下:
演示效果见视频:
5:进阶任务:制作不倒翁——摇摇马
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
进阶任务的要求是——制作不倒翁,展示不倒翁运动过程中的不同灯光效果。
Adafruit Circuit Playground Express上有三轴加速度传感器,再加个360度舵机就可以了。
为啥用到了舵机呢?不知为啥,一下就想到了摇摇车“爸爸的爸爸是爷爷”那个魔性BGM,然后就想再给装饰一下。时间和材料都不够折腾出旋转木马的,于是搞个低配版,只旋转背景得了。
舵机都是靠占空比控制的,只不过360度舵机收到占空比后,不是转到固定角度,而是以不同速度连续旋转。那么就会有一个表示“静止”的占空比,低于或高于它,就会向不同方向转动,离得越远,转的越快。
找了一个西点盒,用泡沫塑料剪了马头和马尾,插到盒子上,然后给盒子里装上重物,不倒翁“摇摇马”就做好了。
(2)软件流程图
(3)任务代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
from adafruit_circuitplayground import cp
import board,pwmio,time
pwm = pwmio.PWMOut(board.A1, frequency=50, duty_cycle=0)
def servo360_go(diriction=0,speed=0):
if diriction == 0 :
pwm.duty_cycle=0
elif diriction>0:
pwm.duty_cycle = 5000 + min(diriction *speed , 4500)
else:
pwm.duty_cycle = 5000 + max(diriction *speed , -4500)
t=0
servo360_go(0)
while True:
x, y, z = cp.acceleration
v = x*x+y*y+z*z
print("x:%0.4f,y:%0.4f,z:%0.4f => %0.4f" % (x, y, z , v ))
servo360_go(0)
if v > 110:
servo360_go(-25,20)
for j in range(10):
cp.pixels[j]=( 0, 0+25*j , 255-25*j )
cp.play_file('grandpa.wav')
servo360_go(25,40)
time.sleep(0.5)
cp.pixels.fill( (0,0,0) )
time.sleep(0.2)
代码中,servo360_go就是用来通过调整pwm改变舵机运动的函数。先使用三轴加速度传感器,用acceleration就可以读出x、y、z的加速度。再把3轴x、y、z的平方和加起来,估算当前的总体加速度。因为有重力加速度,所以会有个基准的值,我也不管基准是多少了,只要这个平方和大于110,就认为开始晃了。然后转背景、亮灯、播放BGM。效果如图:
当然,能动的制作效果还得看视频:
6:创意任务一:可穿戴装饰——报警器
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
创意任务一的要求是,做一个可穿戴装饰。
我的想法是做一个报警器:平时显示彩虹色,按下A键进入报警模式红蓝交替闪烁并播放报警音,直到按B键恢复正常。
按这个功能分析,只需要用Adafruit Circuit Playground Express一块板子就可以完成,不过我还是加了个挂绳,2万万不能装,B还是要装一下的。
(2)软件流程图
(3)任务代码、功能展示及图文说明
from adafruit_circuitplayground import cp
import time
i = 0
while True:
if cp.button_a :
cp.pixels.brightness = 1
while not cp.button_b :
for j in range(5):
cp.pixels[j+0]=( 255,0,0 )
cp.pixels[j+5]=( 0,0,255 )
for j in range(1):
cp.play_file('alert.wav')
for j in range(5):
cp.pixels[j+0]=( 0,0,255 )
cp.pixels[j+5]=( 255,0,0 )
for j in range(1):
cp.play_file('alert.wav')
else:
#cp.pixels.fill( ( 0,0,0 ) )
cp.pixels.brightness = 0.2
for j in range(10):
cp.pixels[j]=( 25*(i%10), 0+25*((j-i)%10) , 255-25*((j-i)%10) )
i = (i+1)%10
time.sleep(0.01)
运行起来效果如同设计的,平时正常显示炫彩,按下a键就进入警报模式:
完成效果见视频:
7:创意任务二:章鱼哥
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
创意任务二的任务是做一个章鱼哥,要求章鱼哥的触角根据环境声音的大小舒展或者收缩。
为了让触角的舒张和收缩幅度相同,是用ULN2003驱动的28BYJ48步进电机来实现的。Adafruit Circuit Playground Express上有麦克风,但是这次只用它来测音量。章鱼触手收回去之后,需要再伸展开来,所以还需要用一个开关。
章鱼的身体是用杯子改的,把杯壁翦成8条,折叠打孔。然后把步进电机固定在杯子底部,在轴上装一个瓶子盖,在瓶盖周围打上8个孔,用棉线穿过空之后,再穿过折叠的杯壁的孔,绕到触手末端,就完成了。
(2)软件流程图
(3)各任务对应的主要代码片段、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
为了能操作ULN2003驱动28BYJ48步进电机省事,先写了一个文件Stepper28BYJ48_ULN2003.py,里面定义了操作步进电机的类。
初始化的时候,把控制的引脚传进去,之后每次走一步,都只要传方向和速度。
import board,digitalio
import time
class Stepper28BYJ48_ULN2003:
_DELAY_T = 0.15
_POS_ARRY =(
(False , True ,True ,True ),# A
(False , False ,True ,True ),# AB
(True , False ,True ,True ),# B
(True , False ,False ,True ),# BC
(True , True ,False ,True ),# C
(True , True ,False ,False),# CD
(True , True ,True ,False),# D
(False , True ,True ,False),# DA
)
# init
def __init__(self,pin_a,pin_b,pin_c,pin_d):
#self.speed = 1000
#self.direction = 1
self.pos = -1
self.pins = [ digitalio.DigitalInOut(p) for p in (pin_a,pin_b,pin_c,pin_d) ]
for p in self.pins:
p.switch_to_output()
# step
def steper_one_step(self,d=1,speed=1000):
self.pos += d #self.direction
self.pos %= len(self._POS_ARRY)
print(self.pos)
#ctr_a.value , ctr_b.value , ctr_c.value , ctr_d.value = self._POS_ARRY[pos]
for i in range(len(self.pins)):
self.pins[i].value = self._POS_ARRY[self.pos][i]
#time.sleep(self._DELAY_T/self.speed)
time.sleep(self._DELAY_T/abs(speed))
检测声音大小,可以用audiobusio库,喂给它一个缓冲区,就可以返回一系列模拟值。官网代码套了2层函数,太罗嗦了,精简了一下,用取样缓冲区模拟量计算归一化均值,就能检测声音大小。章鱼触手收回去之后,需要再伸展开来,所以用digitalio来读取开关。主程序如下:
import board,time
from Stepper28BYJ48_ULN2003 import Stepper28BYJ48_ULN2003 as st
import audiobusio,board,array,math
import digitalio
from adafruit_circuitplayground import cp
N = 1/4
stepper = st( board.A3 , board.A2 , board.A1 , board.A6 )
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16)
samples = array.array("H", [0] * 320)
button = digitalio.DigitalInOut(board.A5)
button.switch_to_input(pull=digitalio.Pull.DOWN)
while True:
mic.record(samples, len(samples))
minbuf = int( sum(samples) / len(samples) )
samples_sum = sum([ float(sample - minbuf) * (sample - minbuf) for sample in samples] )
val = math.sqrt(samples_sum / len(samples))
print( sum(samples) , minbuf , val )
if val > 300 :
print('danger!')
cp.play_file('danger.wav')
for i in range(4076 * N):
if i%100==0:
print(i,end=' :-> ')
stepper.steper_one_step(-1,100000)
time.sleep(2)
while button.value :
time.sleep(0.05)
print('safe.')
cp.play_file('shoping.wav')
for i in range(4076 * N):
if i%100==0:
print(i,end=' :-> ')
stepper.steper_one_step( 1,100000)
time.sleep(2)
time.sleep(0.1)
组装起来是这样的:
运行效果看视频吧。
8:创意任务三:触摸钢琴
(1)任务/项目介绍(需要包含项目简介;全部物料清单,含物料名称、实物图片;设计思路)
创意任务三原题要求是做“水果钢琴”——通过触摸水果弹奏音乐,并配合灯光效果。我没准备水果,只是靠触摸完成功能,所以只能叫“琴”。
因为没有水果,只需要用Adafruit Circuit Playground Express一块板子就可以完成。
利用官方adafruit_circuitplayground.cp来点灯、检测触摸、放音乐——其实就是按某个频率震荡。
(2)软件流程图
(3)任务代码、功能展示及图文说明(每个任务需要包含至少一张对应的实物图)
除了当琴弹,还加了个示范功能:按下按键A后,会播放“小星星”这首曲子,并点亮对应的灯,所以要定义乐谱和时长。
还要给每个音调定义好频率,放音的时候用官方库的start_tone功能。这个库只要告诉它Hz数,就会播放对应的音调。不用的时候,执行stop_tone就可以停止。
from adafruit_circuitplayground import cp
import time
HZ = ( 262,294,330,349,392,440,494)
LT = ( 6,8,9,0,1,3,5)
MUSIC_LITTLE_STAR_M = tuple( int(c) for c in '115566544332215544332554433211556654433221' )
MUSIC_LITTLE_STAR_L = tuple( int(c) for c in '111111211111121111112111111211111121111112' )
cp.pixels.fill( ( 0,0,0 ) )
while True:
#break
print( cp.touch_A1,cp.touch_A2,cp.touch_A3,cp.touch_A4,cp.touch_A5,cp.touch_A6 ,cp.button_a)
if cp.button_a:
for i in range(len(MUSIC_LITTLE_STAR_M)):
cp.pixels[ LT[MUSIC_LITTLE_STAR_M[i]-1] ]= ( 255,0,255 )
cp.start_tone( HZ[MUSIC_LITTLE_STAR_M[i]-1] )
time.sleep(0.25*MUSIC_LITTLE_STAR_L[i])
cp.pixels[ LT[MUSIC_LITTLE_STAR_M[i]-1] ]= ( 0,0,0 )
cp.stop_tone()
if cp.touch_A1:
cp.start_tone( HZ[0] )
cp.pixels[ LT[0] ]= ( 0,255,0 )
elif cp.touch_A2:
cp.start_tone( HZ[1] )
cp.pixels[ LT[1] ]= ( 0,255,0 )
elif cp.touch_A3:
cp.start_tone( HZ[2] )
cp.pixels[ LT[2] ]= ( 0,255,0 )
elif cp.touch_A4:
cp.start_tone( HZ[3] )
cp.pixels[ LT[3] ]= ( 0,255,0 )
elif cp.touch_A5:
cp.start_tone( HZ[4] )
cp.pixels[ LT[4] ]= ( 0,255,0 )
elif cp.touch_A6:
cp.start_tone( HZ[5] )
cp.pixels[ LT[5] ]= ( 0,255,0 )
else:
cp.stop_tone()
cp.pixels.fill( ( 0,0,0 ) )
time.sleep(0.3)
这是触碰A5的效果。
完成效果见视频:
9:对本活动的心得体会(包括意见或建议)
这次参加Follow me第二季第1期活动,大致把Adafruit Circuit Playground Express的主要功能都试了一下。按照活动要求,完成了全部任务。对Circuit的python也有了更多认识。学习过程中看到了网友们很多脑洞大开的技巧,受益良多。期间试了一下用arduino编程,准备今后再抽时间试试图形化编程工具。
感谢主办方DigiKey、EEworld,以及各位帮助过我的同学,谢谢!
三、可编译下载的代码
https://download.eeworld.com.cn/detail/nemon/634238
代码说明:
入门任务(必做):开发环境搭建,板载LED点亮
基础任务一(必做):控制板载炫彩LED,跑马灯点亮和颜色变换
code_task_A01_led_blink.py
基础任务二(必做):监测环境温度和光线
code_task_A02_temperature_light.py
基础任务三(必做):接近检测
code_task_A03_distence_alert.py
进阶任务(必做):制作不倒翁——摇摇马
code_task_B01_horse.py
创意任务一:可穿戴装饰——报警器
code_task_C01_alert.py
创意任务二:章鱼哥
code_task_C02_octopus.py
创意任务三:钢琴
code_task_C03_piano.py
-
上传了资料:
Follow me第二季第1期 全部代码
-
上传了资料:
MuEditor 1.2.0(操作系统win64)