In questo post imparerai come utilizzare un modulo PCM5102A con l’ESP32 per riprodurre audio. Il PCM5102A è un convertitore digitale-analogico (DAC) ad alte prestazioni, che comunica tramite l’interfaccia I2S (Inter-IC Sound).
Converte i dati audio in un segnale analogico di livello linea, adatto per l’amplificazione o per l’uso diretto con cuffie ad alta impedenza. Il modulo include un’uscita stereo da 3,5 mm e funziona con un’alimentazione standard da 3,3 V a 5 V, rendendolo compatibile con microcontrollori comuni come le schede ESP32 o Arduino.
Durante questo tutorial imparerai a generare segnali audio, convertire testo in voce, ascoltare radio internet in streaming, riprodurre file MP3 da una scheda SD e utilizzare l’audio Bluetooth.
Componenti necessari
Ti servirà un modulo PCM5102A. Esistono diverse versioni di schede basate su PCM5102A, ma dovrebbero funzionare tutte per questo tutorial. Io ho usato la scheda elencata qui sotto, che ha un jack da 3,5 mm per l’uscita linea.

Avrai bisogno di una coppia di casse attive, preferibilmente con un jack da 3,5 mm per collegarle direttamente a questa scheda PCM5102A.
Per riprodurre file MP3 da una scheda SD ti servirà inoltre una scheda SD da almeno 1GB e un modulo lettore di schede SD. Useremo anche un potenziometro da 10K Ohm come controllo volume e alcuni pulsanti per il lettore MP3 e la radio internet che andremo a costruire.
Infine, ti serviranno un ESP32, una breadboard e alcuni cavi. Io ho usato un ESP32 lite ma la maggior parte delle altre schede ESP32 dovrebbe funzionare ugualmente. Se pensi di memorizzare e riprodurre musica dalla memoria, ti consiglio una scheda ESP32-S3 con PSRAM.

Amplificatore PCM5102

Cassa attiva

Potenziometro 10K Ohm

Pulsanti

Lettore Micro SD Card

Micro SD Card 8GB

ESP32 lite

Cavo dati USB

Set di cavi Dupont

Breadboard
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Il protocollo audio I2S
Iniziamo con una breve introduzione al protocollo I2S, utilizzato per trasferire dati audio digitali da un ESP32 a un DAC come il PCM5102A.
I2S, o Inter-IC Sound, è uno standard di interfaccia bus seriale usato per collegare dispositivi audio digitali. È stato introdotto da Philips negli anni ‘80 per semplificare la trasmissione di dati audio tra circuiti integrati. A differenza di protocolli come SPI o I2C, I2S è progettato specificamente per applicazioni audio, garantendo una temporizzazione precisa e la sincronizzazione dei flussi audio.
Alla base, I2S trasferisce dati audio in Pulse Code Modulation (PCM) in modo sincrono. Il protocollo utilizza tre segnali principali: il clock seriale (SCK), il word select (WS) e il dato seriale (SD). Il clock seriale pulsa alla velocità dei bit, determinando quando vengono inviati i bit. Il segnale word select commuta per indicare se i dati attuali corrispondono al canale audio sinistro o destro. Infine, la linea dati seriale trasporta i bit audio effettivi, trasmettendo prima il bit più significativo (MSB).

Tipicamente, i dati audio vengono inviati in parole da 16 o 24 bit, ma il protocollo può supportare altre profondità di bit a seconda dell’hardware.
La periferica I2S dell’ESP32 supporta la comunicazione full-duplex, permettendo input e output audio simultanei. Può essere configurata per funzionare in modalità master o slave. Quando agisce da master, l’ESP32 genera i segnali di clock e word select. Questa è la configurazione più comune quando si collega il DAC PCM5102A, che agisce come dispositivo slave I2S. Nella prossima sezione vediamo più da vicino il PCM5102A.
Caratteristiche tecniche del modulo PCM5102
I moduli PCM5102A sono basati sul Texas Instruments PCM5102A, un convertitore digitale-analogico stereo progettato per la riproduzione audio ad alta risoluzione. Converte flussi audio digitali in segnali analogici di livello linea usando un percorso del segnale completamente integrato che riduce al minimo la necessità di componenti esterni.
Il PCM5102A supporta l’uscita stereo con un’uscita analogica a piena scala tipica di circa 2,1 Vrms centrata a massa, permettendo il collegamento diretto a livello linea senza bisogno di condensatori di blocco DC esterni.
Il modulo usato in questo tutorial è dotato di un jack stereo da 3,5 mm per l’uscita audio, insieme a componenti passivi onboard per il filtraggio dell’uscita e l’accoppiamento AC. Sono presenti anche ponticelli a saldare per la selezione delle funzioni – ne parleremo più avanti. L’immagine qui sotto mostra il fronte e il retro del modulo PCM5102:

Ingresso audio digitale e clock
I dati audio digitali vengono accettati tramite un’interfaccia PCM standard compatibile con i formati I2S e left-justified, supportando dati a 16, 24 e 32 bit. Sono supportati rate di campionamento da 8 kHz fino a 384 kHz, rendendo il dispositivo adatto sia per applicazioni audio standard che ad alta risoluzione.
Il PCM5102A include un PLL integrato ad alte prestazioni che può sintetizzare il clock interno ad alta velocità richiesto dai suoi motori di interpolazione e DAC sia dal bit clock (BCK) che da un eventuale clock di sistema esterno (SCK). Questo riduce la necessità di una sorgente di clock master esterna e permette il funzionamento con una connessione I2S a 3 fili (LRCK, BCK, DIN).
Elaborazione digitale del segnale e filtri
Una volta ricevuti i dati audio digitali, il percorso interno del segnale del PCM5102A include filtri di interpolazione digitale che sovracampionano il segnale di ingresso di un fattore (ad esempio, 128× la frequenza di campionamento) prima della conversione. Questi stadi di interpolazione riducono il rumore di quantizzazione e semplificano i requisiti del filtro di ricostruzione analogico.
Stadio di uscita analogico e line driver
Lo stadio di uscita analogico del modulo integra un line driver DirectPath™ a pompa di carica, in grado di fornire un’uscita di livello linea su carichi fino a 1 kΩ per canale. Circuiti intelligenti di soft-ramp e mute analogico aiutano a prevenire transitori udibili durante accensione, spegnimento o errori di clock.
Nota che non puoi collegare direttamente un altoparlante passivo all’uscita di linea del PCM5102A. Serve un amplificatore aggiuntivo o una cassa attiva!
Alimentazione, controllo e condizioni operative
Il modulo PCM5102A è progettato per funzionare con un’unica alimentazione, compresa tra 3,3V e 5V. Internamente, il DAC utilizza regolatori low-dropout integrati per generare le tensioni di alimentazione core e analogiche richieste.
Il PCM5102A entra automaticamente in modalità a basso consumo quando i clock I2S sono inattivi per ridurre il consumo energetico. Pin hardware e ponticelli a saldare permettono di configurare il formato audio (ad esempio, I2S vs left-justified) e lo stato di soft mute, senza bisogno di interfacce di controllo seriali (I2C/SPI) per il funzionamento di base.
Pinout
L’immagine seguente mostra il pinout della scheda PCM5102A:

Nella parte superiore della scheda ci sono i pin per Line Out: LROUT = Canale Sinistro, ROUT = Canale Destro, AGNG = Massa) e i pin per controllare le funzioni specifiche della scheda (ne parleremo nella prossima sezione).
Le funzioni sono anche impostabili tramite ponticelli a saldare sul retro della scheda (H1L, H2L, H3L, H4L). Il jack da 3,5 mm duplica i pin Line Out.
Sul lato destro trovi i pin per l’interfaccia I2S (SCK, BCK, DIN, LRCK) e i pin per l’alimentazione (VIN, GND). I pin I2S sono collegati tramite un pacchetto di resistenze che dovrebbe permettere segnali a 5V, ad esempio da un Arduino UNO. La tensione di alimentazione può essere 3,3V o 5V, poiché la scheda ha regolatori di tensione low-dropout interni.
Ponticelli di funzione
Il modulo PCM5102A ha cinque ponticelli/ponti a saldare che devono essere impostati correttamente per far funzionare la scheda con un ESP32. Questi commutano le seguenti funzioni, a seconda che siano collegati a High o Low. Le impostazioni consigliate sono evidenziate in grassetto:
- SCK = Master Clock: Low se non viene fornito un segnale di clock master esterno
- H1L / FLT = Selezione filtro: Latenza normale ( Low ) / Latenza bassa (High)
- H2L / DEMP = Controllo de-enfasi per campionamento a 44.1kHz: Off ( Low ) / On (High)
- H3L / XSMT = Controllo soft mute: Soft mute (Low) / soft un-mute ( High )
- H4L / FMT = Selezione formato audio I2S: Right justified ( Low ) / Left justified (High)
La selezione del filtro con latenza normale è un FIR con buona risposta, che ritarda il segnale di circa 500us (a 44,1 kHz). Il filtro a bassa latenza è un IIR con risposta leggermente peggiore e ritarda il segnale di circa 80us. Pochissime (se non nessuna) sorgenti audio hanno la pre-enfasi applicata, quindi il controllo de-enfasi dovrebbe essere impostato su off. Il pin XSMT permette di silenziare l’uscita tramite un GPO o un interruttore se il ponte H3L non è saldato. Per il formato audio I2S scegliamo right justified.
L’immagine qui sotto mostra lo schema del modulo PCM5102A con questi ponticelli di funzione evidenziati in giallo:

Ponti a saldare
Sul retro della scheda trovi quattro ponti a saldare H1L, H2L, H3L e H4L. L’immagine qui sotto mostra quali ponti devi saldare su High (H) o Low (H):

In alternativa ci sono anche 4 pin (FLT, DEMP, XMST, FMT) nella parte superiore della scheda che puoi collegare a 3,3V (H) o GND (L) per controllare le funzioni della scheda. Questo è utile se vuoi usare interruttori o GPIO per controllare le funzioni. In particolare la funzione mute (XMST/H3L) potrebbe interessarti. Ma assicurati di usare o i pin o i ponti, ma non entrambi contemporaneamente!
Ponte SCK
C’è un singolo ponte nella parte frontale della scheda che devi saldare. Controlla se viene fornito o meno un segnale di clock master esterno (SCK). Nel nostro caso non forniamo SCK e quindi dobbiamo saldare il ponte SCK per collegare SCK a massa.

Specifiche tecniche
La tabella seguente riassume le specifiche tecniche del PCM5102A:
| Parametro | Specifiche |
|---|---|
| Dispositivo DAC | Texas Instruments PCM5102A |
| Architettura interna | DAC delta-sigma ad alte prestazioni con filtri di interpolazione digitale |
| Interfaccia audio digitale | Formati standard I2S, left-justified, right-justified, DSP (PCM) |
| Frequenze di campionamento supportate | 8 kHz a 384 kHz |
| Profondità di bit supportate | 16-bit, 24-bit, 32-bit |
| Requisiti di clock in ingresso | Bit Clock (BCK), Word Clock (LRCK); opzionale clock di sistema esterno (SCK) |
| Clock | PLL integrato con moltiplicatore di clock ad alte prestazioni; generazione clock master interna |
| Sovracampionamento filtro digitale | Stadi multipli con alto rapporto di sovracampionamento (es. 128 x fs) |
| Tipo di uscita analogica | Uscite interne differenziali con filtraggio passivo onboard verso single-ended |
| Connettore di uscita | Jack stereo da 3,5 mm |
| Tensione di uscita a piena scala | Circa 2,1 Vrms (centrato a massa) |
| Carico di uscita supportato | Progettato per carichi di livello linea ≥ 1 kΩ per canale |
| Rapporto segnale/rumore (SNR) | ~112 dB (A-weighted, tipico) |
| Distorsione armonica totale + rumore (THD+N) | ~-93 dB (tipico) |
| Line Driver | Line driver DirectPath™ integrato a pompa di carica |
| Mute/Soft-Ramp | Soft-mute analogico integrato all’accensione/spegnimento o perdita clock |
| Tensione di alimentazione (AVDD) | 3,3 V … 5V |
| Livelli logici | Compatibile LVCMOS con livelli I/O ESP32 |
| Interfaccia di controllo | Configurazione tramite pin hardware (nessun I2C/SPI richiesto per il funzionamento base) |
| Consumo energetico | Modalità a basso consumo automatica quando i clock sono inattivi |
Per ulteriori informazioni consulta il datasheet del PCM5102A linkato qui sotto:
Collegare PCM5102A a ESP32
In questa sezione colleghiamo il PCM5102A all’ESP32. Iniziamo collegando VIN del PCM5102A a 3,3V dell’ESP32 e GND a G. Poi colleghiamo i pin I2S come mostrato nella tabella seguente:
| PCM5102A | ESP32 |
|---|---|
| VIN | 3V3 |
| GND | G |
| LRCK | 32 |
| BCK | 25 |
| DIN | 33 |
| SCK | G |
Se hai saldato il ponte SCK in realtà non serve collegare SCK a massa, ma non crea problemi.
L’immagine seguente mostra il cablaggio completo del modulo PCM5102A con un ESP32 lite. Nota che devi collegare l’uscita line out del PCM5102A a un amplificatore o a una cassa attiva. Non collegare direttamente un altoparlante passivo o cuffie a bassa impedenza al PCM5102A.

Lettore SD Card
Se vuoi riprodurre file audio devi collegare un lettore di schede SD che memorizza i file audio su una SD Card. Lo schema di collegamento qui sotto mostra come collegare un lettore SD Card e il PCM5102A a un ESP32:

Il Lettore SD Card comunica tramite SPI e i pin SPI di default dell’ESP32 sono CS=5, MOSI=23, CLK=18 e MISO=19. La tabella qui sotto riassume i collegamenti da fare tra il Lettore SD Card e l’ESP32:
| Lettore SD Card | ESP32 |
|---|---|
| 3V3 | 3V |
| GND | G |
| CS/SS | 5 |
| MOSI | 23 |
| CLK/SCK | 18 |
| MISO | 19 |
Se non sei sicuro di quali siano i pin SPI di default del tuo ESP32 dai un’occhiata al Find I2C and SPI default pins tutorial.
La foto seguente mostra il mio cablaggio del PCM5102A con un Lettore SD Card, un ESP32 e una piccola cassa attiva mono per i test:

Installazione delle librerie
In questo tutorial useremo la arduino-audio-tools libreria di Phil Schatzmann per inviare dati audio al PCM5102A. Per installare la libreria vai su arduino-audio-tools repo, clicca sul pulsante verde “<> Code” e poi su “Download ZIP” per scaricare la libreria come file ZIP come mostrato qui sotto:

Poi apri uno Sketch, vai su Sketch -> Include Library -> Add .ZIP Library … per installare la libreria ZIP scaricata (arduino-audio-tools-main.zip):

Per alcuni degli esempi di codice servono altre due librerie di Phil Schatzmann; ovvero la arduino-libhelix libreria e la ESP32-A2DP libreria. Puoi installarle allo stesso modo. Clicca sul link per andare al repo github, clicca sul pulsante verde “<> Code” per scaricare le librerie (arduino-libhelix-main.zip, ESP32-A2DP-main.zip) e poi installale.
Infine, se è la prima volta che programmi una scheda ESP32 dall’IDE Arduino dovrai installare anche il core ESP32. Per i dettagli vedi il Install ESP32 core in Arduino IDE tutorial.
Esempio di codice: Test Sound
In questo primo esempio generiamo semplicemente un’onda sinusoidale di test e la inviamo tramite l’interfaccia I2S al DAC
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
*/
#include "AudioTools.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define VOLUME 1000 // max 32000
AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave(VOLUME);
GeneratedSoundStream<int16_t> sound(sineWave);
I2SStream out;
StreamCopy copier(out, sound);
void setup(void) {
auto config = out.defaultConfig(TX_MODE);
config.copyFrom(info);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
out.begin(config);
sineWave.begin(info, N_B4);
}
void loop() {
copier.copy();
}
Import
Il codice inizia includendo la AudioTools.h libreria, che fornisce classi e funzioni per generare e trasmettere segnali audio facilmente su ESP32.
#include "AudioTools.h";
Costanti
Successivamente, definiamo i pin collegati al modulo DAC PCM5102A. Questi pin corrispondono ai segnali dell’interfaccia I2S: DIN_PIN per i dati seriali, LRCK_PIN per il word select (left-right clock), e BCLK_PIN per il clock seriale. Definiamo anche una costante VOLUME per impostare l’ampiezza dell’onda sinusoidale generata, con un’ampiezza massima di 32000.
#define DIN_PIN 33 // serial data #define LRCK_PIN 32 // word select #define BCLK_PIN 25 // serial clock #define VOLUME 1000 // max 32000
Configurazione audio e oggetti
L’oggetto AudioInfoinfo definisce il formato audio: frequenza di campionamento di 44.100 Hz, 2 canali (stereo) e 16 bit per campione. Questo corrisponde all’audio di qualità CD standard.
L’oggetto SineWaveGeneratorsineWave viene usato per generare un segnale audio sinusoidale con il volume specificato. Produce campioni interi con segno a 16 bit.
L’oggetto GeneratedSoundStreamsound incapsula il generatore di onde sinusoidali in un’interfaccia stream, rendendo più semplice inviare i dati audio a un’uscita.
L’oggetto I2SStreamout rappresenta l’uscita I2S su ESP32, che invierà i dati audio al DAC PCM5102A.
Infine, l’oggetto StreamCopycopier si occupa di copiare continuamente i dati audio dallo stream generato allo stream di uscita I2S.
AudioInfo info(44100, 2, 16); SineWaveGenerator<int16_t> sineWave(VOLUME); GeneratedSoundStream<int16_t> sound(sineWave); I2SStream out; StreamCopy copier(out, sound);
Funzione Setup
All’interno della funzione setup() configuriamo lo stream di uscita I2S. Iniziamo ottenendo una configurazione di default per la modalità trasmissione usando out.defaultConfig(TX_MODE). Poi copiamo le impostazioni del formato audio dall’oggetto info in questa configurazione.
Successivamente, assegniamo i pin I2S alla configurazione: BCLK_PIN per il bit clock, LRCK_PIN per il word select, e DIN_PIN per la linea dati seriale.
Dopo aver configurato i pin, inizializziamo lo stream di uscita I2S con out.begin(config). Infine, avviamo il generatore di onde sinusoidali con il formato audio e una frequenza di nota musicale predefinita N_B4 (che corrisponde alla nota B4).
void setup(void) {
auto config = out.defaultConfig(TX_MODE);
config.copyFrom(info);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
out.begin(config);
sineWave.begin(info, N_B4);
}
Funzione Loop
La funzione loop() copia continuamente i dati audio dallo stream del generatore di onde sinusoidali allo stream di uscita I2S usando copier.copy(). Questo mantiene la riproduzione audio attiva all’infinito senza interruzioni.
void loop() {
copier.copy();
}
Esempio di codice: Bluetooth
Questo esempio mostra come riprodurre audio via Bluetooth su un ESP32 usando il DAC PCM5102A. Utilizza diverse librerie per gestire lo streaming audio e la funzionalità Bluetooth A2DP (Advanced Audio Distribution Profile). L’ESP32 riceve dati audio via Bluetooth e li invia tramite l’interfaccia I2S al convertitore digitale-analogico PCM5102A.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
- [ESP32-A2DP](https://github.com/pschatzmann/ESP32-A2DP)
Version: 1.8.8
*/
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
auto config = i2s.defaultConfig();
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
a2dp_sink.start("MyMusic");
}
void loop() { }
Import
Il codice inizia includendo le librerie necessarie. AudioTools.h fornisce le funzionalità di streaming audio, mentre BluetoothA2DPSink.h gestisce la funzionalità Bluetooth A2DP sink, permettendo all’ESP32 di ricevere flussi audio da sorgenti Bluetooth come smartphone.
#include "AudioTools.h" #include "BluetoothA2DPSink.h"
Costanti
Successivamente, tre costanti definiscono i pin GPIO usati per l’interfaccia I2S, che è il protocollo di comunicazione tra ESP32 e il DAC PCM5102A. Questi pin corrispondono alla linea dati seriale (DIN_PIN), alla linea word select o left-right clock (LRCK_PIN), e alla linea bit clock (BCLK_PIN).
#define DIN_PIN 33 // serial data #define LRCK_PIN 32 // word select #define BCLK_PIN 25 // serial clock
Oggetti
Un oggetto I2SStreami2s viene creato per gestire il flusso di dati audio I2S. Poi, un oggetto BluetoothA2DPSinka2dp_sink viene istanziato, passando lo stream i2s come parametro. Questo collega direttamente l’ingresso audio Bluetooth all’uscita I2S, permettendo una riproduzione audio senza interruzioni.
I2SStream i2s; BluetoothA2DPSink a2dp_sink(i2s);
Funzione Setup
All’interno della funzione setup() viene configurata l’interfaccia I2S. La configurazione I2S di default viene ottenuta tramite i2s.defaultConfig(), e i pin rilevanti per bit clock, word select e dati vengono assegnati secondo le costanti definite prima. L’interfaccia I2S viene poi inizializzata con questa configurazione usando i2s.begin(config).
Dopo aver configurato l’interfaccia I2S, il Bluetooth A2DP sink viene avviato con il nome dispositivo "MyMusic". Questo rende l’ESP32 visibile come ricevitore audio Bluetooth con quel nome, permettendo ad altri dispositivi di connettersi e trasmettere audio.
void setup() {
auto config = i2s.defaultConfig();
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
a2dp_sink.start("MyMusic");
}
Apri il telefono e cerca dispositivi Bluetooth per trovare il dispositivo "MyMusic" e poi inizia a riprodurre musica.
Funzione Loop
La funzione loop() è vuota perché il Bluetooth A2DP sink e lo stream I2S gestiscono l’elaborazione e la riproduzione audio in modo asincrono. Una volta completata la configurazione, l’ESP32 ascolta continuamente i flussi audio Bluetooth e li invia tramite l’interfaccia I2S senza bisogno di altro codice nel loop principale.
void loop() { }
Esempio di codice: Internet Radio
Questo codice mostra come realizzare un lettore radio internet usando un microcontrollore ESP32 e un modulo DAC PCM5102A. Si connette a una rete WiFi, riceve in streaming audio MP3 da una stazione radio online, decodifica l’audio e lo invia tramite l’interfaccia I2S al DAC. Il codice gestisce anche i metadati dallo stream, come i titoli delle canzoni.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
*/
#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Communication/HTTP/ICYStream.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define VOLUME 0.3 // Volume
const char* ssid = "ssid";
const char* password = "pwd";
const char* url = "https://jazz.stream.laut.fm/jazz";
ICYStream icystream;
I2SStream i2s;
VolumeStream volume(i2s);
EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix());
StreamCopy copier(mp3decode, icystream);
void callbackMetadata(MetaDataType type, const char* str, int len) {
Serial.printf("%s: %s\n", toStr(type), str);
}
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
volume.begin(config);
volume.setVolume(VOLUME);
mp3decode.begin();
icystream.begin(url);
icystream.setMetadataCallback(callbackMetadata);
}
void loop() {
copier.copy();
}
Import
Il codice inizia includendo diverse librerie necessarie per la connessione WiFi, l’uscita audio I2S e la decodifica MP3. Le librerie Arduino.h e WiFi.h forniscono le funzioni base di Arduino e WiFi. La libreria Wire.h è inclusa ma non usata esplicitamente qui. La libreria AudioTools e i suoi componenti gestiscono lo streaming audio, la decodifica e la riproduzione.
#include <Arduino.h> #include <WiFi.h> #include <Wire.h> #include "AudioTools.h" #include "AudioTools/AudioCodecs/CodecMP3Helix.h" #include "AudioTools/Communication/HTTP/ICYStream.h"
Costanti e definizione dei pin
Successivamente, il codice definisce i pin usati per l’interfaccia I2S per comunicare con il DAC PCM5102A. Questi pin corrispondono ai segnali dati seriali, word select (left-right clock) e bit clock. Inoltre, viene impostato un livello di volume come costante float.
#define DIN_PIN 33 // serial data #define LRCK_PIN 32 // word select #define BCLK_PIN 25 // serial clock #define VOLUME 0.3 // Volume
Le credenziali WiFi e l’URL dello stream radio internet sono memorizzati come puntatori a caratteri costanti.
const char* ssid = "ssid"; const char* password = "pwd"; const char* url = "https://jazz.stream.laut.fm/jazz";
Ecco una lista di URL di altre stazioni radio internet che puoi provare:
"https://jazz.stream.laut.fm/jazz" "http://vis.media-ice.musicradio.com/CapitalMP3"; "http://stream.srg-ssr.ch/m/rsj/mp3_128" "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service" "http://icecast.omroep.nl/radio1-bb-mp3" "http://stream-02-eu.relaxingjazz.com/stream/1/"
Oggetti per lo streaming audio
Vengono creati diversi oggetti per gestire la pipeline di streaming audio. L’oggetto ICYStream gestisce lo streaming HTTP dei dati MP3 dall’URL della radio internet, mentre l’oggetto I2SStream gestisce la comunicazione I2S con il DAC. L’oggetto VolumeStream permette di regolare il volume di riproduzione ed è collegato allo stream I2S. Infine, l’oggetto EncodedAudioStream decodifica i dati MP3 usando il decoder Helix MP3 e invia l’audio decodificato allo stream volume. L’oggetto StreamCopy copia i dati audio decodificati dal decoder MP3 allo stream ICY.
ICYStream icystream; I2SStream i2s; VolumeStream volume(i2s); EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix()); StreamCopy copier(mp3decode, icystream);
Funzione di callback per i metadati
La funzione callbackMetadata è definita per gestire i metadati ricevuti dallo stream radio internet, come il titolo o l’artista della canzone in corso. Stampa il tipo di metadato e il contenuto sul monitor seriale per debug o visualizzazione.
void callbackMetadata(MetaDataType type, const char* str, int len) {
Serial.printf("%s: %s\n", toStr(type), str);
}
Funzione Setup
Nella funzione setup() viene inizializzata la comunicazione seriale a 115200 baud per il debug. Viene avviato anche l’audio logger per catturare warning ed errori. L’ESP32 tenta poi di connettersi alla rete WiFi specificata, riprovando ogni 500 millisecondi fino al successo.
Dopo che la connessione WiFi è stabilita, l’interfaccia I2S viene configurata in modalità trasmissione con i pin specificati per bit clock, word select e dati. Lo stream I2S e lo stream volume vengono inizializzati con questa configurazione e il volume viene impostato al livello predefinito.
Il decoder MP3 viene avviato e lo stream ICY viene inizializzato con l’URL della radio internet. La funzione di callback per i metadati viene registrata per ricevere e gestire i metadati dallo stream.
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
volume.begin(config);
volume.setVolume(VOLUME);
mp3decode.begin();
icystream.begin(url);
icystream.setMetadataCallback(callbackMetadata);
}
Funzione Loop
La funzione loop() copia continuamente i dati audio dallo stream radio internet attraverso il decoder MP3 e il controllo volume fino all’uscita I2S. Questo mantiene la riproduzione audio attiva all’infinito.
void loop() {
copier.copy();
}
Esempio di codice: Internet Radio con controllo volume
In questo esempio di codice aggiungiamo un potenziometro che funziona come controllo volume per la radio internet implementata nella sezione precedente. L’immagine qui sotto mostra il cablaggio:

Il circuito è essenzialmente lo stesso di prima. Aggiungiamo solo un potenziometro da 10K Ohm e tre fili. Inizia collegando uno dei pin esterni del potenziometro a 3V e l’altro pin esterno a massa (G) dell’ESP32. Poi collega il pin centrale (swiper) del potenziometro al GPIO 35 dell’ESP32. Ecco una tabella con i collegamenti richiesti:
| Potenziometro | ESP32 |
|---|---|
| 1 | G |
| 2 | 35 |
| 3 | 3V |
Puoi invertire il collegamento dei pin 1 e 3 del potenziometro se vuoi cambiare il verso di rotazione per aumentare il volume.
Libreria TickTwo
Il seguente codice per la Internet Radio con controllo volume richiede la TickTwo libreria. Per installarla apri il LIBRARY MANAGER, digita “TickTwo” nella barra di ricerca e clicca sul pulsante INSTALL per la libreria “TickTwo by Stefan Staub”:

Qui sotto trovi il codice per la radio internet con controllo volume. È in gran parte lo stesso codice di prima. La novità è la funzione updateVolume() che viene chiamata ogni 100 msec e aggiorna il volume in base alla posizione del potenziometro:
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
- [TickTwo](https://github.com/sstaub/TickTwo)
Version: 4.4.0
*/
#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include "TickTwo.h"
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Communication/HTTP/ICYStream.h"
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define POT_PIN 35 // Poti for Volume
const char* ssid = "ssid";
const char* password = "pwd";
const char* url = "https://jazz.stream.laut.fm/jazz";
ICYStream icystream;
I2SStream i2s;
VolumeStream volume(i2s);
EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix());
StreamCopy copier(mp3decode, icystream);
void callbackMetadata(MetaDataType type, const char* str, int len) {
Serial.printf("%s: %s\n", toStr(type), str);
}
void updateVolume() {
static float oldVol = -1;
long pot = analogRead(POT_PIN);
float vol = map(pot, 0, 4095, 0, 100) / 100.0;
if (fabs(vol - oldVol) >= 0.02) {
oldVol = vol;
volume.setVolume(vol);
}
}
TickTwo timer(updateVolume, 100);
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
volume.begin(config);
volume.setVolume(0.1);
mp3decode.begin();
icystream.begin(url);
icystream.setMetadataCallback(callbackMetadata);
pinMode(POT_PIN, INPUT);
timer.start();
}
void loop() {
timer.update();
copier.copy();
}
Al posto di un potenziometro lineare da 10K Ohm puoi anche usare un potenziometro logaritmico, che offre una relazione più naturale tra la percezione del volume e la regolazione del potenziometro.
La funzione updateVolume() legge la posizione del potenziometro, la mappa su un livello di volume e regola il volume se il nuovo livello è sufficientemente diverso dal precedente. Nella funzione loop() basta chiamare timer.update() ripetutamente, per leggere il potenziometro e regolare il volume ogni 100 msec.
Puoi anche aggiungere pulsanti per cambiare stazione o per silenziare l’audio. Come aggiungere pulsanti al circuito e al codice è spiegato nell’esempio seguente per un lettore MP3.
Esempio di codice: Riproduzione MP3 da SD Card
Il codice seguente mostra come riprodurre file audio MP3 memorizzati su una scheda SD usando un microcontrollore ESP32 e il modulo DAC PCM5102A. Utilizza le librerie arduino-audio-tools e arduino-libhelix per gestire la decodifica audio e la riproduzione tramite l’interfaccia I2S.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
*/
#include "AudioTools.h"
#include "AudioTools/Disk/AudioSourceSD.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define VOLUME 0.5 // Volume
#define PATH "/"
#define EXT "mp3"
AudioSourceSD source(PATH, EXT);
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);
void printMetaData(MetaDataType type, const char* str, int len){
Serial.printf("%s: %s\n", toStr(type), str);
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
player.setMetadataCallback(printMetaData);
player.setVolume(VOLUME);
player.begin();
}
void loop() {
player.copy();
}
Import
All’inizio, il codice include diversi header file delle librerie audio. Questi forniscono le classi e le funzioni necessarie per leggere file audio dalla SD, decodificare stream MP3 e inviare l’audio tramite I2S.
#include "AudioTools.h" #include "AudioTools/Disk/AudioSourceSD.h" #include "AudioTools/AudioCodecs/CodecMP3Helix.h"
Costanti e definizione dei pin
Il codice definisce i pin usati per collegare l’ESP32 al DAC PCM5102A. Questi pin corrispondono ai segnali I2S: dati seriali (DIN), word select (LRCK) e clock seriale (BCLK). Inoltre, viene impostato un livello di volume come valore float tra 0.0 e 1.0.
#define DIN_PIN 33 // serial data #define LRCK_PIN 32 // word select #define BCLK_PIN 25 // serial clock #define VOLUME 0.5 // Volume
Le costanti PATH e EXT specificano la directory root e l’estensione dei file audio da riprodurre, che in questo caso sono file MP3 situati nella root della SD Card.
#define PATH "/" #define EXT "mp3"
Oggetti audio
Vengono istanziati diversi oggetti per gestire la riproduzione audio. AudioSourceSD gestisce la lettura dei file audio dalla SD Card che corrispondono al percorso e all’estensione specificati. I2SStream gestisce lo stream di uscita audio I2S. MP3DecoderHelix è il decoder MP3 basato sulla libreria Helix. Infine, AudioPlayer collega questi componenti per coordinare la riproduzione.
AudioSourceSD source(PATH, EXT); I2SStream i2s; MP3DecoderHelix decoder; AudioPlayer player(source, i2s, decoder);
Funzione di callback per i metadati
La funzione printMetaData() è definita per ricevere informazioni sui metadati come artista, titolo o album dai file MP3 durante la riproduzione. Stampa queste informazioni sul monitor seriale usando Serial.printf. La funzione prende come parametri il tipo di metadato, una stringa con il metadato e la sua lunghezza.
void printMetaData(MetaDataType type, const char* str, int len){
Serial.printf("%s: %s\n", toStr(type), str);
}
Funzione Setup
Nella funzione setup() viene inizializzata la comunicazione seriale a 115200 baud per abilitare il debug. Il livello di logging audio viene impostato su Warning per ridurre la verbosità.
Successivamente, l’interfaccia I2S viene configurata in modalità trasmissione. Si ottiene la configurazione I2S di default e la si modifica assegnando i pin definiti prima per bit clock, word select e dati. Lo stream I2S viene poi avviato con questa configurazione.
Il lettore audio viene configurato per usare la callback printMetaData per mostrare i metadati durante la riproduzione. Il volume viene impostato al livello definito e il player viene avviato con player.begin().
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
player.setMetadataCallback(printMetaData);
player.setVolume(VOLUME);
player.begin();
}
Funzione Loop
La funzione loop() chiama continuamente player.copy(), che elabora i dati audio leggendo dalla SD, decodificando lo stream MP3 e inviando i campioni audio all’uscita I2S. Questo mantiene la riproduzione audio fluida.
void loop() {
player.copy();
}
Esempio di codice: MP3 Player con controllo volume e pulsanti traccia
Un tipico lettore MP3 ha funzioni per controllare il volume e saltare avanti o indietro tra le tracce. In questo esempio di codice aggiungiamo un potenziometro per il controllo volume e due pulsanti per cambiare traccia. Lo schema di collegamento qui sotto mostra come aggiungere un potenziometro e i pulsanti:

La tabella seguente elenca i collegamenti da effettuare. Quando colleghi i pulsanti assicurati di collegare i poli corretti.
| Potenziometro | Pulsante Next | Pulsante Prev | ESP32 |
|---|---|---|---|
| 1 | 4 | ||
| 1 | 15 | ||
| 1 | 2 | 2 | G |
| 2 | 35 | ||
| 3 | 3V |
Useremo la libreria EasyButton per leggere lo stato dei pulsanti. Per installarla apri il LIBRARY MANAGER, cerca la libreria “EasyButton by Evert Arias” e premi INSTALL:

Il codice qui sotto è il codice per il lettore MP3 con le funzioni aggiunte onNextTrack(), onPrevTrack() e updateVolume(), che vengono usate per saltare tracce o controllare il volume:
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.7
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
- [TickTwo](https://github.com/sstaub/TickTwo)
Version: 4.4.0
- [EasyButton](https://github.com/evert-arias/EasyButton)
Version: 2.0.3
*/
#include "TickTwo.h"
#include "EasyButton.h"
#include "AudioTools.h"
#include "AudioTools/Disk/AudioSourceSD.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
#define POT_PIN 35 // Poti for Volume
#define PATH "/"
#define EXT "mp3"
EasyButton nextBtn(4);
EasyButton prevBtn(15);
AudioSourceSD source(PATH, EXT);
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);
void printMetaData(MetaDataType type, const char* str, int len) {
Serial.printf("%s: %s\n", toStr(type), str);
}
void updateVolume() {
static float oldVol = -1;
long pot = analogRead(POT_PIN);
float vol = map(pot, 0, 4095, 0, 100) / 100.0;
if (fabs(vol - oldVol) >= 0.02) {
oldVol = vol;
player.setVolume(vol);
}
}
void onPrevTrack() {
Serial.println("Prev track");
player.next(-1);
}
void onNextTrack() {
Serial.println("Next track");
player.next(+1);
}
TickTwo timer(updateVolume, 100);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
player.setMetadataCallback(printMetaData);
player.setVolume(0.1);
player.begin();
pinMode(POT_PIN, INPUT);
timer.start();
nextBtn.begin();
nextBtn.onPressed(onNextTrack);
prevBtn.begin();
prevBtn.onPressed(onPrevTrack);
}
void loop() {
timer.update();
nextBtn.read();
prevBtn.read();
player.copy();
}
Esempio di codice: Text to Speech
Questo esempio di codice mostra come implementare un sistema Text-to-Speech (TTS) su ESP32 usando l’API TTS di OpenAI e inviare l’audio tramite un DAC PCM5102A. I dati audio vengono trasmessi in formato MP3, decodificati e riprodotti tramite l’interfaccia I2S. Il programma si connette al WiFi, invia il testo all’API OpenAI, riceve la voce sintetizzata e la riproduce in tempo reale.
/*
www.makerguides.com
Libraries:
- ESP32 Core 3.3.6
- [arduino-audio-tools](https://github.com/pschatzmann/arduino-audio-tools)
Version: 1.2.2
- [arduino-libhelix](https://github.com/pschatzmann/arduino-libhelix)
Version: 0.9.2
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
// PCM5102A
#define DIN_PIN 33 // serial data
#define LRCK_PIN 32 // word select
#define BCLK_PIN 25 // serial clock
// Text to Speech
#define TTS_MODEL "gpt-4o-mini-tts"
#define TTS_VOICE "marin"
#define TTS_VOLUME 0.6
// WiFi credentials
const char* ssid = "ssid";
const char* password = "pwd";
// OpenAI configuration
const char* openaiHost = "api.openai.com";
const int openaiPort = 443;
const char* openaiApiKey = "apikey";
WiFiClientSecure client;
I2SStream i2s;
VolumeStream volume(i2s);
EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix());
StreamCopy copier(mp3decode, client);
void text2speech(const char* text) {
client.setInsecure();
if (!client.connect("api.openai.com", 443)) {
Serial.println("Connection failed");
return;
}
String body = String("{") +
"\"model\":\"" + TTS_MODEL + "\"," +
"\"voice\":\"" + TTS_VOICE + "\"," +
"\"format\":\"mp3\"," +
"\"input\":\"" + text + "\"" +
"}";
client.println("POST /v1/audio/speech HTTP/1.1");
client.println("Host: api.openai.com");
client.println("Authorization: Bearer " + String(openaiApiKey));
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(body.length());
client.println();
client.print(body);
// ---- Skip HTTP headers ----
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") break;
}
}
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
mp3decode.begin();
volume.begin(config);
volume.setVolume(TTS_VOLUME);
text2speech("Hello, how are you doing today?");
}
void loop() {
copier.copy();
}
Import
Il codice inizia includendo le librerie necessarie. Arduino.h fornisce le funzioni core di Arduino. WiFi.h e WiFiClientSecure.h gestiscono la connessione WiFi e la comunicazione HTTPS sicura. La libreria AudioTools e il suo codec MP3 CodecMP3Helix vengono usati per lo streaming e la decodifica audio.
#include <Arduino.h> #include <WiFi.h> #include <WiFiClientSecure.h> #include "AudioTools.h" #include "AudioTools/AudioCodecs/CodecMP3Helix.h"
Costanti e definizione dei pin
I pin per il DAC PCM5102A sono definiti per configurare l’interfaccia I2S. Questi includono il pin dati seriali (DIN_PIN), il pin word select (LRCK_PIN) e il pin clock seriale (BCLK_PIN). Inoltre, vengono impostate costanti per il modello TTS, la voce e il livello di volume. Le credenziali WiFi e i dettagli API di OpenAI sono anch’essi dichiarati come puntatori a caratteri costanti.
// PCM5102A #define DIN_PIN 33 // serial data #define LRCK_PIN 32 // word select #define BCLK_PIN 25 // serial clock // Text to Speech #define TTS_MODEL "gpt-4o-mini-tts" #define TTS_VOICE "marin" #define TTS_VOLUME 0.6 // WiFi credentials const char* ssid = "ssid"; const char* password = "pwd"; // OpenAI configuration const char* openaiHost = "api.openai.com"; const int openaiPort = 443; const char* openaiApiKey = "apikey";
Puoi provare altri modelli TTS, come “tts-1” e altre voci come “alloy”, “ash”, “coral”, “echo”, “fable”, “onyx”, “nova”, ‘sage”, “shimmer”, “marin”, “cedar”. Per maggiori dettagli dai un’occhiata a platform.openai.com/docs/guides/text-to-speech.
Le credenziali WiFi e i dettagli API di OpenAI sono anch’essi memorizzati come stringhe costanti. Dovrai sostituire “ssid” e “pwd” con le credenziali della tua rete WiFi.
// WiFi credentials const char* ssid = "ssid"; const char* password = "pwd";
Dovrai anche ottenere una “apikey” da OpenAI. Vai su https://platform.openai.com e registrati con un indirizzo email o un account Google o Microsoft esistente.
// OpenAI configuration const char* openaiHost = "api.openai.com"; const int openaiPort = 443; const char* openaiApiKey = "apikey";
Dopo aver verificato l’email e completato la configurazione iniziale, accedi alla dashboard di OpenAI, platform.openai.com/api-keys e trova o crea la tua API Key (=SECRET KEY) come mostrato qui sotto:

La API Key è una stringa lunga e unica, che inizia con “sk-proj-” e serve per autenticare le richieste API (vedi sotto).
sk-proj-xcA.......................OtDu0U
Questo è tutto ciò che serve per ottenere una API key, ma ti consiglio di impostare anche un limite di utilizzo per il tuo account. Per maggiori dettagli vedi il Vision Chatbot with DFRobot ESP32-S3 AI Camera and OpenAI tutorial.
Oggetti audio e di rete
Vengono istanziati diversi oggetti per gestire lo streaming audio e la comunicazione di rete. WiFiClientSecure gestisce la connessione HTTPS al server OpenAI. I2SStream gestisce l’uscita audio I2S. L’oggetto VolumeStream incapsula lo stream I2S per controllare il volume audio. EncodedAudioStream viene usato per decodificare lo stream audio MP3 usando il decoder Helix MP3. Infine, StreamCopy copia lo stream audio decodificato verso il client di rete.
WiFiClientSecure client; I2SStream i2s; VolumeStream volume(i2s); EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix()); StreamCopy copier(mp3decode, client);
Funzione Text-to-Speech
La funzione text2speech() prende una stringa di testo in ingresso e la invia all’API TTS di OpenAI per generare l’audio vocale. Prima configura il client per accettare connessioni SSL insicure (utile per lo sviluppo). Poi tenta di connettersi al server OpenAI sulla porta 443. Se la connessione fallisce, stampa un messaggio di errore e ritorna.
La funzione costruisce un body JSON contenente il modello TTS, la voce, il formato di output (MP3) e il testo di input. Invia una richiesta HTTP POST con gli header appropriati, incluso il token di autorizzazione bearer con la API key. Dopo aver inviato il body della richiesta, legge e salta gli header della risposta HTTP per prepararsi a ricevere lo stream audio.
void text2speech(const char* text) {
client.setInsecure();
if (!client.connect("api.openai.com", 443)) {
Serial.println("Connection failed");
return;
}
String body = String("{") +
"\"model\":\"" + TTS_MODEL + "\"," +
"\"voice\":\"" + TTS_VOICE + "\"," +
"\"format\":\"mp3\"," +
"\"input\":\"" + text + "\"" +
"}";
client.println("POST /v1/audio/speech HTTP/1.1");
client.println("Host: api.openai.com");
client.println("Authorization: Bearer " + String(openaiApiKey));
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(body.length());
client.println();
client.print(body);
// ---- Skip HTTP headers ----
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") break;
}
}
Funzione Setup
Nella funzione setup() viene inizializzata la comunicazione seriale per il debug. L’audio logger è configurato per segnalare warning. L’ESP32 si connette alla rete WiFi specificata, aspettando finché la connessione non è stabilita.
Successivamente, l’interfaccia I2S viene configurata con i pin definiti prima per bit clock, word select e uscita dati. Il decoder MP3 e il controllo volume vengono inizializzati con questa configurazione e il volume viene impostato al livello definito.
Infine, viene chiamata la funzione text2speech() con un testo di saluto di esempio, che avvia il processo TTS e lo streaming audio dall’API OpenAI.
void setup() {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
auto config = i2s.defaultConfig(TX_MODE);
config.pin_bck = BCLK_PIN;
config.pin_ws = LRCK_PIN;
config.pin_data = DIN_PIN;
i2s.begin(config);
mp3decode.begin();
volume.begin(config);
volume.setVolume(TTS_VOLUME);
text2speech("Hello, how are you doing today?");
}
Funzione Loop
La funzione loop() copia continuamente lo stream audio MP3 decodificato dal server OpenAI all’uscita I2S. Questo mantiene la riproduzione audio attiva finché la connessione rimane aperta.
void loop() {
copier.copy();
}
Conclusioni
In questo progetto hai imparato come riprodurre audio usando l’ESP32 e il DAC PCM5102A. Abbiamo esplorato i dettagli tecnici del modulo PCM5102A e come collegarlo all’ESP32. Hai anche imparato a convertire testo in voce, ascoltare radio internet in streaming, riprodurre file MP3 da una SD Card e riprodurre audio via Bluetooth.
Per un suono migliore e più potente puoi collegare un amplificatore all’uscita linea del PCM5102A. Consulta i seguenti tutorial per maggiori informazioni:
- TDA7379 Class AB Audio Amplifier with ESP32
- High-Power ESP32 Audio with TPA3116D2 and PCM5102
- Audio with PAM8403, PCM5102 and ESP32
- Stereo Amplifier with TPA31110 XH-A232, PCM5102 and ESP32
- Playing Audio with ESP32 and MAX98357
Se hai domande sentiti libero di lasciarle nella sezione commenti.
Buon divertimento con i tuoi esperimenti ; )
FAQ
D: Cos’è il PCM5102A e perché dovrei usarlo?
Il PCM5102A è un convertitore digitale-analogico di alta qualità che si collega all’ESP32 tramite I2S e converte l’audio digitale in un segnale analogico stereo pulito, molto migliore rispetto al DAC interno dell’ESP32 e che offre suono più chiaro, meno rumore e qualità audio superiore per musica, voce o streaming.
D: Come si collega il PCM5102A all’ESP32?
Il PCM5102A usa tre segnali principali I2S più l’alimentazione.
Esempio di collegamento:
ESP32_3V3 ----> VIN ESP32_GND ----> GND ESP32_GPIO32 ----> LRCK ESP32_GPIO25 ----> BCK ESP32_GPIO33 ----> DIN SCK ----> GND // Optional
Il clock interno del PCM5102A elimina la necessità di un clock master esterno, semplificando il cablaggio.
D: Posso collegare direttamente un altoparlante al PCM5102A?
No, perché il PCM5102A fornisce solo un segnale di livello linea, troppo debole per pilotare direttamente un altoparlante e che deve essere prima amplificato.
Configurazione corretta:
PCM5102A --> Amplifier --> Speaker
Oppure con casse attive:
PCM5102A --> Active Speakers
D: Che amplificatore devo usare con il PCM5102A?
Puoi usare un piccolo amplificatore Class-D per progetti semplici o un amplificatore stereo più potente per un suono migliore e volume più alto.
Vedi il High-Power ESP32 Audio with TPA3116D2 and PCM5102 o il TDA7379 Class AB Audio Amplifier with ESP32 tutorial, ad esempio.
D: Come posso migliorare la qualità audio con un’alimentazione filtrata?
Un’alimentazione pulita è molto importante, perché il rumore sulla linea di alimentazione influisce direttamente sull’uscita del DAC. Puoi aggiungere dei condensatori:
VIN -- 100nF -- GND VIN -- 100µF -- GND
Il condensatore piccolo elimina il rumore ad alta frequenza, mentre quello grande riduce le ondulazioni di tensione e fornisce alimentazione stabile al DAC.
Se possibile, filtra anche l’alimentazione dell’amplificatore:
5V -- 10Ω --+-- AMP_VCC | 220µF | GND
Questo riduce il rumore proveniente dall’ESP32 o dall’alimentazione USB.
D: Devo usare alimentazioni separate per DAC e amplificatore?
Usare alimentazioni separate o filtrate può migliorare la qualità audio, perché l’amplificatore assorbe correnti elevate che possono introdurre rumore nell’alimentazione del DAC. Ad esempio:
5V ----> DAC 5V ----> Filter ----> Amplifier
Questo riduce le interferenze tra le sezioni digitali e di potenza.
D: Servono condensatori sull’uscita audio?
Di solito no, perché il PCM5102A ha già uno stadio di uscita privo di DC, ma in alcuni casi aggiungere un condensatore di accoppiamento può aiutare se l’ingresso dell’amplificatore è sensibile:
DAC_OUT -- 1µF -- AMP_IN
Questo può ridurre rumore a bassa frequenza o problemi di offset.
D: Come posso aumentare il volume?
Il volume dipende soprattutto dall’amplificatore e dalle casse, non dal DAC. Per aumentare il volume:
- Usa un amplificatore più potente
- Usa una tensione di alimentazione più alta (entro i limiti)
- Usa casse efficienti
Il DAC fornisce già un segnale di linea forte, quindi è lo stadio amplificatore a determinare il volume finale.
D: Qual è la differenza tra casse da 4Ω e 8Ω?
L’impedenza delle casse ha un grande effetto su volume e carico dell’amplificatore.
- Le casse da 4Ω assorbono più corrente e producono volume più alto
- Le casse da 8Ω assorbono meno corrente e sono più facili da pilotare
Molti piccoli amplificatori come il PAM8403 erogano più potenza su casse da 4Ω, ma devi assicurarti che l’amplificatore regga il carico senza surriscaldarsi o distorcere.
D: Come posso migliorare ulteriormente la qualità audio?
Ci sono diversi accorgimenti pratici che insieme fanno molta differenza.
Tieni i cablaggi corti:
DAC_L ----> AMP_L DAC_R ----> AMP_R
Evita di far passare i cavi audio vicino a quelli di alimentazione o degli altoparlanti.
Usa una massa a stella:
ESP32_GND ----+---- DAC_GND | AMP_GND
Questo evita che le correnti di rumore influenzino il segnale audio.
Usa buone casse, perché anche la migliore elettronica non può migliorare casse di scarsa qualità.
D: Perché la configurazione PCM5102A è molto più pulita rispetto a ESP32 DAC + amplificatore?
Puoi collegare un amplificatore direttamente ai DAC dell’ESP32. Vedi il Playing Sound with PAM8403 and ESP32 tutorial per i dettagli, ma la qualità audio non sarà molto buona, a causa della bassa risoluzione (8 bit) e del percorso del segnale analogico.
Il PCM5102A invece usa elaborazione digitale ad alta risoluzione e filtri interni, che eliminano la maggior parte del rumore e della distorsione prima che il segnale diventi analogico.
D: Qual è la configurazione migliore per qualità e volume massimi?
Per i migliori risultati, combina un DAC di alta qualità, un buon amplificatore e casse adeguate. Vedi il High-Power ESP32 Audio with TPA3116D2 and PCM5102 o il TDA7379 Class AB Audio Amplifier with ESP32 tutorial, ad esempio.

