Forum: Mikrocontroller und Digitale Elektronik Audio-Ansage-Player mit Esp8266


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich bastele an einer Audio-Ansage (ca. 1 Min), die von einem ESP8266 auf 
Knopfdruck per PWM abgespielt werden soll. Ich kenne die Beispiele mit 
externen MP3-Chips oder wenigstens einer SD-Karte, aber ...

Auf dem Wege zu einer möglichst minimalistischen Lösung, versuche ich 
gerade mal ein binäres Array mit den 8-Bit-PCM-Werten in PROGMEM 
unterzubringen. Meine Daten sind ca. 850k groß und ich habe mir ein Tool 
programmiert, was mir die in diese Form bringt:
1
const byte data[] PROGMEM = {0x80,0x80,0x80, ... ,0x80,0x7F,0x80}

Zum Lesen der Bytes verwende ich diese Syntax, die auch problemlos durch 
den Compiler (Arduino IDE) läuft:
1
myChar =  pgm_read_byte(data[pos]);
2
Serial.println(myChar);

Leider zeigt der serielle Monitor nicht testweise die gelesenen Werte 
an, sondern (für mich) sofort nach dem Hochladen wilde Fehlermeldungen:
1
Exception (3):
2
epc1=0x40201c32 epc2=0x00000000 epc3=0x00000000 excvaddr=0x4022e6cc depc=0x00000000
3
4
ctx: cont 
5
sp: 3ffef1c0 end: 3ffef390 offset: 01a0
6
7
>>>stack>>>
8
3ffef360:  3fffdad0 00000000 3ffee35c 40201c27  
9
3ffef370:  feefeffe feefeffe 3ffee35c 4020201c  
10
3ffef380:  feefeffe feefeffe 3ffee370 40100114  
11
<<<stack<<<

Ist das ein Syntax-Problem oder hängt das mit dem zu großen Datenblock 
im PROGMEM zusammen? Die IDE ziegt nach dem Compilieren, dass (nur) 70% 
belegt wären ... Danke für Tips.

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Serial.println(myChar);

ist denn myChar printable oder wolltest du HEX Werte ausgeben?

Serial.print(78, HEX) gives "4E"

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

wenn es ein ESP8266-12 mit 4MB Flash ist, pack den Kram doch als 
passendes Wave in das SPIFFS.
Ansonsten schau Dir die ESP8266Audio-Lib an, die enthält eigentlich 
alles schon.

Gruß aus Berlin
Michael

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Michael U. schrieb:
> Hallo,
>
> wenn es ein ESP8266-12 mit 4MB Flash ist, pack den Kram doch als
> passendes Wave in das SPIFFS.
> Ansonsten schau Dir die ESP8266Audio-Lib an, die enthält eigentlich
> alles schon.
>
> Gruß aus Berlin
> Michael

Ok, danke für den Hinweis ... "SPIFFS" war mir bisher nicht so richtig 
ein Begriff, werde mich damit beschäftigen. Kann man von dort aus 
byteweise lesen?

Es ist ein "Wemos D1 Mini", ist das der genannte ESP8266-12 ... ?

von Michael U. (amiga)


Lesenswert?

Hallo,

Frank E. schrieb:
> Ok, danke für den Hinweis ... "SPIFFS" war mir bisher nicht so richtig
> ein Begriff, werde mich damit beschäftigen. Kann man von dort aus
> byteweise lesen?

File öffnen und dann eben readBytes() usw.
Mein Vorschlag zur ESP8266Audio kam nur deshalb, weil Du da in den 
Beispielen vermutlich schon passendes für alles findest.
Ausgabe vom Flash, vom SPIFFS, von SD-Card, von Webstream. Format wave, 
flac, mp3 usw. in Software (MP3 besser mit einem ESP32), Ausgabe per 
I2S, Software-DAC usw.

https://github.com/earlephilhower/ESP8266Audio

Ist nur ein Vorschlag, kann man natürlich auch "zu Fuß" selber machen.
Vor Jahren habe ich ähnliches mal für einen Bekannten auf einem Mega88 
mit externem SPI-Flash und DAC gemacht, 22kHz/16Bit WAV-Files. Hatte ich 
auch mit 8Bit Samples und PWM-Ausgabe auf einem Tiny85 bei 64MHz 
PLL-Takt laufen, der hat 4 kurze Sounds aus dem Flash gespielt.
Oha, ich sehe gerade: das ist ja schon 10 Jahre her...

Gruß aus Berlin
Michael

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Danke, in der Audio.Lib gibt es ein Beispiel "PlayWavefromProgmem", was 
meiner Absicht recht nahe kommt.

Allerdings konnte ich eine Info nirgendwo im Web finden: Wie groß dürfen 
Daten im Progmem des ESP8266 (Wemos D1 Mini) eigentlich sein? Trial & 
Error ist mir zu mühselig, weil ja auch das Compilieren richtig lange 
dauert ...

Danke für Info.

von Michael U. (amiga)


Lesenswert?

Hallo,

mehr als 1MB hast Du als Programmflash und damit auch als Progmem nicht 
zur Verfügung. Davon belegen die Standardroutinen ohnehin schon rund 
250kB.
Leg Deine Daten als Datei ins SPIFFS, da hast Du knapp 3MB als Filegröße 
verfügbar. Beispiel müßte in der Lib auch dabei sein, zumindest ist es 
kein größeres Problem, die Komponenten der Lib passend 
zusammenzustellen.

Compilieren: Was ist bei Dir "richtig lange"? Ich habe gerade mal meinen 
Webserver compiliert, mit OTA, SPIFFS usw., Durchlauf 1m 5s, geflasht 
habe ich jetzt nicht, mache ich generell mit 921600 bei den ESP8266.

Gruß aus Berlin
Michael

von Timmo H. (masterfx)


Lesenswert?

Mit plattform io ist das Kompilieren in ein paar Sekunden durch. Arduino 
IDE ist arg lahm. Gerade mal Tasmota kompilieren lassen, das dauert 
keine 30 Sekunden.
Wenn du dann noch das example vom ESP8266webserver einbindest kannst du 
deine Wav-Files bequem via webinterface ins SPIFFS hochladen

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

30s oder hut 1min ist doch "jammern auf hohem Niveau" ;-).
Ich frage mal meinen Bekannten, wie lange so ein Linux-Kernel 
compiliert...

Timmo H. schrieb:
> Wenn du dann noch das example vom ESP8266webserver einbindest kannst du
> deine Wav-Files bequem via webinterface ins SPIFFS hochladen

Genau das wäre mein Ansatz. Zumal die ESP8266Audio die üblichen Formate 
direkt lesen und ausgeben kann.

Gruß aus Berlin
Michael

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Der Threat ist schon älter, ich weiss, aber ich habe noch eine (neue) 
Frage dazu:

Ich habe das oben genannte Projekt mit der Audio-Lib (MP3 in SPIFFS) 
umgesetzt und es funktioniert auch ganz grundsätzlich. Zur Soundausgabe 
benutze ich den RX-Pin ("fake DAC").

Was auf die Dauer doch ein wenig nervt, sind die enormen Störgeräusche 
(auch wenn gerade kein File gespielt wird). Die Audio-Ausgabe klingt, 
wie neben einem Lagerfeuer am Bach. Also ständiges Kinstern, Zischeln 
etc., obwohl ich ein RC-Glied (10k in Reihe, 100nF nach Masse) zumm 
Verstärker dran habe und sämtliche WLAN-Funktionen (soweit das mit der 
Arduino-Lib möglich ist), deaktivert sind.

Aus Gründen der Dateigröße habe ich meine MP3-Files nur mono mit 22kHz 
codiert. Aber das ist es nicht. Höre ich mir die auf dem PC an, klingen 
sie zwar nicht besonders brilliant - logisch - aber sind frei von 
Störgeräuschen.

Was könnte man noch tun (abgesehen von externem DAC oder 
MP3-Player-Chip)?

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

Frank E. schrieb:
> Ich habe das oben genannte Projekt mit der Audio-Lib (MP3 in SPIFFS)
> umgesetzt und es funktioniert auch ganz grundsätzlich. Zur Soundausgabe
> benutze ich den RX-Pin ("fake DAC").

ich habe die Ausgabe damals nur kurz getestet und auch keine anhörbaren 
Ergebnisse erziehlt. Allerdings nur kurz weil ohnehin ein I2S-DAC bei 
mir dranhängt. Wenn es in Dein Projkt passt, nimm sowas und gebe über 
I2S aus:
https://www.amazon.de/s?k=B01GFNYKK6

Die MAX98357A Module sind leider nicht ganz so super billig.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Alexander (alecxs)


Lesenswert?

Hallo, ich bekomme leider keinen Ton raus mit der ESP8266Audio Library 
in der Arduino IDE. Habe nun schon alles neu installiert, keine 
Besserung. Ich sehe zwar die Sample Rate 48 KHz der MP3-Datei auf dem 
Oszilloskop, aber da ist nichts "aufmoduliert". Wenn ich die Sample Rate 
der Datei "pno-cs.mp3" mit Audacity auf 16 KHz ändere, sehe ich auf dem 
Oszilloskop nun die 16 Khz. Laut Serial Monitor läuft auch etwas. Hören 
kann man aber nichts.

Ich nutze die Arduino IDE weil das nur ein Teilprojekt ist, welches 
später zu einem Arduino Projekt hinzugefügt werden soll.
1
#include <Arduino.h>
2
#if defined(ARDUINO_ARCH_RP2040)
3
void setup() {}
4
void loop() {}
5
#else
6
7
#ifdef ESP32
8
  #include <WiFi.h>
9
  #include "SPIFFS.h"
10
#else
11
  #include <ESP8266WiFi.h>
12
#endif
13
#include "AudioFileSourceSPIFFS.h"
14
#include "AudioFileSourceID3.h"
15
#include "AudioGeneratorMP3.h"
16
#include "AudioOutputI2S.h"
17
18
// To run, set your ESP8266 build to 160MHz, and include a SPIFFS of 512KB or greater.
19
// Use the "Tools->ESP8266/ESP32 Sketch Data Upload" menu to write the MP3 to SPIFFS
20
// Then upload the sketch normally.  
21
22
// pno_cs from https://ccrma.stanford.edu/~jos/pasp/Sound_Examples.html
23
24
AudioGeneratorMP3 *mp3;
25
AudioFileSourceSPIFFS *file;
26
AudioOutputI2S *out;
27
AudioFileSourceID3 *id3;
28
29
30
// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc.
31
void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
32
{
33
  (void)cbData;
34
  Serial.printf("ID3 callback for: %s = '", type);
35
36
  if (isUnicode) {
37
    string += 2;
38
  }
39
  
40
  while (*string) {
41
    char a = *(string++);
42
    if (isUnicode) {
43
      string++;
44
    }
45
    Serial.printf("%c", a);
46
  }
47
  Serial.printf("'\n");
48
  Serial.flush();
49
}
50
51
52
void setup()
53
{
54
  WiFi.mode(WIFI_OFF); 
55
  Serial.begin(115200);
56
  delay(1000);
57
  SPIFFS.begin();
58
  Serial.printf("Sample MP3 playback begins...\n");
59
60
  audioLogger = &Serial;
61
  file = new AudioFileSourceSPIFFS("/pno-cs.mp3");
62
  id3 = new AudioFileSourceID3(file);
63
  id3->RegisterMetadataCB(MDCallback, (void*)"ID3TAG");
64
  out = new AudioOutputI2S();
65
  mp3 = new AudioGeneratorMP3();
66
  mp3->begin(id3, out);
67
}
68
69
void loop()
70
{
71
  if (mp3->isRunning()) {
72
    if (!mp3->loop()) mp3->stop();
73
  } else {
74
    Serial.printf("MP3 done\n");
75
    delay(1000);
76
  }
77
}
78
#endif

Mir ist nicht ganz klar ob ich AudioOutputI2S() oder 
AudioOutputI2SNoDAC() verwenden muss, läuft aber auf beiden nicht.


Es handelt sich um einen PC-Speaker 1.5W, 8 Ohm, mit einem BC547 
Transistor und 1k als Basis-Widerstand. Der ist direkt an den internen 
8-Bit DAC des NodeMCU ESP32s angeschlossen. Mit einem Test-Ton höre (und 
sehe) ich aber etwas.
1
#include <driver/dac.h>
2
3
const int sampleRate = 48000;   // Sample rate in Hz
4
const int frequency = 1000;     // Frequency of the sine wave in Hz
5
const int amplitude = 127;      // Amplitude of the sine wave
6
7
void setup() {
8
  dac_output_enable(DAC_CHANNEL_1);  // Enable DAC channel 1
9
}
10
11
void loop() {
12
  for (int t = 0; t < sampleRate; t++) {
13
    int value = amplitude * sin(2 * PI * frequency * t / sampleRate);
14
    dac_output_voltage(DAC_CHANNEL_1, value + 127);  // Adjust the offset to output in the range 0-255
15
    delayMicroseconds(1000000 / sampleRate);  // Delay to maintain the desired sample rate
16
  }
17
}

An der Sample Rate wird es somit nicht liegen. Die ESP32-audioI2S 
Library ist leider mit meinem single-core ESP32s Devboard nicht 
kompatibel, bekomme ich auch nicht kompiliert.

Wenn jemand Ahnung hat von Audio und helfen möchte, einen NodeMCU ESP32s 
kann ich spenden und per Brief zusenden.

von Alexander (alecxs)


Lesenswert?

Achso und ich nutze Arduino 1.8.19 da die Version 2 noch nicht 
ausgereift bzw. alltagstauglich sein soll.

https://github.com/espressif/arduino-esp32/issues/5938

von Alexander (alecxs)


Lesenswert?

To use the internal DAC on ESP32, instantiate this class as 
AudioOutputI2S(0,1), see example PlayMODFromPROGMEMToDAC and code in 
AudioOutputI2S.cpp for details.
1
  out = new AudioOutputI2S(0, 1);

Problem gelöst.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.