2021暑假一起练-用ESP32-S2完成了网络收音机/FM收音机
基于ESP32-S2-Mini-1模块的音频处理平台,实现了网络收音机和FM收音机的功能。
标签
嵌入式系统
音频处理
ESP-S2
Do_listen
更新2021-09-14
3247

一、核心控制器介绍

本平台使用了乐鑫公司的ESP32-S2-Mini-1模块。它采用PCB板载天线,模组配置了4MB SPI flash,采用的是 ESP32-S2FN4 芯片。该芯片搭载了Xtensa® 32 位LX7 单核处理器,工作频率高达 240 MHz,同时,它还集成了丰富的外设接口。可用于多种场景。

ESP32-S2-MINI-1模块的构成:

Fi6OgUu7hd9afOEoevqe-di1tNib

 

二、功能实现与解析

实现项目1 实现网络收音机/FM收音机的功能

  • 可以通过WiFi接收网络上的电台,也可以通过FM模块接收空中的电台,并可以通过按键进行切换、选台
  • 在OLED显示屏上显示网络电台的IP地址、节目名字等相关信息或FM信号的频段
  • 系统能够自动校时,开机后自动调节到准确的时间(年、月、日、时、分、秒)

功能解析:开机——WiFi连接——自动校时——按键切换——FM模式——FM频率信息显示——网络收音——网络音乐信息显示

程序流程:

Flz0JuBliOaWIJBbPSc-HgPSRbO8

 

三、代码解释

WiFi连接:

在Arduino中,要使用ESP32连接互联网,一共只需要四个步骤。

1.调用库 #include <WiFi.h>

2.设置WiFi SSID和密码

const char* ssid     = "SSID";

const char* password = "Password";

3.设置WiFi模式

WiFi.mode(WIFI_STA);

4.设备自连

WiFi.begin(ssid, password);

同时,为了便于查看,如果成功连上WiFi,返回相关信息,即  

return WiFi.localIP().toString(); //连接上

到此为止,WIFI配置就完成了。具体程序如下所示:

String wificonnect(){
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid,password);
  while(WiFi.status() != WL_CONNECTED){ //未连接上
    delay(400);
  }
  return WiFi.localIP().toString(); //连接上
} 

 

自动校时:

ESP32在连接了WiFi以后,可以使用NTP来校对本机时间,否则默认的Unix时间戳从0开始。使用configTime来对时间进行设置,其中GMT是指时区,daylightoffset是指夏令时,因为中国在东八区,所以跟日期变更线差7个时区,只需要在GMT中设置3600*7即可,这样打印出来的时间即是东八区时间。

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600*7; //时区
const int   daylightOffset_sec = 3600; //夏令时


//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

 

按键切换:

为了提高按键输入可靠性,采用延时程序避开按键的抖动时间,消除抖动的影响。并且,参考收音机按键的一般需求,为四个按键分别定义功能。

int KEY1 = 1; //按键定义
int KEY2 = 2;
int KEY3 = 3;
int KEY4 = 6;


pinMode(KEY1, INPUT_PULLUP); //上拉输入
pinMode(KEY2, INPUT_PULLUP);
pinMode(KEY3, INPUT_PULLUP);
pinMode(KEY4, INPUT_PULLUP);


//循环监听
//按键1:模式切换 按键2:频道切换 按键3:音量降低 按键4:音量提高
if(digitalRead(KEY1) == LOW) { //按键被按下
  delay(100); //消除抖动
  if(digitalRead(KEY1) == LOW) { //确认按键被按下
    if(modelsign == 2)
      modelsign == 0;
    else
      modelsign++;
  }
}

if(digitalRead(KEY2) == LOW) {
  delay(100);
  if(digitalRead(KEY2) == LOW) {
  changestation;    
  }
}

if(digitalRead(KEY3) == LOW) {
  delay(100);
  if(digitalRead(KEY3) == LOW) {
    if(volume > 0)
    volume--;
  }
}

if(digitalRead(KEY4) == LOW) {
  delay(100);
  if(digitalRead(KEY4) == LOW) {
    if(volume < 15)
    volume++;
  }
}

 

FM模式:

FM收音机部分首先学习了Art Deco FM Radio Project Using Arduino的例程,了解了FM收音机的工作过程。在实际操作中,了解到该板子FM收音机模块采用的是RDA5807M,并且使用使用I2C与ESP32S2进行通讯。于是,最终采用了示例SerialRadio进行该模块设计。同时,按我国标准,FM一般为(87)88-108MHz,但由于板子内存有限,为了节省内存和等待时间,我们最多查找10个电台。

void searchFM() {
  uint16_t i = 0;
  uint8_t num = 0;
  rx.setFrequency(8700); //从8700MHZ开始扫描
  while(i < 210) {
    delay(100);
    if(rx.isStereo() && rx.getRssi() > 35) {
      fmstation[num++] = findMaxSing(rx.getFrequency(), rx.getRssi());
      if (num >= MAX_STATIONS)
        return;
    }
    rx.setFrequencyUp();
    i++;
  }
  for(i = 0; i < MAX_STATIONS; i++) {
    Serial.print("FMRadio");
    Serial.print(fmstation[i]);
    Serial.print(rx.getFrequency());
  }
  Serial.println("Search over!");
}

 

信息显示:

这里的显示模块是12864OLED,在Arduino中,通过SPI驱动12864液晶屏是非常简单便捷的。我们只需要使用封装良好的u8g2库,只需在定义数据的时候做一点点的改变即可。

#include <U8g2lib.h>


U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(/*显示方向*/U8G2_R0, /*clock/SCL*/ 36, /*data/SDA*/ 35, /*cs=*/ 46, /*DC=*/ 33, /*reset/RST*/ 34);


u8g2.begin(); //显示器初始化
u8g2.firstPage();
do{
  u8g2.setFont(u8g2_font_ncenB14_tr);
  u8g2.drawStr(0,20,"Radio");
} while(u8g2.nextPage());

 

网络收音:

在网络收音机部分,在网络上学习多个例程后,发现在建立网络收音机时,大家一般采用的都是通过host、path、以及port三个信息建立连接,再通过I2S实现解码和播放功能。如在Arduino例程WebRadioDemo中,也采用的是这种方法。

//  http://comet.shoutca.st:8563/1
const char *host = "comet.shoutca.st";
const char *path = "/1";
int httpPort = 8563;

但是在实际操作中,我遇到了很大的问题。首先是自身对于计算机网络的不了解,在自己尝试编写的网络连接程序完成后,直接套用网址的时候才发现无法连接到对应网络。考虑到自身编程能力问题,不断对代码进行改正并且反复尝试连接。直到连接成功后在利用I2S解码获取数据时发现报错并且无法改正。在自身无法解决的情况下,我查找到Arduino环境下ESP32-S2不支持I2S的使用。于是,我打算重新在IDF环境下进行编写。

但是,在环境搭建过程中我又遇到了一些问题。

首先,是在下载ESP-IDF工具安装器时出错,在Python Choice环节出现乱码并无法继续安装;

其次,VSCode在下载完成后突然无法连接到扩展商店,在网上寻找了多个办法后均没有得到解决。

至此,ESP-IDF环境搭载失败。

在反复尝试无果后,我查看了已有的案例,学习了其解决办法——自行搭建网络音乐电台,在服务器内实现音乐.mp3到.wav格式的转换。

在借鉴了其网络服务器的构建后,我对自身Arduino的程序重新进行了编写,在网络电台模块,对数据流进行直接读写操作。这种称得上是另辟蹊径的方法终于解决了所需网络模块的构建。

uint8_t netbuf[3][1024]; //缓冲区数据
uint16_t writep = 0;     //写入数量
uint16_t readp = 0;      //读取数量
uint16_t m_offset = 0;


void onTimer(void) {
  if(readp<=writep)
    dacWrite(17,netbuf[readp%3][m_offset++]); //播放声音
  if (m_offset >= 1024) {
    m_offset = 0;
    readp++; //一个缓冲区读取完成
  }
}

 

四、使用方法

在系统启动后,OLED显示“Loading-”字符,表示正在开机,程序开始自动扫描FM的波段,在搜索完FM波段后,连接提供的WiFi,并通过互联网“pool.ntp.org”获得当前时间。在一切准备完成后,板子会自动地进行到第一个模块——时间显示模块,在该状态下音量为0,FMradio不播放。在按键切换后,FM收音机开启播放状态。其中,第二个按键负责切换电台,第三个和第四个两个按键负责控制音量。在这种模式下,一般音质较差,只有连接天线后,音质才会大幅度提升。再次切换模式后,进入到网络音乐播放模块,这时候自动连接服务器。如果连不上,显示“Connection failed”,如果连接上,显示服务器信息,并开始播放音乐。

 

五、运行现象

开机界面:

Frb19gkJDSUByGUuSLvTylS53z48

时间显示:

Fk5Pena23oFiU5DieUk9N677Fw1g

FM模式:

FhDDnSbnXuHLFD07-nM0A6E3SGWE

WiFi模式:

Fgy9A9xwAzc2RiQBGs0Zcdguoi8s

 

六、存在问题

  • FM模式转WiFi模式时间较长,需耐心等待;
  • WiFi连接不稳定,多次模式转换后可能会出现卡退现象;
  • WiFi模式下播放音乐质量较差,时间较长。

 

七、心得体会

这次项目是我首次参加电子森林平台的“暑期一起练”活动,带给了我非常大的收获。首先,在这次项目中,我对ESP32-S2这个芯片有了一些简单的认识和了解,学会了进行一些简单的项目编写。同时,在这个过程中,我还学习了Arduino软件的一些知识,对未来的硬件编程也有所帮助。当然,最重要的是,这次活动帮助我提高了硬件编程学习的能力。在这次项目结束后,我也会多多尝试利用这块板子做其他几个项目,希望能够更好地掌握这款芯片的使用。也期待在下次活动中和硬禾学堂、电子森林再会。

附件下载
webradio_sever.rar
web网络服务器
allradio.ino.bootloader.bin
已编译二进制文件
radio.rar
源文件
团队介绍
北京理工大学 信息与电子学院
团队成员
Do_listen
北京理工大学 信息与电子学院
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号