# ESP32 **Repository Path**: iron2222/esp32 ## Basic Information - **Project Name**: ESP32 - **Description**: ESP32小项目,开发环境ESP-IDF与Arduino。 - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 7 - **Forks**: 3 - **Created**: 2022-01-17 - **Last Updated**: 2025-10-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ESP32S2小项目,FM,网络时钟/电台,Arduino开发环境 ## 效果展示 [TOC] ### 开机动画: ### 网络时钟: ### FM模块: ### 网络收音: ## 硬件平台 ESP32是乐鑫的一块国产WiFi芯片。 **ESP32-S2-MINI-1**采用PCB板载天线,模组配置了4MB SPI flash,32 位LX7 单核处理器,工作频率高达 240 MHz。43 个 GPIO 口,14 个电容式传感 IO,支持 SPI、I2C、I2S、UART、ADC/DAC 和 PWM 等各种标准外设,支持 LCD 接口(8-bit 并口 RGB、8080、6800 接口),支持 8-/16-bit DVP 图像传感器接口,最高时钟频率支持到 40 MHz ,支持全速 USB OTG。 **硬核学堂**在ESP32-S2-MINI-1的基础上,扩展了麦克风输入、按键输入、红外输入、FM收音机模块、12864OLED屏幕输出、扬声器(耳机接口)输出。 具体信息请参考下面网址: [电子森林基于ESP32-S2模块的物联网/音频信号处理平台]: https://www.eetree.cn/project/detail/419 ## 开发平台 可选择平台有:esp-idf、Arduino,CicruitPython,因为前段时间刚用Arduino平台玩过ESP8266模块,所以这里选择Arduino平台进行开发(我才不会告诉你们,我是因为esp-idf编译工具链没配置好)。 ### 简单环境配置 #### 第一步:首选项中开发板管理网址: [复制粘贴就完了]: https://dl.espressif.com/dl/package_esp32_index.json #### 第二步:开发板管理器,找ESP32,下载 #### 第三步:换开发板 因为下载太慢,一般会直接用别人下载好的ESP32的包,但问题是相当的多,给大家放一个我的环境配置历程图: ### 手动配置 最后把我成功试验过的一种方法告诉大家: #### 首先,下载解压我这个包 > --来自百度网盘超级会员V4的分享 > hi,这是我用百度网盘分享的内容~复制这段内容打开「百度网盘」APP即可获取 > 链接:![img](file:///C:\Users\lenovo\AppData\Roaming\Tencent\QQTempSys\[5UQ[BL(6~BS2JV6W}N6[%S.png)https://pan.baidu.com/s/1Pcb6X0YfKsrcxr-ZpKr4wA > 提取码:qw35 #### 然后,解压到自己的arduino安装路径里替换掉它 关掉,再打开Arduino就能看到开发板了。 以后大家想配置任何开发板的环境,只要把它的包放到这个路径里就好,亲测有效。 万事俱备,接下来就是进行软件开发了。 ## 程序简述 ### 代码逻辑: 逻辑不算复杂。 ### 连接WiFi: ```c //wifi用户名与密码 char* ssid = "iron2222"; char* password = "*******9009"; ``` ```c //启动WiFi服务,这里是客户端(放在set up函数里) WiFi.begin(ssid, password); Serial.print("Connecting to "); // 串口监视器输出网络连接信息 Serial.print(ssid); Serial.println(" ..."); // 告知用户正在尝试WiFi连接 int i = 0; // 这一段程序语句用于检查WiFi是否连接成功 while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函数的返回值是由WiFi连接状态所决定的。 delay(1000); // 如果WiFi连接成功则返回值为WL_CONNECTED Serial.print(i++); Serial.print(' '); // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值 } // 同时NodeMCU将通过串口监视器输出连接时长读秒。 // 这个读秒是通过变量i每隔一秒自加1来实现的。 Serial.println(""); // WiFi连接成功后 Serial.println("Connection established!"); // 将通过串口监视器输出"连接成功"信息。 Serial.print("IP address: "); // 同时还将输出IP地址。这一功能是通过调用 Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。 ipaddress = WiFi.localIP().toString(); ``` ### 网络时钟: ```c //网络时钟设置 const char *ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 8 * 3600; const int daylightOffset_sec = 0; ``` ```c // 从网络时间服务器上获取并设置时间,获取成功后芯片会使用RTC时钟保持时间的更新(放在set up函数里) configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); printLocalTime(); ``` ```c //网络时钟显示函数 void timer_show() { struct tm timeinfo; if (!getLocalTime(&timeinfo)) { u8g2.clearBuffer(); u8g2.setFontDirection(0); u8g2.setFont(u8g2_font_ncenB08_tr); u8g2.setCursor(0, 40); u8g2.print("Failed to obtain time"); u8g2.setCursor(2,55); u8g2.print(ipaddress); u8g2.sendBuffer(); return; } u8g2.clearBuffer(); u8g2.setFontDirection(0); u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.setCursor(20, 15); u8g2.print(&timeinfo, "%H:%M:%S"); u8g2.setCursor(15, 35); u8g2.print(&timeinfo, "%Y/%m/%d"); u8g2.setCursor(2,55); u8g2.print(ipaddress); u8g2.sendBuffer(); } ``` ### FM收音机: 因为FM模块是通过I2C进行数据传输的,所以要打开相应的配置。 ```c //I2C引脚设置 #define ESP32_I2C_SDA 5 #define ESP32_I2C_SCL 4 #define MAX_DELAY_RDS 40 // 40ms - polling method long rds_elapsed = millis(); RDA5807 rx; ``` ```c // I2C相关设置(放在set up函数里) Wire.begin(ESP32_I2C_SDA, ESP32_I2C_SCL); rx.setup(); rx.setVolume(0);//音量大小设置,可调 delay(500); //FM相关设置 rx.setFrequency(10650); //开启是频率,可调 //使能SDR rx.setRDS(true); ``` ```c //FM模式显示函数 void FM_show() { char str[64] = {0}; u8g2.firstPage(); u8g2.clearBuffer(); //清除内部缓冲区 u8g2.setFontDirection(0); //设置字体方向 u8g2.setFont(u8g2_font_ncenB14_tr); //设置字体 u8g2.setCursor(15, 20); u8g2.print("FM Radio"); u8g2.setFont(u8g2_font_ncenB10_tf); u8g2.setCursor(15, 40); sprintf(str, "%u MHz",rx.getFrequency() ); u8g2.print(str); u8g2.setCursor(15, 55); sprintf(str, "Vol: %2.2u",rx.getVolume()); u8g2.print(str); u8g2.sendBuffer(); delay(1000); } ``` ### 网络收音: 这里其实可以重点讲解一下,因为涉及到了DAC。关于什么是ADC/DAC大家可以看这篇博文: [博客园]: https://www.cnblogs.com/iron2222/p/15833426.html [CSDN]: https://iron2222.blog.csdn.net/article/details/122636386?spm=1001.2014.3001.5502 整个webradio的实现过程可以划分为**三部分**: - 获取音频流,程序使用的 http 协议从一个服务器上面获取的音频数据,并将整个数据存放到一个 buffer 中。 - 对音频流进行解码,当 buffer 中有一定的数据后(可以通过宏进行调整),开启解码线程。解码线程会从这个 buffer 中取出数据,然后调用解码库,将音频流解码为可直接输出的数字信号。 - 将解码后的数据通过 DAC 输出,解码线程每解完一帧数据后,将它通过 I2C 驱动程序直接送给 DAC。 这里面存在一个**同步的问题**,即从服务器上面获取音频流与对音频流进行解码的同步。如果获取的音频流过快,超过了解码的速度,则它可能将 buffer 撑爆,因此会丢失部分数据;如果解码的速度过快,超过了获取音频的速度,则它可能将 buffer 消耗的干干净净,从而也会出现声音卡顿问题。这需要进行权衡。 但是在S2中无法实现在线音频流的解码,所以利用**ESP8266作为网络服务器用socketTCP传输搭建了了独立的网络音频库**,上面看到的那个黑色的模块。 ```c //网络收音 uint16_t num=0; #define WEBSERVERIP "192.168.43.212" #define WEBSERVERPORT 3999 uint8_t netbuf[3][1024]; //网络数据缓冲区 uint16_t writep = 0; //写入数量 uint16_t readp = 0; //读取数量 WiFiClient client; //声明一个客户端对象,用于与服务器进行连接 bool connstat = false; //连接状态 bool iswaitecho = false; //是否等待服务器回应 Ticker flipper; //时间中断 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++; //读取完成一个缓冲区 } } bool connNetMusic() { uint8_t i = 0; while (i < 5) { //最多连接5次 if (client.connect(WEBSERVERIP, WEBSERVERPORT)) { connstat = true; Serial.println("连接成功"); return true; } else { Serial.println("访问失败"); client.stop(); //关闭客户端 } i++; delay(100); } return false; } void playMusic() { digitalWrite(41, HIGH);digitalWrite(42, HIGH); if (connstat == true){ if (iswaitecho == false && (writep - readp) < 2) { client.write('n'); //申请一个缓冲片 iswaitecho = true; } if (client.available()) { //如果有数据可读取 num = client.read(netbuf[writep % 3], 1024); if (writep == 0 && readp == 0) { flipper.attach(0, onTimer); //开启定时中断 就是每秒中断20000次 } writep++; iswaitecho = false; } } } ``` 以上便是代码的各个模块配置,完整代码,可以去我的gitee库上下载,最终程序文件夹名字是arduino_final_test,其他文件夹是我对各个模块的功能测试,大家都可以拿来玩玩,一步一步的完成这个项目。 [码云]: https://gitee.com/iron2222/esp32 ## 结语 这个项目还有很多可以改善的的地方,比如FM的自动搜索较好频道功能,以及网络电台的连接等。 下一步我会使用刚搭建好的esp-idf平台重新开发,arduino平台开发起来有些不是那么的得心应手,祝我bug少少!!!