项目介绍
设计一款能够播放网络电台的收音机,具体要求如下:
- 使用M5StickC Plus通过WiFi模块连接网络
- 在M5StickC Plus上进行解码,并通过提供的扬声器模块播放音乐
- 在M5StickC Plus上能够切换电台,并将电台的信息显示在LCD屏幕上
所使用的器件如下:
-
M5StickC Plus一套
-
扬声器板一块
开发平台介绍
M5StickC PLUS 主控采用ESP32-PICO-D4模组,具备蓝牙4.2与WIFI功能,机身内部集成了丰富的硬件资源,如红外、RTC、麦克风、LED、IMU、按键、蜂鸣器、PMU等,包含1.14寸、135*240分辨率的TFT屏幕,电池容量达到120mAh,接口同样支持HAT与Unit系列产品。
产品特性
-
基于 ESP32开发,支持WiFi、蓝牙
-
内置3轴加速计与3轴陀螺仪
-
内置Red LED
-
集成红外发射管
-
内置RTC
-
集成麦克风
-
用户按键, LCD(1.14 寸), 电源/复位按键
-
120 mAh 锂电池
-
拓展接口
-
集成无源蜂鸣器
-
可穿戴 & 可固定
-
开发平台 UIFlow, MicroPython, Arduino
设计思路
本应用设计思路非常清晰,将设备连接网络后,访问网络广播地址,解析数据后进行播放即可。同时需要绘制界面显示网络电台信息和系统状态,并设置按键用于功能控制。由于M5StickC Plus平台内置加速度传感器,在进行项目实现时增加了通过旋转设备实现电台切换的功能。整体流程如下图所示:
最终显示效果图如下,左侧为M5StickC Plus开发平台,右侧为扬声器模块。可以直观看到屏幕中显示了当前的电台信息和播放状态。平台的G26引脚用于输出音频信号,可以与扬声器模块进行直接连接,不需要额外接线。
设计要点
M5官方为Arduino平台提供了常用API,能够快速实现联网、屏幕显示、按键控制等功能,本应用设计的主要难点是如何播放网络电台信息。
扬声器模块没有搭配DAC,需要使用芯片内部的DAC输出音频信号。由于平台的处理器是ESP32芯片,电子森林平台已经有比较多的案例给出了使用ESP ADF开发框架播放在线音频的具体方案。但ESP ADF的使用存在一定门槛,且较难进行快速产出,被留为了备选方案。
通过搜索,本人在Github平台上找到了专门为M5平台封装的网络电台播放器,将其加载到Arduino后,便可进行高效开发。播放器支持播放M3U8格式的网络广播地址,创建好播放器对象后设置地址即可自动播放,并且支持换台功能。默认情况下采用G26引脚直接输出模拟音频。下面是使用该库播放网络广播的简单例子:
#include <M3U8Player.h>
M3U8Player *player;
String stationUrl = "http://xxxx/xxxx/playlist.m3u8";
player = new M3U8Player(stationUrl);
player->start();
在进行简单的界面设计时,发现M5官方的LCD显示库默认状态下不能显示汉字信息,经过一番查找在官方的Github仓库找到了汉字显示的代码。需要使用M5.Lcd.loadHzk16()
加载汉字库后,再使用M5.Lcd.writeHzk(text)
绘制待显示的内容。另外,中文字符需要采用GB2312编码保存,与arduino默认编码不同。本项目工程中的stationinfo.h
文件包含了将要播放的站点信息,其采用GB2312格式进行保存,修改时需要留意。
为支持姿态控制功能,本人使用了M5.IMU.getAccelData(&accx, &accy, &accz)
获取了三个方向的加速度,随后通过阈值判断对不同旋转方向进行识别。姿态识别后,会更新当前播放的电台序号并重新绘制屏幕内容。为避免连续时间内进行多次识别,这里简单增加了一秒钟的延时。
项目主要代码如下:
#include <M5StickCPlus.h>
#include <WiFi.h>
#include <M3U8Player.h>
#include <SD.h>
#include "stationinfo.h"
// Write your SSID and Password here
#define SSID "esptest"
#define PASSWD "123456789"
M3U8Player *player;
uint8_t cur_station_id = 0;
float accx, accy, accz;
bool isMuted = false;
enum RadioStatus { STOP, PLAY } cur_status;
void print(const char *text) {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(5, 0);
M5.Lcd.printf("%s", text);
}
void drawScreen() {
M5.Lcd.fillScreen(BLACK);
if (cur_status == PLAY) {
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("Playing");
} else {
M5.Lcd.setCursor(10, 10);
M5.Lcd.print("Stop");
}
M5.Lcd.drawLine(0, 40, 205, 40, ORANGE);
M5.Lcd.setCursor(10, 45);
M5.Lcd.writeHzk(stationName[cur_station_id]);
}
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.loadHzk16();
M5.Lcd.setTextSize(2);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWD);
M5.IMU.Init();
print("WiFi Connecting...");
while (!WiFi.isConnected()){ delay(10); }
cur_status = PLAY;
player = new M3U8Player(stations[cur_station_id], 100.0, true);
drawScreen();
}
// 判断姿态
void judgePitch() {
if (accx < -0.9) {
cur_station_id = cur_station_id - 1 + stationNumber;
cur_station_id %= stationNumber;
player->changeStationURL(stations[cur_station_id]);
drawScreen();
delay(1000);
} else if (accx > 0.9) {
cur_station_id = cur_station_id + 1 + stationNumber;
cur_station_id %= stationNumber;
player->changeStationURL(stations[cur_station_id]);
drawScreen();
delay(1000);
}
}
void loop() {
M5.IMU.getAccelData(&accx, &accy, &accz);
judgePitch();
M5.update(); // 按键读取
if (M5.BtnA.isPressed()){
cur_station_id = cur_station_id + 1;
cur_station_id %= stationNumber;
player->changeStationURL(stations[cur_station_id]);
drawScreen();
delay(1000);
}
if (M5.BtnB.isPressed()){
float nextVolume = isMuted ? 100.0 : 0.0;
player->setVolume(nextVolume);
isMuted = !isMuted;
if (cur_status == PLAY) {
cur_status = STOP;
} else {
cur_status = PLAY;
}
drawScreen();
delay(1000);
}
delay(100);
}
总结
M3U8Player库大大简化了项目代码,但该库仅支持m3u8格式的网络电台,不能处理如 http://ngcdn002.cnr.cn/live/jjzs/index.m3u8 结构的复杂地址。如果想要实现更好的效果,则必须要对其内部的代码进行修改。
目前的项目实现中,网络电台的地址是直接写在代码里的,如果想要增删电台则必须重新编译下载程序。为实现更好的效果,可以构建服务器,对电台内容进行在线调整,或接入蜻蜓FM等平台获取在线电台地址。
目前的的项目实现中,屏幕的显示内容相对简单,可以参照优秀项目,重新设计显示界面。并且可以增加时间显示或动态LOGO,丰富整个屏幕的内容。
参考资料
- M3U8格式的网络电台地址:M3U8/radio.m3u at master · reysc/M3U8 (github.com)
- 使用外部DAC构建的网络收音机,包含网络数据的处理代码:基于HTTPS长连接的ESP32+VS1053网络电台收音机Arduino代码悟渔的博客-CSDN博客esp32 网络收音机
- 使用M5StickC构建的网络收音机,实测不能连续播放音频:Arduino Web Radio Player - Hackster.io
- M3U8在线播放器 - 刘明野的工具箱 (liumingye.cn)