Webstream über ESP32 zu Bluetooth-Lautsprecher senden

Hallo Community,

ich bin Anfänger im Thema Arduino-Programmierung und hoffe hier von den Experten einen Tipp zu bekommen.

Ich möchte mit einem ESP32-Modul einen Webstream eines Radiosendender empfangen und an einem externen Bluetooth-Lautsprecher senden.

Folgendes sollte bereits funktionieren:
-Verbindung mit W-lan
-Verbindung mit Host der Website
-Verbindung mit Bluetooth-Lautsprecher (wird akustisch vom Lautsprecher bestätigt)

Folgendes Problem:
-auf dem Lautsprecher hört man nur ein zyklisches Knacken

Mögliche Ursachen:
-die client.print "Get" - Anfrage an den Webserver hat einen Fehler oder funktioniert nicht. (ich weiß auch nicht genau wie ich das überprüfen kann.
-der client.read Datensatz passt nicht zu dem was ich an den Bluetooth lautsprecher senden muß. Evtl. müssen die Daten noch bearbeitet werden. Wenn ja wäre ich für einen Tipp dankbar wie man das machen muss.

Für ein paar Tipps wie ich den Webstream auf den Bluetooth Lautsprecher bekomme wäre ich sehr Dankbar.

Infos:
-ESP32 AZ-Delivery Dev Kit C V2 WROOM-32
-Arduino IDE 2.3.4

mfG
Mario Neubert

#include "AudioTools.h"
#include "AudioTools/AudioLibs/A2DPStream.h"
#include "WiFi.h"

BluetoothA2DPSource a2dp_source;
WiFiClient client;

const char *ssid =    "xxxx";
const char *password = "xxxx";
const char *BT_item = "FY-R919";
const char *URL = "https://strm112.1.fm/ccountry_mobile_mp3?aw_0_req.gdpr=true&listenerid=3cd4583ef17c17497c8ab6c47d9f1421&awparams=companionAds%3Atrue";
const char *host = "strm112.1.fm";
//const char *path = "/ccountry_mobile_mp3?aw_0_req.gdpr=true&listenerid=3cd4583ef17c17497c8ab6c47d9f1421&awparams=companionAds%3Atrue"; //Evergreens Kanal
const char *path = "/ccountry_mobile_mp3"; //Country Kanal
//const char *host = "ic.radiomonster.fm";
//const char *path = "/evergreens.ultra"; //Evergreens Kanal
int httpPort = 80;

int32_t get_sound_data(uint8_t* data, int32_t size) {

  int32_t result = client.read(data, size);
  return result;

}

void setup() {

    Serial.begin(115200);
    WiFi.disconnect();
    WiFi.softAPdisconnect(true);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("Read URL: ");
    Serial.println(URL);

    if (!client.connect(host, httpPort)) {
        Serial.println("Connection failed");
        return;
    }

    client.print(String("GET ") + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");

    a2dp_source.set_data_callback(get_sound_data);
    a2dp_source.start(BT_item); 

}

void loop() {
 if (!client.connected()) {
        Serial.println("Reconnecting...");
        if (client.connect(host, httpPort)) {
          Serial.println("connected to server");
          client.print(String("GET ") + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");  
        }
    }
}

Hallo, wenn du danach "esp32 wlan bluetooth gleichzeitig" googelst, wirst du sehr viel Beiträge finden, die dir sagen, dass es nicht funktioniert.
Mein Tipp, verwende einen zweiten ESP32 für Bluetooth oder WLan.

Hallo HotSystems,

danke für deine Antwort. Das erklärt dass ich immer nur Artikel entweder für das Abrufen des Webstreams oder für das versenden via Bluetooth gefunden habe und nie für beides zusammen.

Abgesehen davon das der ESP32 das wohl Hardware technisch nicht kann, wäre der Code so ok? Vor allem die Zeile:

int32_t result = client.read(data, size);

Spricht was dagegen das mit einem HC-06 zu realisieren oder ist das zu Zeitkritisch?
Kann ich dann die A2DPStream lib noch nutzen?

Danke für die Hilfe.

mfG
Mario

Sorry, da muss ich passen, da ich mit Bluetooth noch nichts gemacht habe.

Dein aktuelles Projekt löse ich per Smartphone oder Tablet. Da muss ich dann nicht selbst etwas entwickeln. :wink:

Wenn, würde ich es mit 2 x ESP32 machen und die Audiodaten per I2S Protokoll übertragen.

Hmm... Du benutzt eine TCP Verbindung und machst da von Hand ein unverschlüsseltes HTTP drauf.

Deine URL fängt mit HTTPS an. Also verschlüsseltes HTTP. Es könnte durchaus sein, das der Service nicht unverschlüsselt angeboten wird und du deshalb keine Daten für den Decoder bekommst.

Lass dir mal den Response Header nach den client.connect() auf der Seriellen Schnittstelle ausgeben.

Jetzt weiß ich nicht ob a2dp_source einen MP3 Stream verarbeiten kann oder ob der erst zu PCM dekodiert werden muss.

Und warum gehts nicht? Ich kann mir schwer vorstellen, das Espressif kein RF Coexistence implementiert hat.

Frage:

Muss der ESP-32 eigentlich vom Lautsprecher weg stehen. ??

Wenn nein, wieso kaufst du dir für 2-3 Euro kein i2s-VERSTÄRKER Modul. Hängst da die Lautsprecher per Kabel dran und versteckst den ESP32 in der Nähe des Lautsprechern.

Steuern kann man das sicher mit einen einfachen WEB-Interface.

(Bis auf das Web-Interface habe ich das nämlich genau SO gebaut, bei meinen Virtuellen Plattenspieler)

Habe gerade mal gegooglet. Es gibt auch fertige Module die man an den i2s hängen kann und die die BT-Verbindung machen.
z,b. : https://ozrobotics.com/shop/bluetooth-5-3-audio-transmitter-board-i2s-digital-input-tsa5001/
Gruß

Pucki

Naja....da ich selbst noch keine derartige Sache nachgebaut habe, kann ich mich nur auf die entsprechenden Beiträge beziehen.
Die besagen, es gibt nur ein Funkmodul (Transceiver) im Chip und das kann bedeuten:
Gleichzeitiges Funken auf unterschiedlichen Kanälen nicht möglich.

Hallo,

und danke für die Antworten.

@Rintin, die URL wird im Code nicht benutzt. Ich hatte die Ausgabe mit der Audio lib und dem MAX98357A auf einen Lautsprecher versucht. Das hatte auch funktioniert allerdings möchte ich gern mein Bluetooth Lautsprecher nutzen. Im Code wird nur der host, port und path weiterverwendet. Die Header Ausgabe werde ich nachher mal versuchen.

@Pucki007, ich habe so ein Retro-Bluetooth Radio. Das soll im Gäste WC stehen weil es dort schön reinpassen würde. Das Radio hat nur nur FM und Bluetooth keinen Externen Lautsprecheranschluß. Da ich gerade einen Spiegelschrank für das WC baue hatte ich mir gedacht ich bau einfach einen ESP32 mit rein der den Webstream zu mein BT-Radio sendet. Ich hatte gedacht das es nicht so kompliziert sein kann, da der ESP ja Wlan und BT an Board hat. Die Module werde ich mir mal näher anschauen.

@Rintin & Hotsystems
Es wäre schön wenn der ESP32 das ohne Anbauteile könnte. Da ich aber noch nicht genau weiß wo der Fehler liegt, kann ich aber auch nicht sagen ob der ESP32 BT und Wlan zeitgleich kann. Was ich aber sagen kann ist, dass die Wlan verbindung zum Host steht und er dann noch die Verbindung zum Bluetooth Radio aufgebaut hat. Das hätte dann ja auch nicht funktionieren dürfen, oder?

Vielen Dank für eure Hilfe
mfG
Mario

Das ist wohl so. Aber Wifi und BT senden ja nicht durchgehend. Vielmehr hast du arbeiten die Paketorientiert und zwischen den Paketen ist "nichts auf der Leitung los". Da kann das Framework ja auf ein anderes Protokoll umschalten.

Hallo Rintin,

das wäre schön wenn das gehen würde.
Kannst du mir evtl. einen Tipp oder Codeschnipsel geben wie ich das in meinen Code implementieren kann?

Vielen Dank

Da ich mich nur nach den entsprechenden Beiträgen orientieren kann, die bisher sagen, es geht nicht, kann ich auch keine andere Aussage machen.

Ich lasse mich gern eines besseren belehren, wenn es doch geht. Entsprechende Beiträge sind hier gern gesehen.

Hast du mal den Code dazu?

Im Grunde dürftest du da diese Komponenten wiederfinden:
web-bt-radio

Mit etwas Glück musst du nur 2 Zeilen Code ändern um das Output anders zu realisieren.

Ok, so hatte ich die Ausgabe über den MAX98357A mit angeschlossenen Lautsprecher gemacht. Ich weiß nur nicht wie ich das im A2DP Format über Bluetooth ans Radio gesendet bekomme.

#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"

#define I2S_DOUT    25
#define I2S_BCLK    26
#define I2S_LRC     27
#define I2S_GAIN    32
#define I2S_SD      33


Audio audio;

String ssid =    "XXX";
String password = "XXXXXXX";

const char *URL = "https://strm112.1.fm/ccountry_mobile_mp3?aw_0_req.gdpr=true&listenerid=3cd4583ef17c17497c8ab6c47d9f1421&awparams=companionAds%3Atrue";

void setup() {

    //pinMode(I2S_GAIN, INPUT_PULLUP);
    //digitalWrite(I2S_GAIN, HIGH); 

    pinMode(I2S_SD, OUTPUT);
    digitalWrite(I2S_SD, LOW);

    Serial.begin(115200);
    WiFi.disconnect();
    WiFi.softAPdisconnect(true);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("Read URL: ");
    Serial.println(URL);

    digitalWrite(I2S_SD, HIGH);

    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
    audio.setVolume(100);
    audio.connecttohost(URL);

}

void loop()

{
  audio.loop();    
}

Audio.h dürfte diese Library sein:

So direkt in der API der Klasse Audio seh ich jetzt keine Möglichkeit an den PCM Buffer zu kommen.

Jedoch gibt es diese Funktion:

extern __attribute__((weak)) void audio_process_i2s(int16_t* outBuff, uint16_t validSamples, uint8_t bitsPerSample, uint8_t channels, bool *continueI2S); // record audiodata or send via BT

Vielleicht da mal nach Beispielen zu suchen...

Hab mal ein wenig gespielt.

  • BluetoothA2DPSource und Audio zusammen benötigen zu viel RAM. Der ESP32 landet in einer Bootloop weil das FreeRTOS seine Strukturen nicht initialisieren kann.

  • Streamen einer unkomprimierten WAV mit Ausgabe über BT geht zwar, aber abhängig davon was die Nachbarn gerade durch die Luft pusten geht die Datenrate vom WIFI soweit in den Keller, das es Bufferunderruns gibt.

Mein Fazit an der Stelle ist: Es könnte funktionieren, ist dann aber nicht so trivial.

Meine Idee hat sich erledigt:

#error "ESP32C3, ESP32S2, ESP32S3... do not support A2DP"

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.