ESP32 Audio Kit (ESP32-A1S)

Ja, also erstmal hatte ich ja GPIOs blöderweise benutzt, die für SDMMC gebraucht werden. Dann hat, so glaube ich zumindest, der i2c-RFID-Reader den i2c-Bus runtergezogen, wenn er aus war.
In Anbetracht der Tatsache, wieviel Klicks dieser Thread hier schon hat, sollte ich das Thema vielleicht mal wieder angehen. Also ich war demletzt schon dabei, hab’s jedoch (mangels Bock, hehe) nicht fertig gemacht.

Hast du eigentlich einen Link zu einem Tutorial, wie man die Kappe oben abnimmt (+ wieder draufkriegt)? Weil ich habe hier auch noch drei WROVER, die hatte ich fälschlicherweise mit 4 MB bestellt. Das wäre mit 16 MB besser. Einfach zu löten (für erfahrene SMD-Löter) wäre das ja, wenn ich sop8 lese :slight_smile:.

hi @biologist
Danke für die schnelle Antwort , werde es dann mal angehen .
Habe keinen Link , ich war nur neugierig ob das Aufrüsten geht.
Wrover öffnen wird sicher schwieriger da dieser allseits gekapselt ist . Der A1S nur an 4 kurzen Stellen . Geschafft habe ich es mit einem Lötkolben und dicker Spitze. An der kürzesten Seite angefangen und vorsichtig angehoben . Dann allmählich mit der Spitze weiter und letztendlich noch mit Heißluft. Ging wirklich einfach. Die Leiterbahnen sind recht dünn und mit wenig Zinn. Den Deckel wieder schließen war etwas komplizierter . Ich glaube aber dass das gar nicht so wichtig ist ( Abschirmung usw. ) . Ich habe das Teil offen mit 4MB einige Wochen im Probetrieb und habe keine Fehlfunktion festgestellt . Ich denke aber trotzdem dass der Deckel der Abschirmung dient und nicht nur für den Aufdruck…

Oh, ich glaube dann ist mir das doch zu viel Action und ich setze die Module mal für andere Projekte ein, wo mir 4 MB reichen. Dummerweise wäre dort WROOM eigentlich besser, weil dort 16+17 frei sind, aber so ist das halt :slight_smile:
Danke für die Infos.

So, ich habe jetzt mal die rev2 des HATs finalisiert und bei JLC bestellt. Mal hoffen, dass es diesmal funktioniert. So in etwa zwei 2,5 Wochen wissen wir dann mehr.

Hi
Ich habe seit ein paar Tagen PCA9555 hier und seitdem bin ich gefühlt 27 Stunden am Tag mit dem PE an meinem A1S beschäftigt . Am D32 Pro läuft alles. Am A1S wird der PE nicht erkannt und der Neopixel bleibt stehen. RFID geht Musik läuft und Rotary auch . Hat jemand den PE am A1S laufen ?
Hallo @kobel , ich habe das damals getestet war aber nicht so glücklich. Hast du damit weitergemacht , für mich wäre die Lösung mit analoger Tastenabfrage der Hit. Hatte das total zurückgestellt weil der A1S zu wenig Flash hat. Das hat sich ja jetzt durch meinen Umbau auf 16MB erledigt und ich habe den wieder hervorgekramt.

Auf meiner ersten Platine ist der PE auch nicht gelaufen. Bin gespannt, ob es auf der zweiten Platine klappt. Es läuft nativ halt schon eine andere i2c-Instanz für den AC101. Vielleicht gibt’s da mit der zweiten Instanz irgendwelche Probleme.
PCBs sind für nächste Woche angekündigt.

Ich hatte zum Test die I2C-Intanz für den AC101 deaktiviert ,gleiches Verhalten .

Bei einem anderen Projekt (mit dem ESP32) von mir machte die zweite I2C Instanz auch Probleme, alle Slaves an einen I2C Bus und alles lief

Interessant, wird mir aber leider nicht helfen . Beim A1S sind die Pins für I2C intern für den DAC genutzt und damit nicht zugänglich.

Klappt bei mir auch nicht.
Gut, dann ist es halt so. Ich stelle das Thema jetzt wieder zurück.
Interessanterweise hatte ich auch Probleme das Teil zu flashen. Letztlich hat nur geholfen, upload_speed = 115200 zu setzen.

Oh, Oh , dann ist dein neuer HAT ja erstmal für die Katz…schade.
VG

Vor über einem Jahr hatte ich ein Board mit einem ESP32-A1S erstellt.

Es sollte als Basis für ein neues complete sein. Ich habe es dann aus diesem Grund
verworfen.
OTA war mir damals wichtig.

  1. Heute ist es das nicht mehr. Die Praxis hat gezeigt dass es leider manchmal nicht funktioniert und der ESP32 von der falschen Partition bootet. Da meine Boxen in Kanada sind kann ich dann nicht helfen. So habe ich mich entschlossen Updates immer selbst vor Ort auszuführen.
  2. Der A1S kann nach Umbau auch 16MB , siehe hier.

Da ich den A1S wegen der minimalen zusätzlichen Hardware, kein DAC, kein Kopfhörerverstärker, toll finde, habe ich weitergemacht. Ich bin auch kein Freund eines Portexpanders (wieder Hardware) und brauche auch so viele Pins nicht. Und im Moment hat das wohl auch noch niemand am A1S ans Laufen gebracht. Deshalb habe ich in Anlehnung des Codes von @kobel eine Lösung für die Buttons per analogread erstellt. Ich verwende nur NEXT, PREV, PLAY, ROTARYBUTTON und die Doppeltastenfunktionen. Mehr Tasten sind möglich. Ich habe es dank eines Tipps von @biologist jetzt funktionstüchtig. Es ist noch nicht die finale Lösung aber ich wollte vor dem Weiterentwickeln der Hardware erst sicherstellen dass es auch einwandfrei funktioniert.

Über 2 Sachen bin ich dabei extrem gestolpert:

  1. Der ESP32 hat 2 AD-Wandler. Analogread funktioniert nicht mit GPIOs des ADC2 wenn WLAN aktiviert ist. Es kommt zu dieser Fehlermeldung:

[E][esp32-hal-adc.c:135] __analogRead(): GPIO12: ESP_ERR_TIMEOUT: ADC2 is in use by Wi-Fi.

siehe Analog to Digital Converter (ADC) - ESP32 - — ESP-IDF Programming Guide latest documentation

  1. Ich habe für ROTARYENCODER_CLK GPIO12 zufällig ausgewählt. Da der Rotary interne Pullups hat kann man den A1S dann meist nicht flashen und wenn es doch geht bootet er anschließend nicht. Fehlermeldungen:

rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57

siehe hier und hier.

GPIO12 wird bei einigen Chips intern verwendet (strapping pins).
Das ist auch noch vom Typ bzw. Ausgabe des ESP32 unterschiedlich. Mein Wrover-E funktioniert.
TIPP: Nie Pullups an GPIO12 verwenden.

1 „Gefällt mir“

Guten Abend :slight_smile:

Vielen Dank für die Arbeit die hier bereits investiert wurde! unglaublich!
Ich bin an zwei defekte Tonieboxen gekommen und möchte eine davon für meinen Sohn umbauen. Da ich gerne optional auch originale Tonies lesen möchte (natürlich nicht die original Daten sondern nur die UID und entsprechend eigene Sound Files), habe ich als RFID Leser den PN5180 vorgesehen. Erste Tests mit Raspi & Co. liefen auch problemlos. Nun habe ich aber eben auch noch so ein ESP32-A1S Board hier rumfliegen. Das wäre natürlich die deutlich „bessere“ Lösung für mein Vorhaben. Nun habe ich im Verlauf des Threads nur noch über den RC520 Leser und diesen nach Möglichkeit auch noch als I²C Version gelesen. Da der PN5180 etwas mehr Pins benötigt ist das Zusammenspiel mit dem ESP32-A1S Audio Kit vermutlich nicht mehr möglich oder ? Gibt es einen I²C Leser der auch die Tonies (iso15693 )auslesen kann ?

Vielen Dank im Voraus!
Grüße

Hey, ich versuche seit Tagen einen Tür Gong mit dem A1S V2.2 Board zu realisieren. Ich hab einen code zusammengebastelt und habe auch einen Demo code bei dem ein Sinus Ton abgespielt wird der Funktioniert aber leider bekomme ich das nicht in meinen code integriert.

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <SD_MMC.h> // Verwende die SD_MMC-Bibliothek
#include <time.h> // Für die Zeitfunktion

// Definiere die Pins für die Tasten
#define BUTTON_KEY3 19

// WLAN-Zugangsdaten
const char* ssid = „xxx“; // Ersetze mit deinem WLAN-Namen
const char* password = „xxx“; // Ersetze mit deinem WLAN-Passwort

WebServer server(80); // Erstelle einen Webserver, der auf Port 80 hört

// Variablen zur Speicherung der Statusausgaben
String output = „“;

// Funktion zum Erhalten des aktuellen Zeitstempels
String getTimestamp() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return „Error“; // Gibt „Error“ zurück, wenn die Zeit nicht abgerufen werden kann
}
char buffer[16];
strftime(buffer, sizeof(buffer), „%H:%M:%S“, &timeinfo);
return String(buffer);
}

void handleRoot() {
// HTML-Inhalt für die Webseite
String html = „

Serieller Monitor


“ + output + „

„“
„“;
server.send(200, „text/html“, html); // Sende die HTML-Seite zurück
}

void handleStatus() {
server.send(200, „text/plain“, output); // Sende den aktuellen Status als Plain Text
}

void setup() {
Serial.begin(115200); // Initialisiere die serielle Kommunikation

// Setze die Button-Pins als Eingänge

pinMode(BUTTON_KEY3, INPUT_PULLUP);


// Verbinde mit dem WLAN
WiFi.begin(ssid, password);
Serial.print("Verbinde mit WLAN...");

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

Serial.println();
Serial.print("Verbunden mit WLAN! IP-Adresse: ");
Serial.println(WiFi.localIP()); // Zeige die lokale IP-Adresse an

// Zeit synchronisieren
configTime(3600 * 2, 0, "pool.ntp.org", "time.nist.gov"); // UTC+2 für Sommerzeit

// Warten, bis die Zeit synchronisiert ist
delay(1000); // Kurze Verzögerung, um sicherzustellen, dass die Zeit abgerufen werden kann

// Jetzt den Output mit Zeitstempel aktualisieren
output += getTimestamp() + " - Verbunden mit WLAN! IP-Adresse: " + WiFi.localIP().toString() + "\n";

// Definiere die Routen für den Webserver
server.on("/", handleRoot);        // Handle root URL
server.on("/status", handleStatus); // Handle status URL

// Starte den Server
server.begin();
Serial.println("Webserver gestartet. Port: 80");
output += getTimestamp() + " - Webserver gestartet. Port: 80\n";

// SD-Karte im MMC-Modus initialisieren
Serial.println("Starte SD-Karteninitialisierung...");
output += getTimestamp() + " - Starte SD-Karteninitialisierung...\n";

if (!SD_MMC.begin()) {
    Serial.println("SD-Karte konnte nicht initialisiert werden!");
    output += getTimestamp() + " - SD-Karte konnte nicht initialisiert werden!\n";
    while (true); // Halte die Ausführung an
}

Serial.println("SD-Karte erfolgreich initialisiert!");
output += getTimestamp() + " - SD-Karte erfolgreich initialisiert!\n";

// Teste das Schreiben einer Datei auf die SD-Karte
Serial.println("Versuche, eine Testdatei zu schreiben...");
output += getTimestamp() + " - Versuche, eine Testdatei zu schreiben...\n";

File file = SD_MMC.open("/test.txt", FILE_WRITE);
if (file) {
    file.println("Hallo von der SD-Karte!"); // Schreibe etwas in die Datei
    file.close(); // Schließe die Datei
    Serial.println("Datei erfolgreich geschrieben.");
    output += getTimestamp() + " - Datei erfolgreich geschrieben.\n";
} else {
    Serial.println("Fehler beim Öffnen der Datei zum Schreiben.");
    output += getTimestamp() + " - Fehler beim Öffnen der Datei zum Schreiben.\n";
}

}

void loop() {
// Temporärer Output-String
String newOutput = „“;

// Überprüfe die Tasten mit Entprellung
static unsigned long lastPressTime = 0; // Zeit des letzten Tastendrucks
unsigned long currentTime = millis(); // Aktuelle Zeit

if (currentTime - lastPressTime > 200) { // Warte 200 ms zwischen den Tastendrücken
    if (digitalRead(BUTTON_KEY1) == LOW) {
        newOutput += getTimestamp() + " - Key 1 gedrückt!\n";
        lastPressTime = currentTime; // Aktualisiere die Zeit des letzten Tastendrucks
    }

    if (digitalRead(BUTTON_KEY3) == LOW) {
        newOutput += getTimestamp() + " - Key 3 gedrückt!\n";
        lastPressTime = currentTime; // Aktualisiere die Zeit des letzten Tastendrucks
    }

    if (digitalRead(BUTTON_KEY4) == LOW) {
        newOutput += getTimestamp() + " - Key 4 gedrückt!\n";
        lastPressTime = currentTime; // Aktualisiere die Zeit des letzten Tastendrucks
    }

    if (digitalRead(BUTTON_KEY5) == LOW) {
        newOutput += getTimestamp() + " - Key 5 gedrückt!\n";
        lastPressTime = currentTime; // Aktualisiere die Zeit des letzten Tastendrucks
    }

    if (digitalRead(BUTTON_KEY6) == LOW) {
        newOutput += getTimestamp() + " - Key 6 gedrückt!\n";
        lastPressTime = currentTime; // Aktualisiere die Zeit des letzten Tastendrucks
    }
}

// Wenn neue Ausgaben vorhanden sind, aktualisiere den globalen Output
if (newOutput.length() > 0) {
    output += newOutput; // Füge neue Ausgaben hinzu
    Serial.println(newOutput); // Debug-Ausgabe im seriellen Monitor
}

// Sende den gesamten Output an die Webseite
server.handleClient(); // Überprüfe, ob ein Client eine Anfrage gesendet hat
delay(100); // Kurze Verzögerung, um den Loop nicht zu überlasten

}

Ich glaube da bist du hier eher falsch und musst direkt bei Wolles Library schauen:

Hello, everyone!

I’m working on a VoIP/intercom project using the ESP32 Audio Kit V2.2 (with ES8388 codec), and I’m facing a very specific issue. :white_check_mark: What works:
I can send audio from my PC microphone via TCP socket to the ESP32’s audio output (speakers) without any problem.
Wi-Fi connection is stable and working.
I’m using bidirectional TCP, with a main.cpp sketch using Arduino framework, and two Python scripts on the PC (mic_to_esp32.py and esp32_to_speaker.py).
Sending audio from PC to ESP32 is clear and clean.
:cross_mark: The problem:
The ESP32 does not send any audio from its onboard microphone to the PC.
Port 5001 (which should send audio from ESP32 to PC) connects, but no sound is transmitted.
I’m using AUDIO_HAL_ADC_INPUT_LINE1 as input device.
I’ve tried with onboard mic and also external mic on LINE IN.
The code compiles fine, no runtime errors, just silence.
:brain: AudioKit Config:

cpp
CopiarEditar
auto cfg = kit.defaultConfig(RXTX_MODE); cfg.input_device = AUDIO_HAL_ADC_INPUT_LINE1; cfg.sample_rate = 16000; cfg.channels = 1; kit.begin(cfg); kit.setVolume(100); :red_question_mark: My questions:
What am I missing to make the built-in microphone or LINE1 input of the ESP32 Audio Kit V2.2 work and transmit audio to the PC?
Has anyone succeeded in creating a working full-duplex VoIP project with this board?
Should I move to ESP-ADF instead of Arduino Framework?

Any help, hints or working examples would be greatly appreciated :folded_hands:

Thank you in advance!

#include
#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"
// ======= CONFIGS =======
const char* ssid = "Pandora";
const char* password = "vini5701";
const int port_in = 5000; // Entrada de áudio (fala do PC pro ESP32)
const int port_out = 5001; // Saída de áudio (fala do ESP32 pro PC)
WiFiServer serverIn(port_in);
WiFiServer serverOut(port_out);
AudioKitStream kit;
StreamCopy copierIn;
StreamCopy copierOut;
// ======== TASKS =========
void taskAudioIn(void* param) {
WiFiClient* client = (WiFiClient*)param;
copierIn.begin(kit, *client);
while (client->connected()) {
copierIn.copy();
delay(1);
}
client->stop();
delete client;
vTaskDelete(NULL);
}
void taskAudioOut(void* param) {
WiFiClient* client = (WiFiClient*)param;
copierOut.begin(*client, kit);
while (client->connected()) {
copierOut.copy();
delay(1);
}
client->stop();
delete client;
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// Wi-Fi
Serial.println("Conectando ao Wi-Fi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n✅ Conectado! IP:");
Serial.println(WiFi.localIP());
// Áudio
auto cfg = kit.defaultConfig(RXTX_MODE);
cfg.sample_rate = 16000;
cfg.channels = 1;
cfg.bits_per_sample = 16;
cfg.input_device = AUDIO_HAL_ADC_INPUT_LINE1; // microfone embutido da ESP32 Audio Kit V2.2
kit.begin(cfg);
kit.setVolume(60); // 🔊 volume ajustado para evitar chiado
serverIn.begin();
serverOut.begin();
Serial.printf("🔊 Porta IN (fala): %d\n", port_in);
Serial.printf("🎤 Porta OUT (mic ): %d\n", port_out);
}
void loop() {
if (serverIn.hasClient()) {
WiFiClient client = serverIn.available();
if (client) {
xTaskCreatePinnedToCore(taskAudioIn, "audioIn", 4096, new WiFiClient(client), 1, NULL, 1);
Serial.println("🔊 Cliente IN conectado");
}
}
if (serverOut.hasClient()) {
WiFiClient client = serverOut.available();
if (client) {
xTaskCreatePinnedToCore(taskAudioOut, "audioOut", 4096, new WiFiClient(client), 1, NULL, 0);
Serial.println("🎤 Cliente OUT conectado");
}
}
delay(100);
}

[platformio]
default_envs = esp32dev
[env:esp32dev]
platform = espressif32@5.0.0
board = esp32dev
framework = arduino
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
-DAUDIOKIT_BOARD=5
-DCORE_DEBUG_LEVEL=1
-Wno-unused-variable
-Wno-unused-but-set-variable
-Wno-unused-function
-Wno-format-extra-args
lib_deps =
Wire
https://github.com/pschatzmann/arduino-audio-tools.git#v0.9.4
https://github.com/pschatzmann/arduino-audiokit.git#v0.6.3
https://github.com/pschatzmann/arduino-libhelix.git#v0.8
https://github.com/pschatzmann/arduino-libmad.git#v0.7
https://github.com/greiman/SdFat.git#2.2.0
knolleary/PubSubClient@2.8
upload_port = COM3
monitor_port = COM3