331|1

183

帖子

12

TA的资源

一粒金砂(高级)

楼主
 

【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

 

最新回复

最像八爪鱼的八爪鱼     详情 回复 发表于 2024-9-1 18:22
点赞 关注
 
 

回复
举报

6450

帖子

9

TA的资源

版主

沙发
 

最像八爪鱼的八爪鱼  

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表