Skip to Content

Riprodurre audio con ESP32 e MAX98357

Riprodurre audio con ESP32 e MAX98357

In questo post imparerai come utilizzare il modulo amplificatore MAX98357A con l’ESP32 per riprodurre audio.

Il MAX98357A è un compatto convertitore digitale-analogico (DAC) con amplificatore integrato. Riceve dati audio digitali tramite il protocollo I2S e fornisce audio amplificato direttamente a un altoparlante. Questa combinazione semplifica il cablaggio hardware e migliora la qualità del suono.

In questo tutorial imparerai a generare segnali audio, convertire testo in voce, ascoltare radio internet, riprodurre file MP3 da una scheda SD e utilizzare l’audio Bluetooth.

Overview

Componenti necessari

Ti servirà almeno un modulo MAX98357A. Se vuoi riprodurre audio stereo, avrai bisogno di due moduli MAX98357A. Allo stesso modo, ti serviranno due altoparlanti da 4-8 Ω e almeno 3 Watt.

Per riprodurre file MP3 da una scheda SD, ti servirà inoltre una scheda SD da almeno 1GB e un modulo lettore di schede SD.

Infine, ti serve un ESP32, una breadboard e alcuni cavi. Io ho usato un ESP32 lite, ma la maggior parte delle altre schede ESP32 dovrebbe funzionare. Se vuoi memorizzare e riprodurre musica dalla memoria, è meglio scegliere un ESP32-S3 con PSRAM.

2 x Amplificatore MAX98357A

2x Altoparlante 4Ω 5W

Lettore Micro SD Card

Micro SD Card 8GB

ESP32 lite Lolin32

ESP32 lite

USB data cable

Cavo USB dati

Dupont wire set

Set di cavi Dupont

Half_breadboard56a

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, usato per trasferire dati audio digitali da un ESP32 a un modulo amplificatore come il MAX98357.

I2S, o Inter-IC Sound, è uno standard di interfaccia 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: serial clock (SCK), word select (WS) e serial data (SD). Il serial clock pulsa alla velocità dei bit, determinando quando vengono inviati i bit. Il word select indica se i dati attuali corrispondono al canale audio sinistro o destro. Infine, la linea serial data trasporta i bit audio effettivi, trasmettendo prima il bit più significativo (MSB).

I2S Timing Diagram
Diagramma temporale I2S (source)

Tipicamente, i dati audio vengono inviati in parole da 16 o 24 bit, ma il protocollo può supportare altre profondità a seconda dell’hardware.

La periferica I2S dell’ESP32 supporta la comunicazione full-duplex, permettendo input e output audio simultanei. Può essere configurata 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 MAX98357A, che funziona come dispositivo slave I2S. Nella prossima sezione vediamo più da vicino il MAX98357A.

Caratteristiche tecniche del modulo MAX98357A

Il modulo MAX98357A è un amplificatore digitale che accetta direttamente l’input I2S. Converte il flusso audio digitale in segnale analogico e lo amplifica per pilotare gli altoparlanti. Integra un amplificatore Class-D da 3,2W con DAC integrato. L’interfaccia audio digitale riconosce fino a 35 diversi schemi di clock PCM e TDM, eliminando la necessità di programmazione I2C.

Block Diagram of the MAX98357A
Schema a blocchi del MAX98357A (source)

Il MAX98357A supporta campioni audio a 16, 24 e 32 bit con frequenze di campionamento da 8 kHz fino a 96 kHz. Questa flessibilità permette una riproduzione audio di alta qualità, adatta a voce, musica e altre applicazioni sonore.

Il modulo funziona con un’unica alimentazione da 3,3V o 5V, rendendolo compatibile con la maggior parte dei microcontrollori, incluso l’ESP32. Dispone di regolatore integrato a bassa caduta e protezione termica. L’immagine qui sotto mostra fronte e retro di un tipico modulo MAX98357A:

Front and Back of the MAX98357A Module
Fronte e retro del modulo MAX98357A

Sul lato input, il MAX98357A si aspetta tre segnali principali: bit clock (BCLK), word select (LRC) e serial data (SD). Il bit clock sincronizza i bit dei dati, mentre il word select indica se i dati attuali sono per il canale sinistro o destro. La linea serial data trasporta i campioni audio in un flusso continuo.

Functional Diagram of the MAX98357A
Schema funzionale del MAX98357A (source)

Internamente, il modulo converte i dati audio digitali in segnale analogico tramite il DAC integrato. Questo segnale analogico viene poi amplificato dallo stadio Class-D, che pilota un altoparlante da 4 o 8 Ω con 3 Watt.

Il MAX98357A include un controllo di guadagno e può essere configurato per produrre il canale sinistro, destro o un’uscita mista dall’input stereo tramite il pin SD. Nella sezione seguente vedremo questi pin più in dettaglio.

Pinout del modulo MAX98357A

Un tipico modulo MAX98357A ha pin per l’alimentazione (Vin, GND), per l’interfaccia I2S (LRC, BCLK, DIN), per il controllo del guadagno (GAIN) e per la selezione del canale e lo shutdown (SD). L’immagine qui sotto mostra il pinout:

Pinout of MAX98357A Module
Pinout del modulo MAX98357A

Alimentazione

Il pin VIN accetta da 3,3V a 5V. Il pin GND è la massa di riferimento e deve essere collegato alla massa dell’ESP32.

Il consumo di corrente del MAX98357A per una riproduzione audio a volume moderato è tipicamente tra 200mA e 400mA. Il regolatore di tensione di una tipica scheda ESP32 arriva a circa 800mA, ma l’ESP32 lite usa un ME6211 da soli 500mA.

Questo significa che puoi alimentare un MAX98357A dal pin 3.3V dell’ESP32, ma è rischioso, perché a volume alto e guadagno massimo la corrente può arrivare fino a 1,5A (a 5V). Quindi, è meglio alimentare il MAX98357A con una fonte esterna.

Nota che il MAX98357A include un limitatore di corrente in uscita per l’altoparlante di 2,8A. Se la corrente supera questo valore, il chip si spegne temporaneamente e si riavvia per proteggersi.

Interfaccia I2S

Il pin LRC sta per Left-Right Clock o Word Select. Indica se i dati audio attuali appartengono al canale sinistro o destro. L’ESP32 genera questo segnale come parte del protocollo I2S.

Il pin BCLK è il Bit Clock. Sincronizza i bit dei dati inviati sulla linea DIN. Anche questo segnale viene fornito dall’ESP32.

Il pin DIN è la linea di ingresso dati. Questo pin riceve i dati audio dall’ESP32.

Controllo del guadagno

Puoi controllare il guadagno del MAX98357A collegando il pin gain a VCC o GND direttamente o tramite una resistenza da 100K. La tabella seguente mostra quale collegamento corrisponde a quale guadagno.

Guadagno Collegamento
15dB GAIN — 100K — GND
12dB GAIN — GND
9dB Nessuno
6dB GAIN — VCC
3dB GAIN — 100K — VCC

Il guadagno di 9dB è l’impostazione predefinita e in questo caso non serve alcun collegamento.

Controllo del canale

Il pin SD (Shutdown) del MAX98357A permette di spegnere l’amplificatore o di selezionare il canale destro, sinistro o un’uscita mista dall’input stereo. L’immagine qui sotto mostra lo schema del modulo MAX98357A con il pin SD Mode e le informazioni su come selezionare il canale:

Schematics of MAX98357A Module
Schema del modulo MAX98357A

Se il pin SD non è collegato (default), l’amplificatore genera un’uscita mista tra canale sinistro e destro ((L+R)/2). Se il pin SD è collegato a massa, l’amplificatore è spento. Altrimenti, la tensione su SD determina se viene amplificato il canale sinistro o destro. La tabella seguente mostra le tensioni richieste sul pin SD per attivare le diverse funzioni:

Tensione @ SD Funzione
< 0.16V Amplificatore spento
0.16 … 0.77V Canale sinistro e destro misti ((L+R)/2)
0.77 … 1.4V Canale destro (370KΩ @ 5V, 210KΩ @ 3V3)
> 1.4V Solo canale sinistro (100kΩ)

Per ottenere la tensione richiesta sul pin SD per selezionare il canale destro, devi collegare il pin SD a VCC tramite una resistenza adeguata. Lo schema mostra la seguente formula:

R = (94 * VDD – 100) KΩ

Questo significa che, a 5V serve una resistenza da 370KΩ tra SD e 5V, mentre a 3.3V serve una resistenza da 210KΩ.

Per selezionare il canale sinistro puoi usare una resistenza da 100kΩ sia a 5V che a 3.3V. Se vuoi l’uscita mista (mono sommato), lascia semplicemente il pin SD scollegato.

Datasheet

Il pulsante seguente porta al datasheet del MAX98357A, dove puoi trovare ulteriori dettagli tecnici:

Collegare MAX98357A all’ESP32

In questa sezione vedrai i diversi modi per collegare il MAX98357A e gli altoparlanti a un ESP32.

Mono sommato

Partiamo dalla configurazione più semplice. Usiamo un solo MAX98357A e un solo altoparlante per riprodurre un segnale stereo misto (50% canale sinistro, 50% canale destro).

Collega Vin del MAX98357A a 3.3V dell’ESP32 e GND a G. Poi collega i pin I2S come mostrato nella tabella seguente:

MAX98357A ESP32
Vin 3V3
GND G
LRC 32
BCLK 25
DIN 33

Lascia i pin GAIN e SD del MAX98357A scollegati. In questo modo verrà generato un mix di canale sinistro e destro con guadagno di 9dB.

Quando colleghi l’altoparlante, fai attenzione alla polarità corretta e usa un altoparlante da 4Ω o 8Ω con almeno 3W. Puoi usare altoparlanti con wattaggio superiore, ma non inferiore.

L’immagine seguente mostra il cablaggio completo di un MAX98357A con un ESP32 lite per audio mono sommato (mix) alimentato dal pin 3.3V:

Single MAX98357A with ESP32 at 3.3V for Mono Sound
Singolo MAX98357A con ESP32 a 3.3V per audio mono

Come già detto, il MAX98357A può assorbire fino a 1,5A quando riproduce suoni forti al massimo guadagno. Il pin 3.3V dell’ESP32 non può fornire tutta questa corrente, quindi serve un’alimentazione esterna. L’immagine sotto mostra come collegare un’alimentazione esterna a 5V al circuito:

Single MAX98357A with ESP32 with external 5V for Mono Sound
Singolo MAX98357A con ESP32 e alimentazione esterna a 5V per audio mono

Stereo

Se vuoi riprodurre audio stereo, ti servono due altoparlanti, due MAX98357A (uno per canale) e resistenze per selezionare il canale sinistro o destro. L’immagine sotto mostra il cablaggio completo:

Two MAX98357A with ESP32 at 3.3V for Stereo Sound
Due MAX98357A con ESP32 a 3.3V per audio stereo

Entrambi i MAX98357A sono collegati in parallelo, usando gli stessi pin di alimentazione e I2S come prima. L’unica differenza è che il MAX98357A per il canale sinistro ha una resistenza da 100KΩ tra SD e 3.3V, mentre quello per il canale destro ha una resistenza da 210KΩ.

Nota che l’ESP32 deve produrre un segnale stereo e il MAX98357A seleziona semplicemente il canale sinistro o destro dell’input stereo in base alla tensione sul pin SD.

Come prima, invece di alimentare il MAX98357A tramite il pin 3.3V dell’ESP32, è più sicuro usare un’alimentazione esterna. Lo schema mostra come usare un alimentatore esterno a 5V:

Two MAX98357A with ESP32 with external 5V for Stereo Sound
Due MAX98357A con ESP32 e alimentazione esterna a 5V per audio stereo

Nota che il pin SD del MAX98357A è ancora collegato a 3.3V tramite una resistenza da 100KΩ o 210KΩ. Puoi collegare le resistenze anche all’alimentazione esterna a 5V, ma in questo caso per il canale destro dovresti usare una resistenza da 370KΩ invece di 210KΩ. La resistenza da 100KΩ per il canale sinistro può restare invariata.

Scheda SD

Se vuoi riprodurre file audio, devi collegare un lettore di schede SD che memorizza i file audio su una scheda SD. Lo schema seguente mostra come collegare un lettore SD e il MAX98357A a un ESP32:

Single MAX98357A with ESP32 and SD Card Reader for Mono Sound
Singolo MAX98357A con ESP32 e lettore SD per audio mono

Il lettore SD comunica tramite SPI e i pin SPI predefiniti dell’ESP32 sono CS=5, MOSI=23, CLK=18 e MISO=19. La tabella sotto riassume i collegamenti da fare tra il lettore SD 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 predefiniti del tuo ESP32, dai un’occhiata alla Find I2C and SPI default pins guida.

Se vuoi riprodurre audio stereo, devi collegare due moduli MAX98357A. Lo schema seguente mostra come fare:

Two MAX98357A with ESP32 and SD Card Reader for Stereo Sound
Due MAX98357A con ESP32 e lettore SD per audio stereo

Se hai bisogno di aiuto per collegare il lettore SD, consulta la nostra SD Card Module with ESP32 guida.

Installazione delle librerie

Ci sono diverse librerie Arduino che puoi usare per generare audio per un dispositivo I2S come il MAX98357A. Di seguito ti presento brevemente le tre più usate.

Per prima cosa, c’è la libreria ESP8266Audio di Earle F. Philhower, che supporta schede ESP8266, ESP32, Raspberry Pi Pico RP2040 e Pico 2 RP2350.

Poi c’è la libreria ESP32-audioI2S di schreibfaul1. Nota che questa libreria funziona solo su chip multi-core come ESP32, ESP32-S3, ESP32-P4 e la tua scheda deve avere PSRAM. Non funziona su ESP32-S2, ESP32-C3.

Infine, c’è la libreria arduino-audio-tools di Phil Schatzmann, che è la più potente e ricca di funzioni. È la libreria che useremo in questo tutorial, ma anche le altre meritano di essere provate.

Installa core ESP32

A gennaio 2026, non sono riuscito a far funzionare la libreria arduino-audio-tools con il core ESP32 attuale (Versione 3.3.6). Per gli esempi di questo tutorial devi fare il downgrade del core ESP32 alla versione 2.0.17.

Supponendo che tu abbia già installato il core ESP32, il downgrade è semplice. Apri il BOARDS MANAGER, digita “esp32” nella barra di ricerca, poi seleziona la versione 2.0.17 per il core “esp32 by Espressif” e clicca su “UPDATE” come mostrato sotto:

Installing ESP32 Core Version 2.0.17
Installazione core ESP32 versione 2.0.17

Se hai bisogno di aiuto per il downgrade o per installare il core ESP, consulta la Install ESP32 core in Arduino IDE guida.

Installa la libreria arduino-audio-tools

Per installare la libreria arduino-audio-tools 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 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 esempi di codice servono altre due librerie di Phil Schatzmann: 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.

Riproduci suono di test

Prima di provare qualcosa di complesso, facciamo un test audio. Questo ci permette di verificare il cablaggio tra MAX98357A ed ESP32 e che i canali sinistro e destro siano selezionati correttamente in stereo. Inoltre, questo codice non richiede librerie e funziona sia con il core ESP32 attuale (3.x) che con quello vecchio (2.x).

#include <driver/i2s.h>
#include <math.h>

#define I2S_PORT I2S_NUM_0

// MAX98357
#define MAX_DIN 33   
#define MAX_LRC 32   
#define MAX_BCLK 25  

// Audio parameters
#define SAMPLE_RATE 44100
#define TONE_FREQ 500
#define AMPLITUDE 1000  // Max 32767

// Channels
#define LEFT false
#define RIGHT true

// Buffer size (frames, not samples)
#define BUFFER_LEN 256

// Stereo buffer: Left, Right
int16_t samples[BUFFER_LEN * 2];

void setup() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = BUFFER_LEN,
    .use_apll = false,
    .tx_desc_auto_clear = true,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = MAX_BCLK,
    .ws_io_num = MAX_LRC,
    .data_out_num = MAX_DIN,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_PORT, &pin_config);
}

void loop() {
  static float phase = 0.0;
  const float phaseIncrement = 2.0 * PI * TONE_FREQ / SAMPLE_RATE;

  for (int i = 0; i < BUFFER_LEN; i++) {
    int16_t sound = (int16_t)(AMPLITUDE * sin(phase));
    int16_t silence = 0;

    samples[2 * i] = (LEFT) ? sound : silence;       // Left channel
    samples[2 * i + 1] = (RIGHT) ? sound : silence;  // Right channel

    phase += phaseIncrement;
    if (phase >= 2.0 * PI) phase -= 2.0 * PI;
  }

  size_t bytes_written;
  i2s_write(I2S_PORT, samples, sizeof(samples), &bytes_written, portMAX_DELAY);
}

Il codice configura l’ESP32 come trasmettitore I2S master, genera in tempo reale un’onda sinusoidale audio e la invia all’amplificatore per produrre suono sul canale sinistro, destro o entrambi.

Import

Il codice include la libreria driver/i2s.h, che fornisce le funzioni driver I2S dell’ESP32 per la comunicazione audio. Include anche la libreria matematica standard math.h per usare funzioni come sin() per generare la forma d’onda audio.

#include <driver/i2s.h>;
#include <math.h>;

Costanti

Sono definite diverse costanti per configurare l’interfaccia I2S e i parametri audio. I2S_PORT seleziona la periferica I2S numero 0 sull’ESP32. I pin MAX_DIN, MAX_LRC e MAX_BCLK corrispondono ai segnali dati, word select (left-right clock) e bit clock collegati al MAX98357.

I parametri audio includono sample rate di 44.100 Hz, frequenza del tono di 500 Hz e ampiezza di 1000 (su un range di interi a 16 bit con segno). Fondamentale, il codice definisce anche i flag booleani LEFT e RIGHT per controllare quali canali audio emettono suono.

Infine, BUFFER_LEN imposta il numero di frame audio per buffer, e un array stereo samples contiene i campioni audio interlacciati dei canali sinistro e destro.

#define I2S_PORT I2S_NUM_0

// MAX98357
#define MAX_DIN 33   
#define MAX_LRC 32   
#define MAX_BCLK 25  

// Audio parameters
#define SAMPLE_RATE 44100
#define TONE_FREQ 500
#define AMPLITUDE 1000  // Max 32767

// Channels
#define LEFT false
#define RIGHT true

// Buffer size (frames, not samples)
#define BUFFER_LEN 256

// Stereo buffer: Left, Right
int16_t samples[BUFFER_LEN * 2];

Funzione setup

La funzione setup() inizializza il driver I2S e configura i pin per la comunicazione con il MAX98357.

Viene creato uno struct i2s_config_t per specificare la modalità I2S come master transmitter, campioni a 16 bit, formato stereo (right and left) e sample rate di 44.1 kHz. Imposta anche i parametri DMA per un trasferimento dati efficiente.

Poi, uno struct i2s_pin_config_t assegna i pin GPIO per bit clock (bck_io_num), word select (ws_io_num) e data output (data_out_num). Il pin data input non viene usato e impostato a I2S_PIN_NO_CHANGE.

Infine, il driver I2S viene installato con i2s_driver_install() e la configurazione dei pin applicata con i2s_set_pin().

void setup() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = BUFFER_LEN,
    .use_apll = false,
    .tx_desc_auto_clear = true,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = MAX_BCLK,
    .ws_io_num = MAX_LRC,
    .data_out_num = MAX_DIN,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_PORT, &pin_config);
}

Funzione loop

La funzione loop() genera continuamente campioni audio e li invia alla periferica I2S per la riproduzione.

Una variabile statica phase tiene traccia della posizione corrente nell’onda sinusoidale. Il phaseIncrement viene calcolato in base alla frequenza del tono desiderata e al sample rate, determinando di quanto avanza la fase per ogni campione.

Nel ciclo, il codice riempie il buffer samples con dati audio stereo interlacciati. Per ogni frame, calcola il seno della fase corrente, lo scala per l’ampiezza e lo converte in intero a 16 bit. In base ai flag LEFT e RIGHT, il suono viene assegnato al canale sinistro e/o destro, mentre l’altro canale viene azzerato.

La fase viene incrementata e riportata nel range 0-2π radianti, per garantire una forma d’onda continua.

Dopo aver riempito il buffer, la funzione i2s_write() invia i dati audio al driver I2S, che li trasmette all’amplificatore. La funzione blocca finché tutti i byte non sono scritti, mantenendo la riproduzione fluida.

void loop() {
  static float phase = 0.0;
  const float phaseIncrement = 2.0 * PI * TONE_FREQ / SAMPLE_RATE;

  for (int i = 0; i < BUFFER_LEN; i++) {
    int16_t sound = (int16_t)(AMPLITUDE * sin(phase));
    int16_t silence = 0;

    samples[2 * i] = (LEFT) ? sound : silence;       // Left channel
    samples[2 * i + 1] = (RIGHT) ? sound : silence;  // Right channel

    phase += phaseIncrement;
    if (phase >= 2.0 * PI) phase -= 2.0 * PI;
  }

  size_t bytes_written;
  i2s_write(I2S_PORT, samples, sizeof(samples), &bytes_written, portMAX_DELAY);
}

Puoi usare questo codice per verificare che l’audio stereo venga riprodotto correttamente usando due moduli MAX98357 e due altoparlanti. Se imposti la costante LEFT su true e RIGHT su false, solo l’altoparlante sinistro deve suonare. Allo stesso modo puoi verificare il canale destro. Se non funziona, controlla tensione e resistenze sul pin SD del MAX98357, che controlla il canale.

Per i prossimi esempi useremo la libreria arduino-audio-tools, che nasconde tutti i dettagli della comunicazione I2S e semplifica il codice.

Text to speech

Questo esempio mostra come convertire testo in voce usando l’interfaccia I2S con un amplificatore MAX98357. Si connette al WiFi, invia il testo all’API Text-to-Speech (TTS) di OpenAI, riceve uno stream audio MP3, lo decodifica e lo riproduce tramite l’amplificatore. Il codice usa la libreria arduino-audio-tools per gestire streaming e decodifica audio.

/*
www.makerguides.com

Libraries:
- ESP32 Core 2.0.17
- [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"

// MAX98357 I2S pins
#define MAX_DIN   33
#define MAX_LRC   32
#define MAX_BCLK  25

// 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  = MAX_BCLK;
  config.pin_ws   = MAX_LRC;
  config.pin_data = MAX_DIN;
  i2s.begin(config);

  mp3decode.begin();
  volume.begin(config);
  volume.setVolume(TTS_VOLUME);

  text2speech("Hello, this a test for text to speech.");
}

void loop() {
  copier.copy();
}

Import

Il codice inizia includendo diverse librerie. Arduino.h è la libreria core di Arduino. WiFi.h e WiFiClientSecure.h forniscono connettività WiFi e client HTTPS sicuro. La libreria AudioTools e il suo codec MP3 CodecMP3Helix sono usati per streaming e decodifica audio.

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"

Costanti e definizione dei pin

Poi vengono definiti i pin usati per l’interfaccia I2S verso il MAX98357. Questi pin corrispondono all’ingresso dati (MAX_DIN), word select o left-right clock (MAX_LRC) e bit clock (MAX_BCLK).

// MAX98357 I2S pins
#define MAX_DIN   33
#define MAX_LRC   32
#define MAX_BCLK  25

Inoltre, vengono impostate costanti per il modello TTS, la voce e il livello di volume.

// Text to Speech
#define TTS_MODEL "gpt-4o-mini-tts"
#define TTS_VOICE "marin"
#define TTS_VOLUME 0.6

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 guarda platform.openai.com/docs/guides/text-to-speech.

Le credenziali WiFi e i dettagli API di OpenAI sono memorizzati come stringhe costanti. Dovrai sostituire “ssid” e “pwd” con le credenziali del tuo 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’email o un account Google/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 sotto:

OpenAI API keys
Chiavi API OpenAI

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 la Vision Chatbot with DFRobot ESP32-S3 AI Camera and OpenAI guida.

Oggetti audio e di rete

Vengono istanziati diversi oggetti per gestire streaming audio e comunicazione di rete. WiFiClientSecure gestisce la connessione HTTPS all’API OpenAI. I2SStream gestisce l’output audio I2S. VolumeStream avvolge lo stream I2S per controllare il volume. EncodedAudioStream decodifica i dati audio MP3 usando il decoder Helix MP3. Infine, StreamCopy copia lo stream audio decodificato dal client di rete all’output audio.

WiFiClientSecure client;
I2SStream i2s;
VolumeStream volume(i2s);
EncodedAudioStream mp3decode(&volume, new MP3DecoderHelix());
StreamCopy copier(mp3decode, client);

Funzione Text-to-Speech

La funzione text2speech() invia una stringa di testo all’API TTS di OpenAI e prepara lo stream audio per la riproduzione. Prima configura il client per accettare certificati insicuri (utile in sviluppo). Poi tenta di connettersi al server OpenAI sulla porta 443. Se la connessione fallisce, stampa un messaggio di errore e termina.

La funzione costruisce un body JSON specificando modello TTS, voce, formato output (MP3) e il testo di input. Invia una richiesta HTTP POST con gli header appropriati, inclusa l’autorizzazione tramite API key. Dopo aver inviato il body, legge e salta gli header della risposta HTTP per posizionare lo stream del client all’inizio dei dati audio MP3.

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

La funzione setup() inizializza la comunicazione seriale per il debug e imposta il logger audio per mostrare i warning. Poi si connette al WiFi specificato, aspettando finché la connessione non è stabilita.

Dopo la connessione WiFi, l’interfaccia I2S viene configurata in modalità trasmissione con i pin definiti prima. Lo stream I2S, il decoder MP3 e il controllo volume vengono inizializzati. Il volume viene impostato al livello predefinito.

Infine, viene chiamata la funzione text2speech() con una stringa di testo di esempio per iniziare lo streaming e la riproduzione della voce sintetizzata.

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  = MAX_BCLK;
  config.pin_ws   = MAX_LRC;
  config.pin_data = MAX_DIN;
  i2s.begin(config);

  mp3decode.begin();
  volume.begin(config);
  volume.setVolume(TTS_VOLUME);

  text2speech("Hello, this a test for text to speech.");
}

Funzione loop

La funzione loop() copia continuamente i dati dallo stream del decoder MP3 all’output audio I2S. Questo mantiene la riproduzione audio finché ci sono dati disponibili dal client di rete.

void loop() {
  copier.copy();
}

Radio internet

Questo esempio mostra come realizzare una semplice web radio. Si connette a una rete WiFi, riceve uno stream radio internet in formato MP3, decodifica l’audio, regola il volume e invia il suono all’amplificatore digitale MAX98357.

/*
www.makerguides.com

Libraries:
- ESP32 Core 2.0.17
- [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"

// MAX98357
#define MAX_DIN 33   // serial data
#define MAX_LRC 32   // word select
#define MAX_BCLK 25  // serial clock
#define MAX_VOL 0.5  // 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 = MAX_BCLK;
  config.pin_ws = MAX_LRC;
  config.pin_data = MAX_DIN;

  i2s.begin(config);
  volume.begin(config);
  volume.setVolume(MAX_VOL);
  mp3decode.begin();
  icystream.begin(url);
  icystream.setMetadataCallback(callbackMetadata);
}

void loop() {
  copier.copy();
}

Import

Il codice inizia includendo le librerie necessarie per la connettività WiFi, la comunicazione I2C e l’elaborazione audio. Le librerie Arduino.h e WiFi.h forniscono le funzioni base di Arduino e WiFi. La libreria Wire.h è inclusa per la comunicazione I2C, spesso usata per controllare periferiche. La libreria AudioTools e i suoi componenti gestiscono streaming, decodifica e riproduzione audio.

#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Communication/HTTP/ICYStream.h"

Costanti

Poi vengono definiti i pin per l’amplificatore MAX98357. Questi corrispondono ai segnali I2S: MAX_DIN per l’ingresso dati seriale, MAX_LRC per il word select (left-right clock) e MAX_BCLK per il serial clock. Il volume è impostato come valore float tra 0 e 1, dove MAX_VOL è 0.5, cioè 50% del volume.

#define MAX_DIN 33   // serial data
#define MAX_LRC 32   // word select
#define MAX_BCLK 25  // serial clock
#define MAX_VOL 0.5  // Volume

Credenziali WiFi e URL stream

Le credenziali della rete WiFi sono memorizzate nelle costanti ssid e password. La costante url contiene l’indirizzo dello stream radio internet da riprodurre, in questo caso uno stream jazz.

const char* ssid = "ssid";
const char* password = "pwd";
const char* url = "https://jazz.stream.laut.fm/jazz";

Ecco altri URL di 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 audio

Vengono istanziati diversi oggetti per gestire la pipeline audio. L’oggetto ICYStream gestisce lo streaming HTTP della radio internet e l’output audio I2S. L’oggetto VolumeStream avvolge lo stream I2S per controllare il volume. E l’oggetto EncodedAudioStream decodifica i dati MP3 usando il codec MP3DecoderHelix. Infine, 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 callback metadata

La funzione callbackMetadata() è definita per gestire i metadata ricevuti dallo stream radio, come titoli dei brani o informazioni sull’artista. Stampa il tipo di metadata e il contenuto sul monitor seriale per debug o informazione.

void callbackMetadata(MetaDataType type, const char* str, int len) {
  Serial.printf("%s: %s\n", toStr(type), str);
}

Funzione setup

Nella funzione setup() la comunicazione seriale viene inizializzata a 115200 baud per log e debug. Il logger audio è configurato per mostrare warning e messaggi più importanti sul monitor seriale.

L’ESP32 tenta poi di connettersi alla rete WiFi specificata, controllando lo stato ogni 500 millisecondi finché la connessione non va a buon fine.

Dopo la connessione, la configurazione I2S viene ottenuta usando la modalità trasmissione di default. I pin I2S vengono assegnati alle costanti definite prima per bit clock, word select e data input. L’interfaccia I2S e il controllo volume vengono inizializzati con questa configurazione e il volume impostato al 50%.

Il decoder MP3 viene avviato e lo stream radio internet inizializzato con l’URL fornito. La funzione callback per i metadata viene registrata per gestire i metadata durante la riproduzione.

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 = MAX_BCLK;
  config.pin_ws = MAX_LRC;
  config.pin_data = MAX_DIN;

  i2s.begin(config);
  volume.begin(config);
  volume.setVolume(MAX_VOL);
  mp3decode.begin();
  icystream.begin(url);
  icystream.setMetadataCallback(callbackMetadata);
}

Funzione loop

La funzione loop() copia continuamente i dati audio dallo stream radio, attraverso il decoder MP3 e il controllo volume, fino all’output I2S. Questo mantiene la riproduzione audio attiva senza interruzioni.

void loop() {
  copier.copy();
}

Se vuoi aggiungere altre funzioni come un controllo volume, guarda la nostra Playing Audio with ESP32 and PCM5102A guida. Se vuoi aggiungere un display, vedi la Internet Radio with ESP32 and MAX 98357A guida.

Riproduci MP3 da scheda SD

Questo esempio mostra come riprodurre file audio MP3 memorizzati su una scheda SD usando un ESP32, l’amplificatore I2S MAX98357 e la libreria AudioTools. Il codice inizializza l’hardware audio, imposta il decoder MP3 e invia continuamente i dati audio all’amplificatore.

/*
www.makerguides.com

Libraries:
- ESP32 Core 2.0.17
- [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"

// MAX98357
#define MAX_DIN 33   
#define MAX_LRC 32   
#define MAX_BCLK 25  

#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 cfg = i2s.defaultConfig(TX_MODE);
  cfg.pin_bck = MAX_BCLK;  
  cfg.pin_ws = MAX_LRC;    
  cfg.pin_data = MAX_DIN;    
  i2s.begin(cfg);

  //source.setFileFilter("*Bob Dylan*");
  player.setMetadataCallback(printMetaData);
  player.setVolume(0.4);
  player.begin();
}

void loop() {
  player.copy();
}

Import

Il codice inizia includendo gli header della libreria AudioTools. Questi forniscono le classi e funzioni necessarie per gestire sorgenti audio, decodificare file MP3 e inviare dati audio via I2S.

#include "AudioTools.h"
#include "AudioTools/Disk/AudioSourceSD.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"

Costanti

Poi vengono definiti i pin collegati al MAX98357. Questi specificano i pin di ingresso dati I2S (MAX_DIN), word select o left-right clock (MAX_LRC) e bit clock (MAX_BCLK) sull’ESP32.

#define MAX_DIN 33   
#define MAX_LRC 32   
#define MAX_BCLK 25  

Inoltre, vengono impostate costanti per il percorso della sorgente audio e l’estensione dei file. Qui, PATH è la directory root sulla scheda SD e EXT specifica che verranno considerati solo file MP3.

#define PATH "/"
#define EXT "mp3"

Oggetti

Vengono istanziati diversi oggetti per gestire la pipeline di riproduzione audio. AudioSourceSD rappresenta la sorgente audio SD, filtrando i file per percorso ed estensione. I2SStream gestisce lo stream audio I2S. MP3DecoderHelix è il decoder MP3 basato sul codec Helix. Infine, AudioPlayer collega questi componenti per gestire la riproduzione.

AudioSourceSD source(PATH, EXT);
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);

Funzione callback metadata

La funzione printMetaData() è definita per gestire informazioni metadata come artista o titolo del brano. Riceve il tipo di metadata e la stringa, poi la stampa sulla console seriale per debug o informazione.

void printMetaData(MetaDataType type, const char* str, int len){
  Serial.printf("%s: %s\n", toStr(type), str);
}

Funzione setup

Nella funzione setup() la comunicazione seriale viene inizializzata a 115200 baud per il logging. Anche il logger AudioTools viene avviato a livello warning per catturare i messaggi importanti.

La configurazione I2S viene ottenuta dalle impostazioni di default per la modalità trasmissione. I pin per bit clock, word select e data vengono assegnati alle costanti definite prima, corrispondenti ai collegamenti MAX98357. Lo stream I2S viene poi inizializzato con questa configurazione.

Opzionalmente, puoi impostare un filtro sui file della sorgente audio per riprodurre solo quelli che corrispondono a un pattern (commentato in questo esempio). La callback metadata viene impostata sulla funzione printMetaData() per ricevere metadata durante la riproduzione. Il volume viene impostato al 40% per controllare la potenza in uscita. Infine, il player audio viene avviato.

void setup() {
  Serial.begin(115200);
  AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);

  auto cfg = i2s.defaultConfig(TX_MODE);
  cfg.pin_bck = MAX_BCLK;  
  cfg.pin_ws = MAX_LRC;    
  cfg.pin_data = MAX_DIN;    
  i2s.begin(cfg);

  //source.setFileFilter("*Bob Dylan*");
  player.setMetadataCallback(printMetaData);
  player.setVolume(0.4);
  player.begin();
}

Funzione loop

La funzione loop() richiama continuamente player.copy(), che gestisce lo streaming dei dati audio dalla SD, attraverso il decoder, fino all’uscita I2S verso l’amplificatore. Questo mantiene la riproduzione fluida senza bloccare altri processi.

void loop() {
  player.copy();
}

Se vuoi aggiungere funzioni come controllo volume e pulsanti per cambiare traccia, guarda la Playing Audio with ESP32 and PCM5102A guida.

Riproduci audio da Bluetooth

Questo esempio mostra come ricevere e riprodurre audio Bluetooth. Il codice configura l’interfaccia I2S con pin specifici e inizializza un sink Bluetooth A2DP, permettendo all’ESP32 di ricevere e riprodurre audio da dispositivi Bluetooth.

/*
www.makerguides.com

Libraries:
- ESP32 Core 2.0.17
- [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 MAX_DIN 33   // serial data
#define MAX_LRC 32   // word select
#define MAX_BCLK 25  // serial clock

I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);

void setup() {
  auto cfg = i2s.defaultConfig();
  cfg.pin_bck = MAX_BCLK;
  cfg.pin_ws = MAX_LRC;
  cfg.pin_data = MAX_DIN;
  i2s.begin(cfg);

  a2dp_sink.start("MyMusic");
}

void loop() { }

Import

Il codice inizia includendo due librerie importanti. La libreria AudioTools.h fornisce strumenti per gestire stream audio e configurare l’interfaccia I2S. La libreria BluetoothA2DPSink.h permette all’ESP32 di agire come sink Bluetooth A2DP, cioè può ricevere stream audio da sorgenti Bluetooth come smartphone.

#include "AudioTools.h"
#include "BluetoothA2DPSink.h"

Costanti

Poi vengono definite tre costanti per specificare i pin GPIO usati per l’interfaccia I2S. Questi pin collegano l’ESP32 all’amplificatore MAX98357. MAX_DIN è il pin di ingresso dati seriale, MAX_LRC è il pin word select o left-right clock, e MAX_BCLK è il pin serial clock.

#define MAX_DIN 33   // serial data
#define MAX_LRC 32   // word select
#define MAX_BCLK 25  // serial clock

Oggetti

Viene creato un oggetto I2SStream chiamato i2s per gestire lo stream audio I2S. Poi, un oggetto BluetoothA2DPSink chiamato a2dp_sink viene istanziato, passandogli l’oggetto i2s. Questa configurazione collega direttamente l’input audio Bluetooth all’output I2S, permettendo la riproduzione audio tramite l’amplificatore.

I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);

Funzione setup

All’interno della funzione setup(), l’interfaccia I2S viene configurata e avviata. Prima si ottiene la configurazione I2S di default chiamando i2s.defaultConfig(). Poi si assegnano i pin per bit clock (pin_bck), word select (pin_ws) e data input (pin_data) alle costanti definite prima. Infine, l’interfaccia I2S viene inizializzata con questa configurazione chiamando i2s.begin(cfg).

Dopo aver configurato I2S, il sink Bluetooth A2DP viene avviato con il nome dispositivo "MyMusic". Questo nome apparirà quando altri dispositivi Bluetooth cercheranno dispositivi audio disponibili.

void setup() {
  auto cfg = i2s.defaultConfig();
  cfg.pin_bck = MAX_BCLK;
  cfg.pin_ws = MAX_LRC;
  cfg.pin_data = MAX_DIN;
  i2s.begin(cfg);

  a2dp_sink.start("MyMusic");
}

Per provare, apri il tuo telefono, cerca “dispositivi connessi” o “dispositivi Bluetooth”, trova il dispositivo “MyMusic”, connettiti e poi riproduci della musica. Dovresti sentirla uscire dal tuo ESP32 e MAX98357.

Funzione loop

La funzione loop() è vuota perché tutto lo streaming e la riproduzione audio sono gestiti in modo asincrono dal sink Bluetooth A2DP e dall’interfaccia I2S. Una volta avviato, l’ESP32 ascolta continuamente gli stream audio Bluetooth e li invia via I2S all’amplificatore senza bisogno di altro codice nel loop principale.

void loop() { }

Conclusioni

In questo progetto hai imparato a riprodurre audio usando ESP32 e l’amplificatore MAX98357. Abbiamo visto i dettagli tecnici del modulo MAX98357A e come collegarlo all’ESP32 per audio mono o stereo. Hai anche imparato a convertire testo in voce, ascoltare radio internet, riprodurre file MP3 da una scheda SD e riprodurre audio via Bluetooth.

Se vuoi aggiungere funzioni come controllo volume e pulsanti per cambiare traccia, guarda la nostra Playing Audio with ESP32 and PCM5102A guida. Se invece vuoi approfondire il modulo lettore SD usato qui, dai un’occhiata alla SD Card Module with ESP32 guida.

Per un suono migliore e più potente puoi usare il DAC PCM5102A e aggiungere un amplificatore. Consulta i seguenti tutorial per maggiori informazioni:

Se hai domande, sentiti libero di lasciarle nei commenti.

Buon tinkering ; )

FAQ

D: Cos’è il MAX98357A e perché dovrei usarlo?

Il MAX98357A è un amplificatore audio digitale con DAC integrato, cioè riceve direttamente l’audio digitale dall’ESP32 tramite I2S e fornisce un segnale già amplificato che può pilotare un altoparlante senza bisogno di altri amplificatori, semplificando il circuito e migliorando la qualità audio rispetto al DAC interno dell’ESP32.

D: Come si collega il MAX98357A all’ESP32?

Il modulo usa tre segnali I2S più l’alimentazione.

Collegamento tipico:

ESP32_3V3 or 5V ----> VIN
ESP32_GND ---------> GND

ESP32_GPIO25 -----> BCLK
ESP32_GPIO32 -----> LRC
ESP32_GPIO33 -----> DIN

L’ESP32 agisce da master I2S e invia i dati audio, mentre il MAX98357A li riceve e li trasforma in suono.

D: Posso collegare un altoparlante direttamente al MAX98357A?

Sì, perché il MAX98357A ha già uno stadio amplificatore integrato, quindi puoi collegare direttamente un altoparlante.

SPK+ ---- Speaker ---- SPK-

Gli altoparlanti tipici sono da 4Ω a 8Ω, 3W o più. L’amplificatore può fornire circa 3W, abbastanza per piccoli altoparlanti.

D: Come ottengo l’audio stereo?

Il MAX98357A è mono, quindi per lo stereo servono due moduli.

ESP32 --> 2x MAX98357A --> 2x Speakers

Entrambi i moduli condividono i segnali I2S, ma usano resistenze per selezionare i canali sinistro e destro.

SD -- 100kΩ -- 3.3V (left channel)
SD -- 210kΩ -- 3.3V (right channel)

In questo modo ogni amplificatore riproduce un canale.

D: Che alimentazione devo usare?

Il modulo funziona a 3.3V o 5V, ma l’alimentazione è importante per una buona qualità audio. A volume alto il modulo può assorbire molta corrente, quindi alimentarlo dal pin 3.3V dell’ESP32 spesso non basta e può causare distorsioni o reset.

D: Come posso migliorare la qualità audio con il filtraggio dell’alimentazione?

Un’alimentazione pulita è fondamentale, perché il rumore si riflette direttamente sull’uscita audio. Puoi aggiungere condensatori:

VIN -- 100nF -- GND
VIN -- 100µF -- GND

Il condensatore piccolo elimina i disturbi veloci, mentre quello grande stabilizza la tensione e previene cali durante i picchi audio.

Inoltre puoi usare un condensatore di filtro:

5V -- 10Ω --+-- AMP_VIN
|
220µF
|
GND

Questo riduce il rumore da USB o regolatori switching.

D: Devo usare un’alimentazione esterna?

Sì, soprattutto a volume alto, perché il MAX98357A può assorbire molta corrente durante la riproduzione e il regolatore dell’ESP32 potrebbe non reggere.

External 5V ----> MAX98357A
ESP32_GND ------> Shared GND

Questo migliora la stabilità e riduce la distorsione.

D: Come posso aumentare il volume?

Il volume dipende da tre fattori principali: tensione di alimentazione, guadagno dell’amplificatore e tipo di altoparlante. Per aumentare il volume:

  • Usa 5V invece di 3.3V
  • Usa un altoparlante a bassa impedenza (4Ω invece di 8Ω)

Un altoparlante da 4Ω assorbe più potenza e produce più volume, ma aumenta anche il carico sull’amplificatore.

D: Cos’è il pin GAIN e come influisce sul suono?

Il pin GAIN imposta il livello di guadagno dell’amplificatore.

GAIN -- GND (lower gain)
GAIN -- VCC (higher gain)
GAIN -- FLOAT (default)

Un guadagno più alto aumenta il volume ma può anche aumentare rumore e distorsione, quindi spesso è meglio partire da un guadagno basso e regolare via software.

D: Perché sento rumore o fruscio anche senza audio?

Il rumore può provenire da diverse fonti come ripple di alimentazione, massa non ottimale o interferenze dall’ESP32. Soluzioni comuni:

  • Aggiungi condensatori di disaccoppiamento
  • Usa un’alimentazione esterna pulita
  • Tieni i cavi corti

D: Quali pratiche di cablaggio migliorano la qualità audio?

Un buon cablaggio è molto importante, soprattutto per audio digitale e amplificatori switching. Tieni i cavi corti:

ESP32 --> MAX98357A (short lines)

e usa la massa a stella:

ESP32_GND ----+---- AMP_GND
|
POWER_GND

Evita di far passare i cavi degli altoparlanti vicino ai cavi di segnale, perché le correnti elevate possono introdurre rumore.

D: Quali formati audio e funzioni sono supportati?

Il MAX98357A supporta i formati audio digitali tipici usati con ESP32.

  • Audio a 16, 24 o 32 bit
  • Frequenze di campionamento da 8 kHz a 96 kHz