需求:
-
与蓝牙手环连接,获取运动数据,上传到服务器
-
从服务器上下载音频,保存在本地播放
2021.5.24
购回一个立体声解码器模块,I2S UDA1334A,某宝十几元。
先试试这个蓝牙播放功能:ESP32 作为蓝牙音频接收端
- 硬件连接
UDA1334A – ESP32
VIN – +
3VO – 空(这是输出3V)
GND – -
WSEL – 27 (Word Select or Left/Right Clock 指示什么时候左或右被传送)
DIN – 25 (Data In 音频数据输入)
BCLK – 26 (Bit Clock 告诉放大器何时在数据引脚上读取数据的引脚)
其它控制: Mute:将此引脚设置为高电平将使输出静音
-
下载库:https://github.com/tierneytim/btAudio
-
代码
#include <btAudio.h>
// 启动一个蓝牙音频功能,它接收蓝牙音频进行播放
btAudio audio = btAudio("ESP_Speaker");
void setup() {
// 将音频数据流传输到ESP32
audio.begin();
// 将收到的数据输出到一个I2S DAC https://www.adafruit.com/product/3678
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);
}
void loop() {
}
也是相同的,做了一个蓝牙音频接收器
这里BluetoothA2DPSink.cpp中的端口与我的不符,可修改。
#include "BluetoothA2DPSink.h"
BluetoothA2DPSink a2dp_sink;
void setup() {
a2dp_sink.start("MyMusic");
}
void loop() {
}
- 过程
在测试过程中,如果dout线接上了模块上的Lout或Rout,也是有音频输出的,杂音非常大。相当于没有使用模块,直接从ESP上输出
这实现的是:别人让我放。我想实现:我让别人放。 :)
这个代码实现了通过网络播放mp3,当然还不只于此。
当网络不好时,需要进行处理。
中途可以通过串口发送网址,播放此网址的音乐。例如听听在线广播音频:
80后音悦台 http://lhttp.qingting.fm/live/20207761/64k.mp3
怀集音乐之声 http://lhttp.qingting.fm/live/4804/64k.mp3
海峡之声新闻广播 http://lhttp.qingting.fm/live/1744/64k.mp3
动听音乐网络电台 http://lhttp.qingting.fm/live/5022107/64k.mp3
民歌悠扬 https://lhttp.qingting.fm/live/15318585/64k.mp3
汽车音乐1029·河北经典音乐广播 http://lhttp.qingting.fm/live/5021743/64k.mp3
深圳新闻广播 http://lhttp.qingting.fm/live/1270/64k.mp3
看起来mp3格式的大部份能放,更多的自己搜索吧 www.radio-browser.info
//
// https://github.com/schreibfaul1/ESP32-audioI2S
//
//
#include "Arduino.h"
#include "WiFiMulti.h"
#include "Audio.h"
#include "SPI.h"
#include "SD.h"
#include "FS.h"
// Digital I/O used
#define SD_CS 5
#define SPI_MOSI 23
#define SPI_MISO 19
#define SPI_SCK 18
#define I2S_DOUT 25
#define I2S_BCLK 26
#define I2S_LRC 27
Audio audio;
WiFiMulti wifiMulti;
String ssid = "Ease";
String password = "123456789";
void setup() {
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
SPI.setFrequency(1000000);
Serial.begin(115200);
SD.begin(SD_CS);
WiFi.mode(WIFI_STA);
wifiMulti.addAP(ssid.c_str(), password.c_str());
wifiMulti.run();
if(WiFi.status() != WL_CONNECTED){
WiFi.disconnect(true);
wifiMulti.run();
}
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(16); // 0...21
// audio.connecttoFS(SD, "/320k_test.mp3");
// audio.connecttoFS(SD, "test.wav");
// audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u");
// audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx");
// audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac
// audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3
audio.connecttohost("http://i.scwy.net/m.mp3"); // 128k mp3
// audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de");
}
void loop()
{
audio.loop();
if(Serial.available()){ // put streamURL in serial monitor
audio.stopSong();
String r=Serial.readString(); r.trim();
if(r.length()>5) audio.connecttohost(r.c_str());
log_i("free heap=%i", ESP.getFreeHeap());
}
}
// optional
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}
void audio_id3data(const char *info){ //id3 metadata
Serial.print("id3data ");Serial.println(info);
}
void audio_eof_mp3(const char *info){ //end of file
Serial.print("eof_mp3 ");Serial.println(info);
}
void audio_showstation(const char *info){
Serial.print("station ");Serial.println(info);
}
void audio_showstreamtitle(const char *info){
Serial.print("streamtitle ");Serial.println(info);
}
void audio_bitrate(const char *info){
Serial.print("bitrate ");Serial.println(info);
}
void audio_commercial(const char *info){ //duration in sec
Serial.print("commercial ");Serial.println(info);
}
void audio_icyurl(const char *info){ //homepage
Serial.print("icyurl ");Serial.println(info);
}
void audio_lasthost(const char *info){ //stream URL played
Serial.print("lasthost ");Serial.println(info);
}
void audio_eof_speech(const char *info){
Serial.print("eof_speech ");Serial.println(info);
}
2021.5.25
以下代码实现了蓝牙播放
#include "BluetoothA2DPSource.h"
#include <math.h>
#define c3_frequency 130.81
BluetoothA2DPSource a2dp_source;
// The supported audio codec in ESP32 A2DP is SBC. SBC audio stream is encoded
// from PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data
int32_t get_data_channels(Channels *channels, int32_t channel_len) {
static double m_time = 0.0;
double m_amplitude = 10000.0; // -32,768 to 32,767
double m_deltaTime = 1.0 / 44100.0;
double m_phase = 0.0;
double double_Pi = PI * 2.0;
// fill the channel data
for (int sample = 0; sample < channel_len; ++sample) {
double angle = double_Pi * c3_frequency * m_time + m_phase;
channels[sample].channel1 = m_amplitude * sin(angle);
channels[sample].channel2 = channels[sample].channel1;
m_time += m_deltaTime;
}
return channel_len;
}
void setup() {
a2dp_source.start("SPEAKER", get_data_channels); // SPEAKER是要连接的蓝牙音箱
}
void loop() {
}
接下来看如何将网络mp3,通过蓝牙放出来。
据说这是播放SD上mp3到蓝牙的,我还没测试
SD ESP32 VCC 5V GND GND CS CS GP5 SCK SCK GP18 MOSI MOSI GP23 MISO MISO GP19
#include <SPI.h>
#include <SD.h>
#include "AudioFileSourceSD.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputWithCallback.h"
#include "BluetoothA2DPSource.h"
#include "AudioTools.h"
using namespace audio_tools;
const int sd_ss_pin = 5;
const char* fileName = "/audio.mp3";
BluetoothA2DPSource a2dp_source;
AudioFileSourceSD *file;
AudioGeneratorMP3 *mp3;
AudioOutputWithCallback *out;
// callback used by A2DP to provide the sound data
int32_t get_sound_data(Channels* data, int32_t len) {
return out == nullptr ? 0 : out->read(data, len);
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
audioLogger = &Serial;
// Setup Audio
file = new AudioFileSourceSD();
mp3 = new AudioGeneratorMP3();
out = new AudioOutputWithCallback(512,5);
// Open MP3 file and play it
SD.begin(sd_ss_pin);
if (file->open(fileName)) {
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.start("MyMusic", get_sound_data);
// start to play the file
mp3->begin(file, out);
Serial.printf("Playback of '%s' begins...\n", fileName);
} else {
Serial.println("Can't find .mp3 file");
}
}
// Arduino loop - repeated processing
void loop() {
if (mp3->isRunning()) {
if (!mp3->loop()) mp3->stop();
} else {
Serial.println("MP3 done");
delay(10000);
}
}
https://github.com/pschatzmann 此人的相关内容可以看看