1、项目介绍
本项目旨在开发一个音频可视化系统,其主要功能包括:
- PC 通过内置麦克风采集音频信号,并通过 WiFi 传输到 4.3 英寸的 CrowPanel ESP32 Display 开发板。
- 开发板接收到音频数据后,对其进行频谱分析,并在屏幕上显示音频信号的波形图、频谱图,同时展示幅度值和频率范围。
- 用户可以通过界面切换,选择只显示波形图、只显示频谱图,或同时显示波形图和频谱图
该项目采用 Thonny 软件和 MicroPython 语言进行开发,充分利用了 CrowPanel ESP32 Display 开发板的硬件资源和 LVGL 图形库,实现了一个功能丰富、交互性强的音频可视化应用。
2、硬件介绍
本项目使用的主要硬件设备是 CrowPanel ESP32 Display 4.3 英寸 HMI 开发板。该开发板搭载了 ESP32 微控制器,具有以下主要硬件特性:
4.3英寸-CrowPanel ESP32显示屏,分辨率为 480x272 像素
ESP32-S3-WROOM-1-N4R2主处理器
电阻式触摸屏、TFT-LCD屏幕
WiFi 和1*TF卡槽
此外,PC 端使用内置麦克风采集音频信号,并通过 WiFi 传输到开发板,实现了 PC 和嵌入式设备之间的音频数据交互。
3、方案框图和项目设计思路
方案框图如下:
项目设计思路如下:
- PC 通过内置麦克风采集音频信号,并使用 Python 脚本对音频数据进行处理和封装。采用 UDP 协议通过 WiFi 将音频数据传输到 CrowPanel ESP32 Display 开发板。
- 开发板接收 PC 端传输的音频数据,并利用 LVGL 图形库在 4.3 英寸显示屏上绘制波形图和频谱图。同时,开发板计算音频信号的幅度和频率范围,并在屏幕上显示这些信息。开发板设计了界面按钮,用户可以切换只显示波形图、只显示频谱图,或同时显示波形图和频谱图。
4、软件流程图和关键代码介绍
软件流程图如下:
关键代码如下:
- PC端音频采集与传输:
使用 pyaudio
库采集 PC 端的音频数据,并对其进行 FFT 变换计算频谱。
将音频数据和频谱数据封装成 UDP 数据包,通过 WiFi 网络发送到开发板。
stream = p.open(format=pyaudio.paInt16,channels=1,rate=sample_rate,input=True,frames_per_buffer=chunk)
# 创建UDP套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 目标地址和端口
target_address = "192.168.81.234"
target_port = 7788
message = array.array('b')
for i in range(160):
message.append(1)
# 循环发送UDP请求
while True:
# 发送UDP请求
data = stream.read(chunk)
audio_data = np.frombuffer(data, dtype=np.int16)
spectrum = np.abs(fft(audio_data))
#frequencies = fftfreq(len(audio_data), 1/sample_rate)
#print(spectrum)
for i in range(80):
message[i*2]= abs(int(audio_data[i*10] / 256))
message[i*2+1]= abs(int(spectrum[i*5] / 16384))
print(message)
sock.sendto(message, (target_address, target_port))
- 开发板端音频可视化:
开发板通过 UDP 套接字接收 PC 端传输的音频数据和频谱数据。
利用 LVGL 图形库在显示屏上绘制波形图和频谱图,同时计算并显示幅度和频率范围。
开发板设计了三个按钮,用户可以选择只显示波形图、只显示频谱图,或同时显示波形图和频谱图。
# 3. 创建按钮并关联波形显示对象
counterBtn1 = CounterBtn_Wave(scr, waveform_display)
counterBtn2 = CounterBtn_Spetrum(scr, waveform_display)
counterBtn3 = CounterBtn_Both(scr, waveform_display)
lv.scr_load(scr)
connect()
udp_socket = start_udp()
print("udp_socket start...")
while True:
print("udp_socket receive start...")
recv_data, sender_info = udp_socket.recvfrom(1024)
#print("{}发送{}".format(sender_info, recv_data))
#print("{}".format(recv_data))
# 根据当前波形类型更新点的数据
for i in range(80):
if waveform_display.waveform_type == 'wave' or waveform_display.waveform_type == 'both':
waveform_display.points[i] = {"x": i * 6, "y": -recv_data[i*2]+100} # 计算 wave 波形
if waveform_display.waveform_type == 'spectrum' or waveform_display.waveform_type == 'both':
waveform_display.points2[i] = {"x": i * 6, "y": -recv_data[i*2+1]+200} # 计算 spectrum 频谱
# 更新线条
waveform_display.update_waveform()
# 更新幅度和频率信息
waveform_display.update_amplitude_and_frequency(recv_data)
5、功能展示图及说明
波形图和幅度 频谱图和频率范围
波形图和幅度、频谱图和频率范围
频率采样为8000HZ,所以频率范围为0到4000HZ,幅度范围为0到256
6、项目中遇到的难题和解决方法
- 由于 Python 中没有直接操作音频硬件的API,我们需要使用第三方库
pyaudio
来采集音频数据。 - 在对音频数据进行 FFT 变换计算频谱时,也需要借助
numpy
和scipy
库的支持。 - 将采集的音频数据和频谱数据封装成 UDP 数据包,需要进行合理的数据格式转换和打包。
- 解决方法:
- 仔细学习和理解
pyaudio
、numpy
、scipy
等库的使用方法,并进行反复测试,最终实现了 PC 端音频数据的采集和处理。 - 通过分析 UDP 协议数据包的结构,设计了合理的数据打包方式,确保了 PC 端和开发板端的数据传输和解析。
7、心得体会
通过参与这个项目的开发,我受益匪浅,主要有以下几点心得:
- 跨平台开发能力的提升:
本项目涉及 PC 端和嵌入式设备端的开发,需要掌握不同平台的编程语言和开发工具。
在开发过程中,我们学习了 Python 在音频处理方面的应用,以及 MicroPython 在嵌入式设备上的使用。
通过整合 PC 端和开发板端的功能,我们提高了跨平台开发的能力。
- 图形界面设计和开发能力的提升:
使用 LVGL 图形库在开发板上开发图形界面,让我们对嵌入式设备的可视化有了更深入的理解。
在有限的屏幕资源下,如何设计合理的界面布局和交互方式,是一个很好的锻炼。
- 问题分析和解决能力的提升:
在项目开发过程中,我们遇到了一些技术难题,需要通过仔细分析、查阅资料、反复测试等方式来解决。
这种解决问题的经历,让我们的分析和解决能力得到了很好的提升。
针对本次活动,我有以下几点建议:
- 可以增加更多与实际应用场景相关的功能点,让项目更贴近实际需求。
- 可以引入更多嵌入式硬件设备,增加跨平台开发的复杂度,以提高参与者的综合能力。
- 可以组织更多的技术分享和交流活动,让参与者之间互相学习,共同提高。
总的来说,这次项目开发活动是一次非常宝贵的学习经历,我会继续努力,不断提升自己,为未来的工作和生活做好准备。