ESP32S2小项目,FM,网络时钟/电台,Arduino开发环境

效果展示

@

开机动画:

网络时钟:

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模块的物联网/音频信号处理平台

开发平台

可选择平台有:esp-idf、Arduino,CicruitPython,因为前段时间刚用Arduino平台玩过ESP8266模块,所以这里选择Arduino平台进行开发(我才不会告诉你们,我是因为esp-idf编译工具链没配置好)。

简单环境配置

第一步:首选项中开发板管理网址:

https://dl.espressif.com/dl/package_esp32_index.json

第二步:开发板管理器,找ESP32,下载

第三步:换开发板

因为下载太慢,一般会直接用别人下载好的ESP32的包,但问题是相当的多,给大家放一个我的环境配置历程图:

手动配置

最后把我成功试验过的一种方法告诉大家:

首先,下载解压我这个包

--来自百度网盘超级会员V4的分享

hi,这是我用百度网盘分享的内容~复制这段内容打开「百度网盘」APP即可获取

链接:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQh7p6CG-1643251689534)(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:

  1. //wifi用户名与密码
  2. char* ssid = "iron2222";
  3. char* password = "*******9009";
  1. //启动WiFi服务,这里是客户端(放在set up函数里)
  2. WiFi.begin(ssid, password);
  3. Serial.print("Connecting to "); // 串口监视器输出网络连接信息
  4. Serial.print(ssid); Serial.println(" ..."); // 告知用户正在尝试WiFi连接
  5. int i = 0; // 这一段程序语句用于检查WiFi是否连接成功
  6. while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函数的返回值是由WiFi连接状态所决定的。
  7. delay(1000); // 如果WiFi连接成功则返回值为WL_CONNECTED
  8. Serial.print(i++); Serial.print(' '); // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
  9. } // 同时NodeMCU将通过串口监视器输出连接时长读秒。
  10. // 这个读秒是通过变量i每隔一秒自加1来实现的。
  11. Serial.println(""); // WiFi连接成功后
  12. Serial.println("Connection established!"); // 将通过串口监视器输出"连接成功"信息。
  13. Serial.print("IP address: "); // 同时还将输出IP地址。这一功能是通过调用
  14. Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
  15. ipaddress = WiFi.localIP().toString();

网络时钟:

  1. //网络时钟设置
  2. const char *ntpServer = "pool.ntp.org";
  3. const long gmtOffset_sec = 8 * 3600;
  4. const int daylightOffset_sec = 0;
  1. // 从网络时间服务器上获取并设置时间,获取成功后芯片会使用RTC时钟保持时间的更新(放在set up函数里)
  2. configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  3. printLocalTime();
  1. //网络时钟显示函数
  2. void timer_show() {
  3. struct tm timeinfo;
  4. if (!getLocalTime(&timeinfo))
  5. {
  6. u8g2.clearBuffer();
  7. u8g2.setFontDirection(0);
  8. u8g2.setFont(u8g2_font_ncenB08_tr);
  9. u8g2.setCursor(0, 40);
  10. u8g2.print("Failed to obtain time");
  11. u8g2.setCursor(2,55);
  12. u8g2.print(ipaddress);
  13. u8g2.sendBuffer();
  14. return;
  15. }
  16. u8g2.clearBuffer();
  17. u8g2.setFontDirection(0);
  18. u8g2.setFont(u8g2_font_ncenB14_tr);
  19. u8g2.setCursor(20, 15);
  20. u8g2.print(&timeinfo, "%H:%M:%S");
  21. u8g2.setCursor(15, 35);
  22. u8g2.print(&timeinfo, "%Y/%m/%d");
  23. u8g2.setCursor(2,55);
  24. u8g2.print(ipaddress);
  25. u8g2.sendBuffer();
  26. }

FM收音机:

因为FM模块是通过I2C进行数据传输的,所以要打开相应的配置。

  1. //I2C引脚设置
  2. #define ESP32_I2C_SDA 5
  3. #define ESP32_I2C_SCL 4
  4. #define MAX_DELAY_RDS 40 // 40ms - polling method
  5. long rds_elapsed = millis();
  6. RDA5807 rx;
  1. // I2C相关设置(放在set up函数里)
  2. Wire.begin(ESP32_I2C_SDA, ESP32_I2C_SCL);
  3. rx.setup();
  4. rx.setVolume(0);//音量大小设置,可调
  5. delay(500);
  6. //FM相关设置
  7. rx.setFrequency(10650); //开启是频率,可调
  8. //使能SDR
  9. rx.setRDS(true);
  1. //FM模式显示函数
  2. void FM_show() {
  3. char str[64] = {0};
  4. u8g2.firstPage();
  5. u8g2.clearBuffer(); //清除内部缓冲区
  6. u8g2.setFontDirection(0); //设置字体方向
  7. u8g2.setFont(u8g2_font_ncenB14_tr); //设置字体
  8. u8g2.setCursor(15, 20);
  9. u8g2.print("FM Radio");
  10. u8g2.setFont(u8g2_font_ncenB10_tf);
  11. u8g2.setCursor(15, 40);
  12. sprintf(str, "%u MHz",rx.getFrequency() );
  13. u8g2.print(str);
  14. u8g2.setCursor(15, 55);
  15. sprintf(str, "Vol: %2.2u",rx.getVolume());
  16. u8g2.print(str);
  17. u8g2.sendBuffer();
  18. delay(1000);
  19. }

网络收音:

这里其实可以重点讲解一下,因为涉及到了DAC。关于什么是ADC/DAC大家可以看这篇博文:

博客园https://www.cnblogs.com/iron2222/p/15833426.html

CSDNhttps://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传输搭建了了独立的网络音频库,上面看到的那个黑色的模块。

  1. //网络收音
  2. uint16_t num=0;
  3. #define WEBSERVERIP "192.168.43.212"
  4. #define WEBSERVERPORT 3999
  5. uint8_t netbuf[3][1024]; //网络数据缓冲区
  6. uint16_t writep = 0; //写入数量
  7. uint16_t readp = 0; //读取数量
  8. WiFiClient client; //声明一个客户端对象,用于与服务器进行连接
  9. bool connstat = false; //连接状态
  10. bool iswaitecho = false; //是否等待服务器回应
  11. Ticker flipper; //时间中断
  12. uint16_t m_offset = 0;
  13. void onTimer(void) {
  14. if(readp<=writep) dacWrite(17, netbuf[readp % 3][m_offset++]); //播放一次声音
  15. if (m_offset >= 1024) {
  16. m_offset = 0;
  17. readp++; //读取完成一个缓冲区
  18. }
  19. }
  20. bool connNetMusic() {
  21. uint8_t i = 0;
  22. while (i < 5) { //最多连接5次
  23. if (client.connect(WEBSERVERIP, WEBSERVERPORT)) {
  24. connstat = true;
  25. Serial.println("连接成功");
  26. return true;
  27. } else {
  28. Serial.println("访问失败");
  29. client.stop(); //关闭客户端
  30. }
  31. i++;
  32. delay(100);
  33. }
  34. return false;
  35. }
  36. void playMusic() {
  37. digitalWrite(41, HIGH);digitalWrite(42, HIGH);
  38. if (connstat == true){
  39. if (iswaitecho == false && (writep - readp) < 2) {
  40. client.write('n'); //申请一个缓冲片
  41. iswaitecho = true;
  42. }
  43. if (client.available()) { //如果有数据可读取
  44. num = client.read(netbuf[writep % 3], 1024);
  45. if (writep == 0 && readp == 0) {
  46. flipper.attach(0, onTimer); //开启定时中断 就是每秒中断20000次
  47. }
  48. writep++;
  49. iswaitecho = false;
  50. }
  51. }
  52. }

以上便是代码的各个模块配置,完整代码,可以去我的gitee库上下载,最终程序文件夹名字是arduino_final_test,其他文件夹是我对各个模块的功能测试,大家都可以拿来玩玩,一步一步的完成这个项目。

码云https://gitee.com/iron2222/esp32

结语

这个项目还有很多可以改善的的地方,比如FM的自动搜索较好频道功能,以及网络电台的连接等。

下一步我会使用刚搭建好的esp-idf平台重新开发,arduino平台开发起来有些不是那么的得心应手,祝我bug少少!!!

祝大家有一个愉快的假期与春节哦!

ESP32S2小项目-FM-网络时钟/电台-Arduino开发环境的更多相关文章

  1. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. Arduino可穿戴开发入门教程Arduino开发环境介绍

    Arduino可穿戴开发入门教程Arduino开发环境介绍 Arduino开发环境介绍 Arduino不像我们使用的PC端操作系统一样,可以直接在操作系统中安装软件为操作系统编程.Arduino的软件 ...

  3. Arduino 002 --- 在Ubuntu(Linux) 中搭建Arduino开发环境

    在Ubuntu/Linux 中搭建Arduino开发环境 我的Ubuntu系统:Ubuntu 14.04.10 TLS 32位 需要安装的Arduino的版本:Arduino 1.6.11(最新版本) ...

  4. 【搭建开发环境】在 Windows XP 中参与开源项目,搭建 git 和 cygwin 开发环境

    引言 只有一台 Windows XP 家用机,却想在诸如 Git@OSC 之类的开源社区参与开发,本文提供一个入门级的开发环境搭建指引. 涉及工具:Eclipse,EGit,Cygwin. 欢迎来到 ...

  5. 树莓派上搭建arduino开发环境

    -------------还是博客园上面的格式看这舒服,不去新浪了------------- 为什么要在树莓派上开发arduino呢?总要把树莓派用起来嘛,不然老吃灰. 树莓派使用SSH时没有图形界面 ...

  6. 制作一个有趣的涂鸦物联网小项目(涂鸦模组SDK开发 CBU BK7231N WiFi+蓝牙模组 HSV彩色控制)

    实现的功能: l  APP控制月球灯 l  本地月球灯控制 l  APP控制"大白"颜色,实现各种颜色变身 l  门状态传感器状态APP显示 l  网络状态指示灯,连接服务器长亮, ...

  7. esp32(M5STACK) ARDUINO开发环境搭建(ubuntu)

    首先去官网下载arduino https://www.arduino.cc/en/main/software         由于国产链接下载慢的缘故,所以可以采用百度网盘的方式进行下载,具体下载方法 ...

  8. ESP32-S3 arduino 开发环境搭建

    ESP32-S3 arduino 简要描述 在github上搜索arduino-esp32,找到并打开espressif/arduino-esp32仓库,从master主分支切换到esp32-s3-s ...

  9. centos 6.X下建立arduino开发环境

    一.安装arduino IDE 1.下载linux下arduino IDE安装包,从网址:http://arduino.cc/en/Main/Software下载,如果这个网址打不开,可从网盘下载:h ...

随机推荐

  1. Java——HashMap集合详解

    第一章 HashMap集合简介 1.1 介绍 HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对.HashMap 的实现不是同步的,这意味着它不是线程安 ...

  2. [数学]高数部分-Part IV 一元函数积分学

    Part IV 一元函数积分学 回到总目录 Part IV 一元函数积分学 不定积分定义 定积分定义 不定积分与定积分的几何意义 牛顿-莱布尼兹公式 / N-L 公式 基本积分公式 点火公式(华里士公 ...

  3. MySQL数据操作与查询笔记 • 【第3章 DDL 和 DML】

    全部章节   >>>> 本章目录 3.1 使用 DDL 定义数据库表结构 3.1.1 SQL 简介 3.1.2 维护数据库和创建数据表 3.2 使用 DDL 维护数据库表结构 ...

  4. Eclipse远程调试Java代码的三种方法

    Eclipse远程调试Java代码的三种方法, 第1种方法是用来调试已经启动的Java程序,Eclipse可以随时连接到远程Java程序进行调试, 第2种方法可以调试Java程序启动过程,但是Ecli ...

  5. python 安装包时提示“unsupport command install”

    为什么提示找不到? 电脑安装了LoadRunnder,LoadRunner也有pip.exe,导致找不到python的exe 解决方法: 切换到python pip的路径进行安装,进到这个路径下,进行 ...

  6. Python 安装第三方模块时 报Retrying(Retry(total=4, connect=None, read=None, redirect=None, status=None))...[WinError 10061]由于目标计算机积极拒绝,无法连接 错误

    今日在安装ddt模块时(Windows系统),cmd报了一个以前从未见过的错误,如下图所示: 经百度,知是镜像源的问题,将安装命令改成如下命令: pip install ddt -i https:// ...

  7. django中写入数据时给密码加密

    方法一.在自定义的form表单中重写save方法: 方法二.使用信号量来实现 1. 在应用的模块下新建signal.py文件 2.编写回调函数,内容如下: 3. 在应用的app.py文件中的ready ...

  8. Linux上天之路(十六)之Shell编程一

    用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程.以前学过的cd.alias.u ...

  9. Autofac实现有条件的DI

    Autofac.Annotation框架是我用.netcore写的一个DI框架,基于Autofac参考 Spring注解方式所有容器的注册和装配,切面,拦截器等都是依赖标签来完成. 开源地址:http ...

  10. SpringBoot学习笔记一之本地环境基础搭建

    原文链接: https://www.toutiao.com/i6802935050196222471/ 工程创建 Maven创建工程 搜索maven找到project的创建 创建simple proj ...