You are here

Projekt 32 - ESP32

Themen:

 


ESP32 Webradio

Die Entwicklung eines einfachen Internetradios ist mit Hilfe eines ESP32 Audiokit Boards sehr einfach. Das Board enthält bereits sämtliche Komponenten, die für das Verbinden ins Internet (ESP32 WiFi Modul) und das Ausgeben der Audio-Signale benötigt werden (DAC, Audiobuchsen bzw. Verstärker für direkte Lautsprecherausgabe). Somit ist nur noch die Software notwendig. Hier werden bereits sämtliche SW-Komponenten durch Libraries abgedeckt. Somit beschränkt sich die Programmierung nur auf die generelle Ablaufsteuerung (LED ansteuern, Taster auswerten, WiFi Verbindung starten, Audiostream abspielen ...). Die Liste unterhalb enthält eine Schritt-für-Schritt Anleitung für das Projekt. Weiter unterhalb befindet sich der Source Code.

  • Die ESP Softwareentwicklung startet man mit dem Download der Arduino IDE (bei mir war Version 2.1.0 aktuell) von https://www.arduino.cc/en/software.
  • Danach muss der Board Manager um die ESP32 Boards erweitert werden. Unter "File > Preferences > Additional boards manager URLs" muss folgende URL eingetragen werden https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json. Danach kann man die EPS32 im Boards Manager installieren: "Tools > Board > Boards Manager > esp32 by Espressif > Install".
  • Für die serielle Verbindung zum Board wird noch der Silab USB UART Chip Treiber (CP210x Universal Windows Driver) benötigt: https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads. Beim ESP32 Audiokit Board wird zuerst die USB Schnittstelle für die Versorgung und danach erst die USB Schnittstelle der seriellen Schnittstelle angeschlossen.
  • Innerhalb der Arduino IDE kann man das Board und die COM-Verbindung auswählen: "Tools > Board > esp > ESP32 Wrover Module, COM3".
  • Danach kann ein Projekt angelegt oder geöffnet werden (Projektordner und "Main"-Datei müssen gleich lauten, z.B. ./webradio/webradio.ino).
  • Damit die benötigten Libraries gefunden werden werden sie mittels Library Manager installiert: "Sketch > Include Library > Library Manager". Heruntergeladene ZIP Dateien können mittels separaten Menüpunkt installiert werden: "Sketch > Include Library > Add .ZIP Library". Für das Webradio Projekt wurden folgende Libraries benötigt: ESP32-audioI2S-master.zip und es8388-main.zip.
  • Nach dem Programmieren wird das Projekt einfach Compiliert "Sketch > Verify/Compile" und auf das Board gespielt "Sketch > Upload". Die Debug Ausgabe kann im "Serial Monitor" Fenster angesehen werden.

Board WiFi Module UART Chip Speaker Amplifier Chip Mounting Final Setup

/* USED LIBRARIES
  ESP32-audioI2S library - https://github.com/schreibfaul1/ESP32-audioI2S
  ES8388 library         - https://github.com/maditnerd/es8388
*/
 
/* IDE BOARD SETTINGS
  Arduino Board Settings:               ESP32 WROVER Module
  Port:                                 COMx
  Core Debug Level:                     None
  Erase All Flash Before Sketch Upload: Disabled
  Flash Frequency:                      80MHz
  Flash Mode:                           QIO
  Partition Scheme:                     Huge APP (3MB No OTA/1MB SPIFFS)
  Upload Speed:                         921600
  Programmer:                           Esptool
*/
 
/* BOARD SETTINGS
  Settings for ESP32-A1S v2.2 (ES8388)
  Switch 2, 3    ON
         1, 4, 5 OFF
*/
 
// INCLUDES
#include "Arduino.h"
#include "WiFi.h"
#include "Audio.h"
#include "ES8388.h"
 
 
// DEFINES
// Power amplifier pins
#define PA_EN                 21                      // low = enabled, high = disabled
 
// DAC pins
#define I2S_DSIN              26
#define I2S_BCLK              27
#define I2S_LRC               25
#define I2S_MCLK              0
#define I2S_DOUT              35
 
#define IIC_CLK               32
#define IIC_DATA              33
 
// Button pins
#define BTN_VOLUME_DOWN_PIN   19                      // key 3
#define BTN_VOLUME_UP_PIN     23                      // key 4
#define BTN_STATION_PREV_PIN  18                      // key 5
#define BTN_STATION_NEXT_PIN  5                       // key 6
#define BTN_DEBOUNCE_CNT      10
 
// LED pins
#define LED_WIFI_PIN          22                      // LED 4
#define LED_RADIO_PIN         22                      // LED 4
 
// Station list size
#define STATIONS              5
 
// Volume step count
#define VOLUME_STEPS          21
 
// WiFi connection tries
#define WIFI_CONNECTION_TRIES 10
 
 
// GLOBAL VARIABLES
static ES8388 dac;
Audio audio;
 
String ssid      = "asdf";
String password  = "1234";
String ssid2     = "qwert";
String password2 = "5678";
 
uint8_t btn_volume_down_cnt  = 0;
uint8_t btn_volume_up_cnt    = 0;
uint8_t btn_station_prev_cnt = 0;
uint8_t btn_station_next_cnt = 0;
 
uint8_t connectionCnt = 0;
uint8_t stationNumber = 0;
 
const char* stationUrls[STATIONS] = {
  "http://ors-sn05.ors-shoutcast.at/oe3-q1a",
  "http://ors-sn05.ors-shoutcast.at/oe1-q1a",
  "http://ors-sn05.ors-shoutcast.at/fm4-q1a",
  "http://ors-sn05.ors-shoutcast.at/noe-q1a",
  "http://ors-sn05.ors-shoutcast.at/wie-q1a"
};
 
String stationNames[STATIONS] = {
  "OE3",
  "OE1",
  "FM4",
  "Radio NOE",
  "Radio Wien"
};
 
 
void setup() {
  // Initialize debug terminal interface
  Serial.begin(115200);
 
 
  // Initialize pins
  digitalWrite(PA_EN, HIGH);                          // disable power amplifier
  pinMode(PA_EN, OUTPUT);
 
  digitalWrite(LED_WIFI_PIN, HIGH);                   // disable LEDs
  digitalWrite(LED_RADIO_PIN, HIGH);
  pinMode(LED_WIFI_PIN, OUTPUT);
  pinMode(LED_RADIO_PIN, OUTPUT);
 
  pinMode(BTN_VOLUME_DOWN_PIN, INPUT_PULLUP);         // button pins used as input pins
  pinMode(BTN_VOLUME_UP_PIN, INPUT_PULLUP);
  pinMode(BTN_STATION_PREV_PIN, INPUT_PULLUP);
  pinMode(BTN_STATION_NEXT_PIN, INPUT_PULLUP);
 
 
  // Initialize WIFI
  // Set station mode
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
 
  // Connect to first WIFI network
  WiFi.begin(ssid.c_str(), password.c_str());
  Serial.print("Connecting ");
  do {
    connectionCnt++;
    Serial.print(".");
    delay(500);
  }
  while ((WiFi.status() != WL_CONNECTED) &&
         (connectionCnt < WIFI_CONNECTION_TRIES));
 
  if (WiFi.status() == WL_CONNECTED) {
    Serial.printf("\n");
    Serial.printf("Connected WiFi: %s\n", ssid);
 
    digitalWrite(LED_WIFI_PIN, LOW);
  }
  // In case of connection failures, connect to second WIFI
  else {
    connectionCnt = 0;
    WiFi.disconnect();
    WiFi.begin(ssid2.c_str(), password2.c_str());
 
    do {
      connectionCnt++;
      Serial.print(".");
      delay(500);
    }
    while ((WiFi.status() != WL_CONNECTED) &&
           (connectionCnt < WIFI_CONNECTION_TRIES));
 
    if (WiFi.status() == WL_CONNECTED) {
      Serial.printf("\n");
      Serial.printf("Connected WiFi: %s\n", ssid2);
      digitalWrite(LED_WIFI_PIN, LOW);
    }
    else {
      ESP.restart();
    }
  }
 
  Serial.print("IP-Address: ");
  Serial.println(WiFi.localIP());
 
  delay(2000);
  digitalWrite(LED_RADIO_PIN, HIGH);
  while (!dac.begin(IIC_DATA, IIC_CLK)) {
    Serial.println("DAC connection failure!");
    delay(1000);
  }
  audio.i2s_mclk_pin_select(I2S_MCLK);
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DSIN);
  audio.setVolumeSteps(VOLUME_STEPS);
  audio.setVolume((VOLUME_STEPS>>1) + (VOLUME_STEPS>>2));
  Serial.printf("Volume [0-%d]: %d\n", VOLUME_STEPS-1, audio.getVolume());
  //audio.setTone(low, middle, high);
  audio.connecttohost(stationUrls[stationNumber]);
  Serial.printf("Active station: %s\n", stationNames[stationNumber]);
  digitalWrite(LED_RADIO_PIN, LOW);
}
 
void loop()
{
  // Run audio player
  audio.loop();
 
  // UI handling
  if (LOW == digitalRead(BTN_VOLUME_DOWN_PIN)) {
    btn_volume_down_cnt++;
 
    if (btn_volume_down_cnt >= BTN_DEBOUNCE_CNT) {
      btn_volume_down_cnt = 0;
 
      uint8_t vol = audio.getVolume();
      if (vol > 0) {
        vol--;
      }
      audio.setVolume(vol);
      Serial.printf("Volume [0-%d]: %d\n", VOLUME_STEPS-1, vol);
    }
  }
  else {
    btn_volume_down_cnt = 0;
  }
 
 
  if (LOW == digitalRead(BTN_VOLUME_UP_PIN)) {
    btn_volume_up_cnt++;
 
    if (btn_volume_up_cnt >= BTN_DEBOUNCE_CNT) {
      btn_volume_up_cnt = 0;
 
      uint8_t vol = audio.getVolume();
      if (vol < (VOLUME_STEPS-1)) {
        vol++;
      }
      audio.setVolume(vol);
      Serial.printf("Volume [0-%d]: %d\n", VOLUME_STEPS-1, vol);
    }
  }
  else {
    btn_volume_up_cnt = 0;
  }
 
 
  if (LOW == digitalRead(BTN_STATION_PREV_PIN)) {
    btn_station_prev_cnt++;
 
    if (btn_station_prev_cnt >= BTN_DEBOUNCE_CNT) {
      btn_station_prev_cnt = 0;
      delay(500);
 
      if (stationNumber > 0) {
        stationNumber--;
      }
      else {
        stationNumber = STATIONS-1;
      }
      audio.connecttohost(stationUrls[stationNumber]);
      Serial.printf("Active station: %s\n", stationNames[stationNumber]);
    }
  }
  else {
    btn_station_prev_cnt = 0;
  }
 
 
  if (LOW == digitalRead(BTN_STATION_NEXT_PIN)) {
    btn_station_next_cnt++;
 
    if (btn_station_next_cnt >= BTN_DEBOUNCE_CNT) {
      btn_station_next_cnt = 0;
      delay(500);
 
      if (stationNumber < (STATIONS-1)) {
        stationNumber++;
      }
      else {
        stationNumber = 0;
      }
      audio.connecttohost(stationUrls[stationNumber]);
      Serial.printf("Active station: %s\n", stationNames[stationNumber]);
    }
  }
  else {
    btn_station_next_cnt = 0;
  }
}