项目介绍
本项目基于STEP Pico嵌入式系统学习平台完成音乐氛围灯,实现了播放音乐、切换灯效等功能。
硬件介绍本项目所用硬件为基于STEP Pico的嵌入式系统学习平台,配置如下图:
本项目主要使用了如下硬件:
- 2个按键输入
- 12个WS2812B RGB三色灯
- 1个128*64 OLED显示屏
- 1个蜂鸣器
- 1个可调电位计
- Thonny:用于代码编写、调试及上传
- ampy:用于将资源文件上传到板卡中
- 音乐播放:利用awesome-micropython-lib代码库和PicoAudioPWM代码库提供的文件,通过PWM生成不同频率、持续时间不同的音调,驱动蜂鸣器播放
.wav
格式的音乐。 - 氛围彩灯:利用eetree-mpy-lecture-code代码库中的
ws2812b.py
文件,利用板上的12个彩色LED灯,实现不同的显示效果,内置三种灯效。通过按键改变灯效模式全局变量led_mode
,实现切换灯效的功能,同时通过ADC采集电位器电压值来调节彩灯亮度。 - 按键控制:按键按下时产生下降沿信号,触发外部中断,callback函数对按键按下事件进行处理,改变控制音乐播放和灯效的全局变量,每次触发中断后设定最快下次触发中断时间,实现消抖功能。
- 显示说明:利用eetree-mpy-lecture-code代码库中的
ssd1306.py
文件,在OLED屏幕上对操作进行简要说明。 - 多线程控制:利用
_thread
库,给音乐播放和彩灯控制分别分配线程,实现同步运行。
- 音乐播放:利用板上的蜂鸣器播放音乐
- 氛围彩灯:利用板上的12个彩色LED灯,实现不同的显示效果,内置三种灯效
- 亮度调节:利用板上的电位器调节彩色LED亮度
- 按键控制:利用板上的按键控制音乐的播放和灯效的切换
- 显示说明:利用板上的OLED显示屏显示简要说明
利用awesome-micropython-lib代码库和PicoAudioPWM代码库提供的文件,通过PWM生成不同频率、持续时间不同的音调,驱动蜂鸣器播放.wav
格式的音乐。
from wavePlayer import wavePlayer
import machine
def music_play():
lock.acquire()
pwm = machine.PWM(machine.Pin(19))
global k1_pressed
while True:
if k1_pressed:
player = wavePlayer()
player.play("/tkmyjx.wav")
k1_pressed = 0
氛围彩灯
利用eetree-mpy-lecture-code代码库中的ws2812b.py
文件,利用板上的12个彩色LED灯,实现不同的显示效果,内置三种灯效。通过按键改变灯效模式全局变量led_mode
,实现切换灯效的功能,同时通过ADC采集电位器电压值来调节彩灯亮度。
import ws2812b
import machine
import time
def led_show():
adc = machine.ADC(28)
i = 0
jj = 0
while True:
brightness = adc.read_u16()/65535 #通过ADC采集的电位器电压值来调节彩灯亮度
if led_mode == 0:
i = (i+15)%255
for ii in range(12):
pos = int(ii*256/12-i)%255
ws2812b.set_24bit_rgb(ii, ws2812b.wheel(pos), brightness)
time.sleep_ms(1)
elif led_mode == 1:
jj = (jj+1)%12
ws2812b.google_home(jj, brightness)
elif led_mode == 2:
jj = (jj+1)%12
ws2812b.amazon_alexa(jj, brightness)
按键控制
按键按下时产生下降沿信号,触发外部中断,callback函数对按键按下事件进行处理,改变控制音乐播放和灯效的全局变量,每次触发中断后设定最快下次触发中断时间,实现消抖功能。
import machine
import time
k1_pressed = 0
led_mode = 0
next_call_time = 0
def k1_callback(pin):
global k1_pressed
k1_pressed = 1
k1 = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
k1.irq(trigger=machine.Pin.IRQ_FALLING, handler=k1_callback)
def k2_callback(pin):
global led_mode, next_call_time
if time.ticks_diff(time.ticks_ms(), next_call_time) > 0:
next_call_time = time.ticks_add(time.ticks_ms(), 20)
led_mode += 1
led_mode %= 3
k2 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
k2.irq(trigger=machine.Pin.IRQ_FALLING, handler=k2_callback)
显示说明
利用eetree-mpy-lecture-code代码库中的ssd1306.py
文件,在OLED屏幕上显示两行文字,对操作进行简要说明。
from ssd1306 import SSD1306_SPI
import machine
def oled_show():
spi = machine.SPI(1, 100000, mosi = machine.Pin(11), sck = machine.Pin(10))
oled = SSD1306_SPI(128, 64, spi, machine.Pin(9), machine.Pin(8), machine.Pin(29))
oled.text("K1: Play music",8,20)
oled.text("K2: Change LED",8,36)
oled.show()
多线程控制
利用_thread
库,双线程分别分配给音乐播放和彩灯控制,实现同步运行。
import _thread
lock = _thread.allocate_lock()
oled_show()
_thread.start_new_thread(music_play,())
led_show()
遇到主要难题及解决方法
调试多线程过程中意外导致整个板卡卡死,无法连接电脑。
通过烧录擦除flash的.uf2
固件后,重新烧录.uf2
启动文件解决。
- 程序在跑灯效3时有时会卡死,导致整个系统死机,目前已较长时间未出现该问题,可能是之前调试过程中的小失误。
_thread
库的使用还不太熟练,特别是对于线程锁的使用,目前程序是误打误撞调试到能够成功运行,调试过程中还导致整个板卡卡死,无法连接电脑。- 还不太了解
wavePlayer
库具体的工作原理,在其定义中使用2号引脚作为左声道,3号引脚作为右声道,4号引脚作为地,以此连接双声道耳机输出,实际使用中发现不应更改这几个引脚定义,而需要在主程序中初始化19号引脚的PWM输出,即可使用。class wavePlayer: def __init__(self,leftPin=Pin(2),rightPin=Pin(3), virtualGndPin=Pin(4), dma0Channel=10,dma1Channel=11,dmaTimer=3,pwmBits=10): #left channel Pin needs to be an even GPIO Pin number #right channel Pin needs to be left channel + 1
- 增加对音频的频谱分析功能,通过OLED屏幕或彩灯来动态展示音乐图谱,增强互动性。
- 可以增加电池,提高模块的便携性。
用MicroPython开发ESP32-文件传输工具-ampy_晨之清风的博客-CSDN博客
GitHub - joeky888/awesome-micropython-lib: Awesome MicroPython libs
GitHub - danjperron/PicoAudioPWM:带有 8KHz 立体声波形文件的 pico 上的 PWM 音频
播放音频文件 - MicroPython for Kids
ESP32 MicroPython教程:外部中断_pin.irq_zhazhawoaini的博客-CSDN博客
树莓派Pico迷你开发板MicroPython多线程编程实践_袁易学的博客-CSDN博客
picospuch/eetree-mpy-lecture-code - 码云 - 开源中国