研究平台介绍
1 核心控制器介绍
本平台使用了乐鑫公司的ESP32-S2-Mini-1模块,ESP32-S2-MINI-1是一颗通用型Wi-Fi MCU模组,功能强大,具有丰富的外设接口,可用于可穿戴电子设备、智能家居等场景。
2 模块构成
3 核心功能介绍:
- 基于ESP32-S2 WiFi核心模块
- 128*64 OLED显示,SPI接口,显示信息、参数、波形
- 4个按键,用于参数控制、菜单选择
- 1路Mic音频输入 - 模拟电路,通过电位计可以调节增益0-40dB调节范围,并有带通滤波器
- 1路耳机插座音频输入 - 模拟电路,通过电位计可以调节增益 0-40dB调节范围,并有带通滤波器
- 2路音频输出,并有功率放大,可以驱动喇叭和耳机插座
- 一个FM接收模块,ESP32通过I2C接口对其进行参数设置,调节FM电台以及设置音量大小
- 一个模拟开关切换来自ESP32产生的音频还是FM输出的音频,模块开关的输出送到喇叭或耳机输出
项目内容实现
1 项目要求:
-
可以通过WiFi接收网络上的电台,也可以通过FM模块接收空中的电台,并可以通过按键进行切换、选台
-
在OLED显示屏上显示网络电台的IP地址、节目名字等相关信息或FM信号的频段
-
系统能够自动校时,开机后自动调节到准确的时间
2 功能流程:
3 项目环境:
本项目使用ardunio作为开发环境,使用U8G2库驱动屏幕,收音机模块使用RDA5807进行控制。
具体实现:
WIFI模块和校时
在学习使用了几个WiFi相关例程,熟悉使用流程后,使用相关的库中函数就能轻松实现wifi连接和时间校对。
流程为:初始化wifi-设置wifi模式-连接wifi。代码如下:
//连接网络
const char* ssid = "AAAAAA";
const char* password = "aaaaaa";
//时间服务器
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;
String wifi_conn(){
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(400);
//Serial.print("-");
}
return WiFi.localIP().toString();
}
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); //获取时间
FM模块
使用RDA5807库进行FM模块的控制。代码如下:
//搜索收音机的台 从8700~10800 MZH
void search() {
uint16_t i = 0;
uint8_t num = 0;
rx.setFrequency(8700); //从8700MHZ开始扫描
while (i < 210) {
delay(100);
if (rx.isStereo() && rx.getRssi() > 40) { //如果搜到台,切信号值大于40
fmstation[num++] = findBest(rx.getFrequency(), rx.getRssi());
if (num >= MAX_STA) return;
}
rx.setFrequencyUp();
i++;
}
//收音机换台
void change() {
while (1) {
if (stations == MAX_STA - 1) {
stations = 0;
rx.setFrequency(fmstation[stations]);
return;
}
if (fmstation[stations + 1] != 0) {
rx.setFrequency(fmstation[stations + 1]);
stations++;
Serial.println(fmstation[stations]);
return;
}
stations++;
}
}
//选择信号最好的频段
uint16_t findBest(uint16_t freq, uint8_t rssi) {
while (rx.isStereo()) {
rx.setFrequencyUp();
delay(100);
if (rx.isStereo() && rx.getRssi() > rssi) {
freq = rx.getFrequency();
rssi = rx.getRssi();
}
}
return freq;
}
网络收音机模块
在网络收音机部分我首先学习了CSDN上其他人的一些实现方法。连接网络电台和数据传输的部分都在学习后成功实现,但音频流不能正确输出。最终发现是Arduino环境下ESP32-S2不支持I2S的使用。发现这个问题之后我尝试使用VS code和idf环境进行开发。
在idf环境下使用smartconfig和手机ESPtouch实现wifi配置,使用sntp历程实现了校时模块,但我在配置esp-adf时出现卡顿,无法使用adf;另一方面我的校园网不能直接通过输入密码连接,我只能通过连接朋友的热点进行调试。最后考虑到时间问题我放弃使用idf,继续使用ardunio进行开发。
之后我学习了已有案例对于声音输出方面的解决办法,即指定的时间上给DAC管脚输出指定的电平。但音频的解码部分我始终没有找到方法,最终同样学习了案例中的方法,即自建网络电台,让这个电台发送已解码的音频数据。在服务器中写入自己的ip和端口,输出音频流数据。
server = socketserver.ThreadingTCPServer(("192.168.233.209",9000),Handler)
def handle(self):
super().handle()
wavedict=readWaveData()
wavedata=wavedict['datawav']
over=False
import io
rfile:io.TextIOWrapper= self.rfile
while not self.event.is_set():
try:
data = rfile.read1(1024)
except Exception as e:
log.error(e)
data = b""
log.info(data)
if data == b"q" or data == b"" or over==True: #退出
break
elif data == b"n": #获取音乐的内容
msg = wavedata[:1024]
print(len(msg),len(wavedata))
if len(msg)==1024:
wavedata=wavedata[1024:]
else:
over=True
expc = [] # 记录sock出错时对应的clients
with self.lock:
for c, sk in self.clients.items():
try:
sk.send(msg) # 可能在发送消息时就出错
except:
expc.append(c)
for c in expc:
self.clients.pop(c)
在ardunio中连接对应的电台ip和端口即可。
遇到的问题:
1、虽然最终我可以在pycharm(电台服务器端)看到打印日志中有数据输出,但在真正的使用中依旧只能听到质量非常差的声音反应。
2、在esp-idf环境搭建过程由于操作不熟练,尽管跟随乐鑫官方的视频教程我也依旧耗费了许多时间菜搭建完成,在后续的使用中也并不熟悉操作。以后有机会会继续学习相关的知识。
图片展示:
等待界面:
时间展示界面:
FM收音机:
网络收音机: