(原) 继续EPS32研究

原创文章,请后转载,并注明出处。

需求:

  1. 与蓝牙手环连接,获取运动数据,上传到服务器

  2. 从服务器上下载音频,保存在本地播放


2021.5.24

购回一个立体声解码器模块,I2S UDA1334A,某宝十几元。

先试试这个蓝牙播放功能:ESP32 作为蓝牙音频接收端

  1. 硬件连接

UDA1334A – ESP32

VIN – +

3VO – 空(这是输出3V)

GND – -

WSEL – 27 (Word Select or Left/Right Clock 指示什么时候左或右被传送)

DIN – 25 (Data In 音频数据输入)

BCLK – 26 (Bit Clock 告诉放大器何时在数据引脚上读取数据的引脚)

其它控制: Mute:将此引脚设置为高电平将使输出静音

  1. 下载库:https://github.com/tierneytim/btAudio

  2. 代码

#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() {
}
  1. 过程

在测试过程中,如果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 此人的相关内容可以看看