Web Radio with ESP32, OLED display and MAX98357 I2S power amp

This wifi internet radio uses ESP32 module with OLED display 128x64.

It is possible to control volume and channel with push buttons.

It is possibile to set volume (0..21) or web url using serial interface

Features
  • Persistent storage of volume and station index
  • Visualization of selected station, volume and wifi signal strength (RSSI)
  • Auto-recovery in case of remote failure
  • Auto-configuration: Wifi connection is started by pushing WPS on Wifi Access Point




Hardware set-up

Following hardware is required to build the experiment:
  • ESP32 module with OLED display (e.g. Wemos Lolin board)
  • MAX98357 audio I2S power amp
  • 2 Watt 8 ohm audio speaker
Implement following connections:
  • Connect 5V(ESP32+OLED) together with VIN(MAX98357)
  • Connect GND(ESP32+OLED) together with GND(MAX98357)
  • Connect GPIO 16(ESP32+OLED) together with LRC(MAX98357)
  • Connect GPIO 14(ESP32+OLED) together with BCLK(MAX98357)
  • Connect GPIO 13(ESP32+OLED) together with DIN(MAX98357)
  • Connect audio speaker to MAX98357 output
  • Connect push button to GPIO(ESP32+OLED) defined as Pin_previous, Pin_next, Pin_vol_up, Pin_vol_down


The following picture shows the inside of the web radio:

Inside the ESP32 Web Radio

ESP32 software

Before writing software make sure to have installed the software development environment, downloadable from Arduino Software web site. It may be needed to download some library if not already present. Libraries are required also to manage the external devices.

The sketch has to include the required libraries:

#include "Audio.h"
#include "SSD1306Wire.h"
#include "EEPROM.h"
#include "esp_wps.h"


The loop() function implements the Web Radio functionality.

void loop() { audio.loop(); audiotime = audio.getAudioCurrentTime(); //Display refresh logic if (millis() - refresh_time > 1000) { refresh_time = millis(); display_music(); } //Button logic int reading_previous = digitalRead(Pin_previous); if (reading_previous != lastButtonState[pb_previous]) { // reset the debouncing timer lastDebounceTime[pb_previous] = millis(); } if ((millis() - lastDebounceTime[pb_previous]) > debounceDelay) { if (reading_previous != buttonState[pb_previous]) { buttonState[pb_previous] = reading_previous; if (buttonState[pb_previous] == LOW) { Serial.println("Pin_previous"); if (station_index > 0) { station_index--; } else { station_index = station_count - 1; } EEPROM.write(1, station_index);//save station index in EEPROM EEPROM.commit(); open_new_radio(stations[station_index]); } } } lastButtonState[pb_previous] = reading_previous; int reading_next = digitalRead(Pin_next); if (reading_next != lastButtonState[pb_next]) { // reset the debouncing timer lastDebounceTime[pb_next] = millis(); } if ((millis() - lastDebounceTime[pb_next]) > debounceDelay) { if (reading_next != buttonState[pb_next]) { buttonState[pb_next] = reading_next; if (buttonState[pb_next] == LOW) { Serial.println("Pin_next"); if (station_index < station_count - 1) { station_index++; } else { station_index = 0; } EEPROM.write(1, station_index);//save station index in EEPROM EEPROM.commit(); open_new_radio(stations[station_index]); } } } lastButtonState[pb_next] = reading_next; int reading_vol_up = digitalRead(Pin_vol_up); if (reading_vol_up != lastButtonState[pb_vol_up]) { // reset the debouncing timer lastDebounceTime[pb_vol_up] = millis(); } if ((millis() - lastDebounceTime[pb_vol_up]) > debounceDelay) { if (reading_vol_up != buttonState[pb_vol_up]) { buttonState[pb_vol_up] = reading_vol_up; if (buttonState[pb_vol_up] == LOW) { Serial.println("Pin_vol_up"); if (volume < 21) volume++; EEPROM.write(0, volume);//save volume in EEPROM EEPROM.commit(); audio.setVolume(volume); } } } lastButtonState[pb_vol_up] = reading_vol_up; int reading_vol_down = digitalRead(Pin_vol_down); if (reading_vol_down != lastButtonState[pb_vol_down]) { // reset the debouncing timer lastDebounceTime[pb_vol_down] = millis(); } if ((millis() - lastDebounceTime[pb_vol_down]) > debounceDelay) { if (reading_vol_down != buttonState[pb_vol_down]) { buttonState[pb_vol_down] = reading_vol_down; if (buttonState[pb_vol_down] == LOW) { Serial.println("Pin_vol_down"); if (volume > 0) volume--; EEPROM.write(0, volume);//save volume in EEPROM EEPROM.commit(); audio.setVolume(volume); } } } lastButtonState[pb_vol_down] = reading_vol_down; //Serial logic if (Serial.available()) { String r = Serial.readString(); r.trim(); if (r.length() > 5) { audio.stopSong(); open_new_radio(r); } else { audio.setVolume(r.toInt()); } } if (!audio.isRunning()) {//recovery logic, e.g. wifi connection was lost Serial.println("restart due to recovery logic"); ESP.restart(); } }


Download the complete sketch here and enjoy it.

Share Share on Facebook Share on Twitter Bookmark on Reddit Share via mail
Creative Commons Attribution-Share Alike | Terms and conditions | Privacy policy