暑期一起练之使用树莓派PICO的扩展功能板实现采集音频参数
暑期一起练 树莓派PICO 扩展板 音频采集 FFT 波形 麦克风
标签
嵌入式系统
MicroPython
ST7789
FFT
波形展示
aramy
更新2022-03-22
3776

     硬件介绍树莓派PICO,感觉简单来说可以看做一块由RP2040为核心的单片机最小板。有264KB的SRAM(RP2040片内自带)和2MB的Flash(模块上外扩),然后单片机该有的接口都有了,spi、iic、串口、adc。硬核学堂在这个最小板子的基础上,实现了常用的外设。有按键、光电旋转编码器、LCD显示屏,SD卡,蜂鸣器、mic、三轴姿态传感器、红外发射/接收。基本上常用的外设都做了实现,这个扩展板很容易拓展到其他单片机的学习。

     任务选择:“暑期一起练”活动提供了三个任务,一开始选择 项目2 - 设计一个带有背景音乐的数码相框。需要用到的硬件部分有 LCD模块、三轴姿态传感器(MMA7660)、SD卡。在硬禾学堂中寻找教程进行学习,有LCD驱动的教程,有三轴姿态传感器驱动的教程。按教程学习很快就掌握了硬件的驱动方法。但是SD卡驱动一直没找到方法,在互联网上找到了PICO读SD卡spi的驱动方法,但是测试不成功。仔细找了一下原因,这个开发板的SD卡管脚解法没有了解过。通过群里大佬解释,这是接法是sdio协议的接法,但是只找到C语言实现的例子,macropython中没有实现sdio协议读取SD卡的方法。遂放弃!重新选择任务1——制作一个音频参数测试仪。

     任务实现过程
     首先,编程工具和语言的选择。树莓派PICO支持C语言和micropython编程。自己对python还算了解,再加上Micropython下对应的功能包非常多,所以理所应当地选择了micropython。

      其次,硬件的驱动。为了实现任务。需要驱动的硬件有LCD屏幕、麦克风、按键,编码器。硬核学堂很贴心地将相关设备的介绍都收集起来了,按着帖子学习,很快设备就驱动起来了。

      然后,单个设备顺利驱动起来后,就开始开始遇到问题了。第一个遇到的问题是速度问题。TFT刷新不够快!完整刷新一遍屏幕,要几十毫秒!想要实现音频信息展示,采集声音的采样率就不能太低,否则细节会丢失。常见的采样率有CD采样率:44100hz,古老的有线电话采样率:8000hz,而现在绘制屏幕都要用几十毫秒计算,如何做到快速采样啊?
     第一个想到的解决方案是多线程。PICO是双核的M0的微控制器,尝试使用多线程,很可惜,PICO倒是支持多线程,尝试2个线程是能够运行的,再多线程,就不行了。而且两个线程在Thonny下也是有问题,会导致Thonny的卡死。感觉Thonny是已经使用了两个线程,一个提供给用户编程使用,一个是Thonny监控PICO的状态用了。当用户使用双线程,Thonny就无法控制PICO了。所以在micropython下用多线程解决不了这个问题。 
     既然解决不了刷新慢导致无法高速采样的问题,那么就绕过这个问题。将采样和绘制波形分开处理。既先采集一段时间的声音,存放在数组中,然后再绘制屏幕。绘制过程中停止采集声音,这样虽然不能时时绘制采集的声音,但是至少可以保证绘制出的声音是准确的。
     采用分时方式处理完美地避过了屏幕刷新慢的问题。那么每次采集多长时间呢?CD音质的采样率是44100Hz,既每秒有44100个数,对单片机来说太大了,我这里一开始选择的是8000Hz,这是电话音质,既每秒需要采集8000个数。PICO毕竟还是个单片机,内存有限,就每次采集1秒数据,然后绘制波形,再继续采集1秒数据……如此往复。
     第二个问题:频谱转换,就是分析声音信息在频率上的分布情况。python下有专门的频谱转换的函数,想调用快速傅里叶变换的库,还需要依赖numpy库。发现想在pico上安装numpy库是个不可能完成的任务,numpy库的尺寸远远超过了pico能承受的范围。而没有傅里叶变换就无法做出频谱分析,自己又没有能力重写傅里叶变换函数。经过群友“漂移菌”的指点,在https://github.com/v923z/micropython-ulab 中有提供micropython下numpy和快速傅里叶变换的库,并且还帮助编译了新的micropython的固件,非常感谢!这个问题得到完美解决。在micropython下的快速傅里叶变换,不能依赖任意尺寸的数据了,必须是2的指数倍,所以这里将每秒采集ADC次数修改为8192次。在micropython下定时采集ADC值还是蛮简单的,有个timer的库可以直接调用。直接在中断中读取ADC的信息。

#麦克风 音频波形收集
class MICWave():
    def __init__(self):
        self.potentiometer = machine.ADC(26)  # 初始化ADC
        self.micwaveval=[]              #读取麦克风的波形数据
        self.tim = Timer()
        

    #读取一次麦克风时长的数据
    def readmic(self):
        led = Pin(25,Pin.OUT)
        led.value(1)
        self.tim.init(freq=8192, mode=Timer.PERIODIC, callback=self._tick)  # 声音采样率使用 8192 
        while len(self.micwaveval)<8192:
            pass
        self.tim.init(callback=None)
        led.value(0)


    def _tick(self,timer):
        val=self.potentiometer.read_u16()
        self.micwaveval.append(val)

     采集到麦克风的音频信号后,放入数组中,然后进行快速傅里叶变换,这里又需要一个一样尺寸的数组,用来存放频谱信息。这时就发现存储空间不够用了,于是将采样率降低到了4096Hz。快速傅里叶变换后,因为结果在频域上的对称,所以保留一半数据即可。
Fu6S-TVPzHG0eoYCEjp0RRk8rr0x
     接下来就是绘制屏幕了,将屏幕分为上下两个部分,上边负责绘制声音的波纹图,下边负责绘制频谱图。中间留出一行,用来显示信息。显示的信息有:1、占比最大的频率。用来提示这一秒声音中频率出现最多的频率值。2、麦克风的电压最大值。这里的范围是从0~3.3v,声音是在1.65v两端分布,既无声音电压为1.65v,声音越大距离1.65v越远,呈现对称分布,这里取最大值。3,纵向的缩放比例。声音的ADC值是映射到0~65536上的,这里通过比例系数映射到屏幕的范围上。4、横向的缩放比例系数。将1秒内的声音信息,缩放到屏幕范围。在这里又遇到内存不够的问题,PICO毕竟是个单片机,在绘制屏幕之前处理每秒4096数据的数组没有问题,但是绘制屏幕后又开始报这个错误了。
Fp2AlqOFh2TJ3jODjfih_Fx2aQXx

     暂时想不出办法解决这个问题,只能将每秒的采样率调降至2048Hz。这就意味着,这个音频采集器最多能处理到1000Hz的声音信息,再高就无法处理了。还好,说话声音基本都在500Hz以下,采集分析说话声音基本够用。

FvWGWSuulvwxSL7rI2mMUI_cS2EJFkLzMPStXW_U6gVp0koJV1DHFtSA

     最后实现任务:系统运行分成两个模式,自动状态和查看模式。自动模式系统自动收集1秒声音,然后绘图。再收集、绘图如此循环不息。查看模式,就停止收集声音信息,按上次收集的声音信息做图形展示,可以放大缩小、上下左右移动波形图。按下旋转编码器中间按钮可以切换模式,左上角显示“AUTO”处于自动模式,按一下按钮,切换到查看模式的查看横向信息模式,左上角显示“HORI”,此时两个按键负责调整缩放系数,上键缩小缩放系数,波形图在水平轴上就变大,此时会超出屏幕显示范围,使用编码器可以左右移动波形,查看波形细节。水平缩放系数最小为1,即2048个点都会被展示出来。最大为8.5,即2048个点被映射到240(屏幕宽度)上。再按一下旋转编码器中间按钮,切换到纵向查看模式。此时屏幕左上角显示“VERT”。两个按键负责调整纵向的缩放比例系数。比例系数缩小则波形就在纵向上拉伸,比例系数放大,则波形在纵向上缩小。旋转编码器可以上下调节波的位置。再次按下旋转编码器中间按钮就回到自动模式。绘图这块,python的矩阵映射功能是真的好用,使用按键中断控制比例系数,使用numpy的切片,可以很方便地调整图像的缩放。

     心得体会:首次接触micropython,挺好用的工具,编程起来很方便。可惜感觉PICO在micropython下驱动st7789还是不够快。看了网友大神的作品(https://github.com/picospuch/st7789_mpy)速度快了很多,正在学习中。非常感谢硬禾学堂和电子森林,单单一块PICO板子其实不好玩,搭配上这个开发板后能学习到很多东西,而且这个开发板的扩展性很强,可以适合自己制作其它单片机学习的平台!期待学习大家的作品。

 

附件下载
pico_wave.zip
micropython-with-ulab.uf2
团队介绍
团队成员
aramy
单片机业余爱好者,瞎捣鼓小能手。
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号