基于LVGL驱动的OLED屏的FFT声音实时可视化

描述

本项目旨在利用LVGL驱动的 Xiao-expansion-board的OLED显示屏实现FFT声音数据的实时可视化。关键内容包括利用LVGL库在OLED屏幕上进行数据可视化展示,在XIAO ESP32S3 Sense 上进行声音数据的高速采集和预处理,以及同步进行FFT (快速傅里叶) 变换计算。该项目利用了XIAO ESP32S3 Sense 开发板的I2S麦克风组件和Xiao Expansion board 的OLED实现音频数据可视化的过程,深入地了解声音数据处理与可视化的技术细节,为实时声音及音乐数据监测与展示提供参考和应用价值。

材料清单

硬件:

XIAO ESP32S3 Sense

Xiao Expansion board 

软件:

Visual Studio Code

STEP1 - LovyanGFX驱动oled屏幕

Xiao Expansion board 拓展了多个grove接口,同时还配备了一个入门级别的ssd1306_oled,按照常规ssd1306就该使用u8g2这样的功耗上古神器来驱动,但随着很多高性能嵌入式开发板出现了,图形驱动更新迭代的速度也加快了,驱动ssd1306也有了更多选择。我们值得拥有最好的, 本项目中使用LovyanGFX图形驱动库来驱动ssd1306。LovyanGFX库受TFT_eSPI启发,深度改造而来,是很多大众创客的挚爱,它不单只可以驱动常见的LCD屏幕,同时还可以支持一些oled屏幕,使用这个库使得最简单入门级别的ssd1306 oled屏幕也可以共享LCD屏幕才有的作图函数。

在本项目完成了对xiao系列扩展板上的ss1306的适配,更进一步地,按照当下最流行的lvgl图形库的作图机理进行了移植,极大的丰富了xiao扩展板的ssd1306的应用场景,希望你也能从中受到启发,这个项目能为你今后的工作带来便利。

OLED屏OLED屏

   OLED屏

STEP2 - 基于ssd1306的lvgl移植

传统的图形绘制库(例如经典TFT_eSPI,Adafruit_GFX,Lovyan_GFX等)可以帮助用户快速的完成方案。LVGL(Light and Versatile Graphics Library)的出现给嵌入式开发在最终产品呈现上提供了一种更优雅的解决方案。LVGL相对于传统图形库更适合用于嵌入式系统,它在性能、资源占用和灵活性方面都有一定的优势。然而在ssd1306上运行lvgl曾经是多么高远的梦想呀,如今我们在Arduino编程环境上就可以轻松使用上,也可以共享广阔的开源繁荣,是一次重大的进步。   

移植完成后,在ssd1303上可以流畅运行lvgl的项目,但在程序设计的时候注意颜色最好能指定白色或者黑色,这样显示效果更清晰。

LVGL它与传统的图形库有几个显著的差异:

1.硬件加速支持:LVGL具有对硬件加速的支持,可以利用硬件功能来加快图形渲染速度和降低CPU负载,而传统的图形库则通常依赖于软件渲染。

2. 内存需求:LVGL设计时考虑了嵌入式系统的资源限制,因此在内存占用上更为高效,这使得它在资源受限的嵌入式设备上表现更出色。

3. 事件处理:LVGL提供了灵活且强大的事件处理机制,能够方便地实现触摸屏、按键等输入设备的交互,而传统图形库在这方面可能需要额外的定制和开发。

4. 主题和样式:LVGL提供了丰富的主题和样式支持,可以轻松地定制界面外观和风格,而传统图形库可能需要较多的工作来实现相同的效果。

5. 跨平台支持:LVGL被设计成可跨平台使用,可以在不同的嵌入式系统上运行,而传统图形库可能需要针对特定平台进行适配或者重新开发。

OLED屏

STEP3 - 声音频谱解析

(1)I2S麦克风的设置

XIAO ESP32S3 Sense除了装备有摄像头还有一个I2Smicrophone,所以可以开展天马行空的语音类的项目。本项目正是利用了I2S microphore的优良特性,在本项目中发挥了键作用。i2s_config 中我们主要关注的参数包括sample_rate、dma_buf_cout、dma_buf_len这3个参数。采样率、dma数量、dma_buf长度参数的不同会对数据最终呈现产生明显区别。采样率越快就更能捕获声音的细节信息,但也不是可以无限的放大,我这里设了64000,意思是1秒钟能采集64000个数值,这个能力是ADC机制的麦克风无法企及的。DMA 是 "Direct Memory Access"(直接内存访问)允许外部设备直接访问系统内存,而无需CPU的干预。这样可以提高数据传输的效率,减少对CPU的负担,从而提升系统整体性能。这里我们用一个比喻来帮助大家理解体会DMA和MCU之间的关系,DMA它就像会自己独立好学的孩子,它完成“作业”后,就会向老爸(cpu/mcu)报告,然后在老爸忙检查作业的时候,这个好孩子又自觉得跑去做另一门作业了,一刻也没停过,反倒老爸忙个不停。这样理解的话dma_buf_count 参数至少是2,(就是给孩子布置两份作业一个数学,一个语文,轮流干,不然做完一门作业他就没事干了,肯定会跑去玩手机,也可设为3,多布置一份英语作业)。dma_buf_len这里呢,就更有意思了,因为好孩子一把作业做完就会立即送去给老爸看,如果这孩子做一个题目就去给老爸看,就不断的去打扰老爸,老爸就会很烦,老爸就跟孩子说你把这一整页都做完了再来找我,所以为了减少对cpu的占用次数和时间,也把这参数设得尽量大,但也有个范围是8-1024,这样孩子跟老爸默契的配合下,老爸工作安心工作,孩子认真学习,其乐融融,大家的工作都完成得很漂亮。

   OLED屏    

OLED屏

(I2S调参指南)

(2)FFT数据处理

在台面上我们只看到两个入口函数,第一步用FreeRTOS 在esp32的第二个核心上创建一个音频数据处理任务,这个任务的句柄是processing_task_handle,第二个是 i2s_sampler.start 函数,我们把刚才配置好的i2s设置传递给它,它就会在后台默默的干活并通过上述句柄将dma采集到的数据释放出来。在I2SSampler里面FreeRTOS的经典招式都用上了,包括消息队列,消息直接通知,多任务创建,看似慌乱,实际是在密锣紧鼓的忙乎着给老板们“做饭”。另外一个功臣是Processor,它就是FFT的化身,它接收了I2SSampler传来的消息,然后嚼烂消化成漂亮干净的数据。我就是喜欢这样的好同事,一直默默无闻地工作,做好事不留名。实际这些在后台默默无闻埋头苦干的小伙伴们才这个项目的精华部分。

      OLED屏

(3)LVGL动态绘图

我们采用一个振幅更新函数(bar_value_update)来处理频谱和屏幕大小适配的工作,它接受一个傅里叶变换计算得到的浮点型数组mag,循环遍历mag数组的每隔两个元素,计算它们的平均值ave,并将其与窗口高度进行比较得到柱状图的值。整体逻辑是计算加权平均值,然后根据条件判断,更新柱状图的值和峰值,并且采用了一阶滞后的平滑处理,使得柱状图的变化更加平稳。

而图形的绘制关键环节在于把频谱对象作为一个容器进行绘制(spectrum_draw_event_cb),绘图没有采用lvgl常规的使用预设的作图函数,而是采用底层的绘图方法。绘图实际发生在LV_EVENT_DRAW_POST(绘图结束后)事件,会对频谱对象进行绘制操作。整个过程中使用了绘制矩形(lv_draw_rect)、绘制线条(lv_draw_line)机制等。矩形图代表瞬时的频谱强度,线条用于代表频谱峰值的滞后响应,由于线条的宽度是2 像素,所以看起来也是一个小长方体。它通过循环遍历一个大小为频谱分析结果数据SAMPLE_SIZE的数组,绘制矩形和两条线条,其中bar_chart和bar_chart_peaks是用于确定柱状图高度的数据数组。快速地在spectrum_obj对象上绘制柱状图,并通过柱状图的高度数据进行实时更新。即使是在非黑即白的Oled屏上也能够响应及时,产生了良好的动态效果。   

  OLED屏

总结

最终在xiao expansion board的屏幕上展示了经过FFT处理的音乐信息,它能够即时的对当前麦克风采集到声音作出反馈。它就好像是一座小型的音乐的喷泉,在水平面被音符的动能弹起,形成了美丽的水花飞溅的壮观场景。每一个频率成分就如同飞溅的水花一样,展现出音乐中多姿多彩的细节和纹理,从低频的稳重沉郁到高频的轻盈活泼,每个音符都呈现出独特的张力与韧性。充分展现了FFT解析音乐的魅力和神奇之处,通过这种方式让人仿佛能够透过频谱数据看到音乐的灵魂,令人陶醉。






审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分