这是课程视频的简化版文字稿,你可以在这里找到完整的课程视频
T型板的不足
之前T型开发板性能尚可,价格实惠,通用型强,适合基础课程的学习,但是它有以下制约:
- 整体处理能力有限,难以处理复杂任务或多任务情景
- 缺乏对
USB-OTG的支持,难以进行鼠标,键盘等外设的扩展 - 芯片
IO接口较少,难以同时连接多种外设 - 对复杂电路案例来说,搭建成本和可靠性均不能满足要求
USB-OTG允许 USB 设备充当主机或周边设备。这意味着USB-OTG设备可以连接到其他 USB 设备,而无需计算机或其他主机设备。
认识本课程所需的设备
- 基于ESP32-S3的多媒体开发平台
- 图片展示

- 采用
ESP32-S3-WROOM模块,内含8MB闪存与8MB内存 - 配备8键无冲数字键盘,方便支持组合键的开发
- 配有TF卡槽,方便存储空间拓展
- 采用160x128
ST7735彩屏进行显示,具有屏幕触控功能 - 采用两个USB-C接口,分别用与连接上位机和实现USB-OTG
- 采用I2S实现音频输出,配备3.5mm音频输出接口(新版本的开发平台内置了扬声器)
- 板载
MPU-6050传感器,支持体感开发
ESP32是乐鑫科技开发的一系列低成本,低功耗的单片机微控制器,集成了Wi-Fi和双模蓝牙.它采用Tensilica Xtensa LX6双核和单核微处理器,内置无线开关,RF换衡器,功率放大器,低噪声接收放大器,滤波器和电源管理模块
ST7735是一款具有SPI接口的彩色TFT液晶显示驱动芯片,具有 128 x 160 像素的显示分辨率,可显示 16 位RGB颜色
MPU6050是一种集成了 3 轴加速度计和 3 轴陀螺仪的微型运动处理单元(IMU).它是一种小型,低功耗的传感器,能方便的采集加速度和角速度数据,用于测量物体的运动
I2S是用于数字音频传输的串行总线标准,由三条线组成:数据线,时钟线和选择线.其是一种面向主从架构的总线:主设备负责产生时钟信号并将数据传输到从设备,从设备负责接收数据并将其转换为模拟音频信号
- 基于ESP32-S3的智能摄像头
- 图片展示

- 采用
ESP32-S3模块,并配备ST7735彩屏 - 内置
OV2640摄像头,便于开发CV,图传类应用 - 内置TF卡槽和
MPU6050六轴传感器 - 基于拓展手柄可支持
I2S音频输出,5D按键,INMP441数字麦克风 - 配有
7Pin拓展接口便于连接其他外设,用USB-C接口连接上位机
OV2640是一款 1632 x 1232 像素,1/4 英寸,低功耗 CMOS 图像传感器,可用于各种应用.包括机器视觉,物联网,无人机和智能家居,具有 50 帧/秒的视频帧率和 0.008 lux 的低光性能
INMP441是 TDK InvenSense 制造的一种高性能,低功耗,数字输出,全向 MEMS 麦克风.它采用 4.72 x 3.76 x 1 毫米的薄型表面贴装封装,具有可回流焊接兼容性,无灵敏度下降
配套软件系统的重要性
工作室定制了高度客制化的MicroPython固件,继承官方MicroPython特性的同时,还添加了以下支持:
- MP3解码
- FFT计算辅助
- 摄像头支持(
OV2640) - TFLite Runtime
- 声音池
- 软管线3D
- 2D图像仿射变换
- 帧缓冲缩放辅助
- I2S音频录放
- 数字图像处理
- 颜色识别
- USB键鼠和摄像头
以上功能模块可以极大方便人工智能,2D/3D动画和音频等复杂功能的开发
FFT 是快速傅里叶变换的缩写,它是一种计算离散傅里叶变换 (DFT) 的有效算法.FFT有许多应用:包括信号处理,图像处理和信号合成
TensorFlow Lite 是 TensorFlow 的轻量级版本,用于在移动设备,嵌入式设备和物联网设备上运行机器学习模型
运行时(Runtime)是计算机程序运行生命周期内的一个重要阶段,它负责提供程序运行所需的各种服务,并确保程序能够正确执行
管线通常用于处理数据:例如一个图像处理管线可以将图像从原始格式转换为压缩格式,然后进行滤波和增强
背景知识
相较于WAV音频,MP3音频在同等条件下占用空间更小.但由于这种类型的文件存储的是编码压缩之后的音频数据,所以播放前需要进行解码.ESP32-S3的性能相较于T型板有了显著提升,可以进行音频解码操作
hzmp3 模块包含的工具方法
我们将用几个例子引入它们:
- 获取MP3文件信息
1
2
3
4
5
6
7
8
9
10
11
12
13import hzmp3
data = open("test.mp3", "rb").read(2048) #by default #as an array
file_size = os.path.getsize("test.mp3")
info = hzmp3.getMp3Info(data, len(data), file_size)
print("总时间长度:", info[0])
print("第一帧数据字节数:", info[1])
print("普通帧数据的字节数:", info[2])
print("采样率:", info[3])
print("声道型:", info[4]) #1 for stereo, 2 for mono - 初始化
1
2
3
4
5
6
7
8
9
10import hzmp3
bck, ws, sd = "I2S的三个GPIO引脚编号"
samplerRate = "待播放MP3的采样率"
channels = "声道数"
hzmp3.initMp3(bck, ws, sd, samplerRate, channels)
#初始化解码器,I2S和工作在另一个核心的播放任务
#本模块占用#0 I2S - 将一定帧数的数据送入队列等待解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14import hzmp3
inputData = open("test.mp3", "rb").read() #readbinary
volumeFactor = "音量等级[0,5]" #0为原音量,其余为原音量/2^volumeFactor
frameCount = "送入的数据帧数"
bytesPerFrame = "每帧数据字节数"
if hzmp3.playMp3(inputData, volumeFactor, frameCount, bytesPerFrame):
print("Success!") #返回bool
else:
print("Fail!")
#如果系统处于暂停状态,调用此方法会切换成播放状态
#开发者需要确定第一帧和普通帧数据的长度 - 快进快退
1
2
3
4
5
6
7import hzmp3
timeS = "快进/快退秒数,复数为快退"
frameSizeCommon = "音频文件普通帧字节数"
frameSizeFirst = "第一帧字节数"
hzmp3.progressSeek(timeS, frameSizeCommon, frameSizeFirst) - 一些简单方法
1
2
3
4
5
6import hzmp3
hzmp3.getTime() #获取已播放时间
hzmp3.pauseOrContinue() #切换播放/暂停
hzmp3.isFinish() #判断队列是否播放完毕
hzmp3.mp3DeInit() #释放MP3解码器和I2S资源,并销毁另一个核心的播放任务
案例
1 | import hzmp3 |