// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ESP32 38pin, connected to ePaper display, Internet Radio trials for WOKWI, was working on Lilygo ESP32 T5 ePaper
//
// Hardware: ESP32 38pin, ePaper I2C 2.9",
// External libraries: GxEPD.h unfortunately not GxEPD2.h
// Processor selection in Arduino IDE: ESP32 Dev Module
//
// What it does:
// - Internet Radio EMMGEE_DAC, to internal DAC pins 25/26 OR I2S output on pins 25/26 to external I2S amplifier
// Hardware: ESP32 T5 E-Paper 2.13" 122x250, screen library GxEPD2_BW.h
// library Audio.h from Schreibfaul1, basis is file: internalDAC.ino, song info on serial monitor
// Processor selection in Arduino IDE: ESP32-WROOM-DA Module
// -
// to be added: -
// - E-Paper Screen with song infos,
// - potentiometer for loudness (pin39)
// - ev. digital encoder plus switch instead of potentiometer
// - I2S digital audio amplifier MAX98357A
// -
// 24.01.24 last (start jan. 2024)
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// **************************************************************************************************
// D E F I N I T I O N S *
// **************************************************************************************************
//
#include "Arduino.h" // Std. library
#include "WiFi.h" // Std. library
//#include "Audio.h" // MISSING IN WOKWI: external library to be installed from schreibfaul1
// ===== Test with old GxEPD.h library as GxEPD2 doesn't seem to work in WOKWI=============================
#include <GxEPD.h>
#include <GxGDEM029T94/GxGDEM029T94.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#include <SPI.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#define CS 5 // 15 CS 5 pin# std.S3 10 (ESP32 5)
#define DC 22 // 21 DC 22 pin# std.S3 14 (ESP32 2)
#define RSET 21 // 22 RST 21 pin# std.S3 13 (ESP32 0)
#define BUSY 4 // 23 BUSY 4 pin# std.S3 9 or 46 (ESP32 4)
#define MOSI 23 // 5 MOSI Data 23 HW pin# std.S3 11 (ESP32 23)
#define SCLK 18 // 4 CLK Clock 18 HW pin# std.S3 12 (ESP32 18)
#define MISO -1 // -1 MISO - pin# std.S3 - (ESP32 -)
GxIO_Class io(SPI, CS, DC, RSET); // GxIO_Class io(SPI, EPD_CS, EPD_DC, EPD_RSET);
GxEPD_Class display(io, RSET, BUSY); // GxEPD_Class display(io, EPD_RSET, EPD_BUSY);
// ====================================================================================================
//#include <GxEPD2_BW.h> // including library for E-Paper, Jean Marc Zingg
// Lilygo TTGO T5 V2.3.1 with E-Paper 2.13" 122x250 (GDEM0213B74) with SSD1680 driver, internal pins: : DIN=D23, CLK=D18, CS=D5, DC=D17, RST=D16, BUSY=D4
//GxEPD2_BW<GxEPD2_213_B74, GxEPD2_213_B74::HEIGHT> display(GxEPD2_213_B74(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
//
const int volControl = 34; // Define volume control pot connection, ADC3 is GPIO 39 for potentiometer
int volume = 10; // Integer for volume level, initial setting, from 0 to 20
//
/* === ONLY if I2S to external I2S amplifier used: Define Pins for I2S connections, 3 wires, SD (22) SCK (26) WS (25) ===
#define I2S_DOUT 22 // 25 Serial Data (SD) line (fritzing: #33)
#define I2S_BCLK 26 // 27 Serial Clock (SCK) also called bit clock (BCLK). Sample rate: 44.1 kHz, 16 bits per channel, 2 channels, so frequency: 44.1 kHz * 16 * 2 = 1.411 MHz.
#define I2S_LRC 25 // 26 Word Select (WS) or Frame Select (FS) or (LRCLK) to differentiate left/right channel. If WS=0 → Channel 1 (left). If WS=1 → Channel 2 (right)
Audio audio; // Create audio object -> for I2S output to external I2S amplifier as MAX98357M
*/
// === ONLY if I2S output to internal DAC is used/wanted on pins 25/25 on ESP32 T5 E-Paper ===
//Audio audio(true, I2S_DAC_CHANNEL_BOTH_EN); // Create audio object -> for I2S to internal DAC output (25/26 on ESP32 T5 E-Paper)
//String ssid = "Mi 9 SE"; // WiFi credentials
//String password = "Schnaegg99";
const char TextBsp[] = "Irgendein Text"; // Testen des Beispiels mit alter GxEPD library
char * arrayURL[8] = // Selection of radio station URL's in an array
{
"http://jenny.torontocast.com:8134/stream",
"http://188.165.212.154:8478/stream",
"https://igor.torontocast.com:1025/;.mp3",
"http://streamer.radio.co/s06b196587/listen",
"http://media-ice.musicradio.com:80/ClassicFMMP3",
"http://naxos.cdnstream.com:80/1255_128",
"http://149.56.195.94:8015/steam",
"http://ice2.somafm.com/christmas-128-mp3"
};
String arrayStation[8] = // Assign a simple name to radio stations
{
"Mega Shuffle",
"WayUp Radio",
"Asia Dream",
"KPop Radio",
"Classic FM",
"Lite Favorites",
"MAXXED Out",
"SomaFM Xmas"
};
const int LED = 15; // GPIO LED 10
const int BTNA = 35; // A: Play if not running, Pause if running 0
const int BTNB = 32; // B: Station change if not running, Volume change if running 35
const int BTNC = 33; // C: Backlight intensity steps 12
const int BTND = 27; // D: Display inversion of colors 17
//AudioGeneratorTalkie *talkie;
//AudioGeneratorMP3 *mp3;
//AudioFileSourceICYStream *file;
//AudioFileSourceBuffer *buff;
//AudioOutputI2S *out;
const int numCh = sizeof(arrayURL)/sizeof(char *); // why size of array of the URLs? numCh
bool TestMode = false; // only for debugging?
uint32_t LastTime = 0; // variable LastTime, what for?
int playflag = 0; // flag: is music ON or OFF
int ledflag = 0; // flag: is LED ON or OFF
//int btnaflag = 0;
//int btnbflag = 0;
float fgain = 4.0; // variable fgain? volume starting value?
int sflag = 0; // flag: s? for URL starting value?
char *URL = arrayURL[sflag]; // arrayURL[0] would mean: 1st url in array, so "http://jenny.torontocast.com:8134/stream"
String station = arrayStation[sflag]; // arrayURL[0] would mean: 1st name in array, so "Mega Shuffle"
//int backlight[5] = {10,30,60,120,220}; // option to change backlight intensity if TFT display used
//byte b=2;
//int press1=0;
//int press2=0;
//bool inv=0;
// **************************************************************************************************
// S E T U P *
// **************************************************************************************************
void setup()
{
Serial.begin(115200); // Start Serial Monitor
pinMode(LED, OUTPUT);
digitalWrite(LED , HIGH);
pinMode(BTNA, INPUT); // BTNA: start playing if music OFF (playflag == 0), stop if music on (playflag == 1)
pinMode(BTNB, INPUT);
pinMode(BTNC, INPUT_PULLUP);
pinMode(BTND, INPUT_PULLUP);
SPI.begin(SCLK, MISO, MOSI); // GxEPD library alt, Definition
display.init(); // alte und neue library, Initialisierung
//display.init(115200); // default 10ms reset pulse, e.g. for bare panels with DESPI-C02
//display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
WiFi.disconnect(); // Setup WiFi
WiFi.mode(WIFI_STA); // start WiFi in station mode
// ===== WiFi Setup ====== Hotspot Marcel: const char* ssid = "Mi 9 SE"; const char* password = "Schnaegg99";
// Standard WiFi connection code from Wokwi. Note: Specify WiFi channel number (6) when calling WiFi.begin().
// This skips the WiFi scanning phase and saves about 4 seconds when connecting to the WiFi.
Serial.print("Connecting to WiFi... ");
WiFi.begin("Wokwi-GUEST", "", 6); // WiFi.begin("Wokwi-GUEST", ""); Opt. (6) means: skip WiFi scanning phase, save ~4 seconds when connecting
//WiFi.begin("Mi 9 SE", "Schnaegg99", 6); // WiFi.begin for Hotspot Handy Gm
while (WiFi.status() != WL_CONNECTED) // print dots every 100ms when WiFi unconnected
{ delay(100); Serial.print("."); }
Serial.print(" Connected to IP address: ... "); // when WiFi connected, print IP to serial monitor
Serial.println(WiFi.localIP());
/* original for TFT:
tft.drawString("Ready ",78,44,2 );
tft.drawString(String(fgain),78,66,2 );
tft.drawString(String(arrayStation[sflag]),12,108,2);
tft.setTextFont(1);
tft.setCursor(8, 211, 1);
tft.println(WiFi.localIP());
Serial.printf("STATUS(System) Ready \n\n");
out = new AudioOutputI2S(0, 1); // Output to builtInDAC
out->SetOutputModeMono(true);
out->SetGain(fgain*0.05);
*/
//
display.setRotation(1); // Try to write something to ePaper display while in setup()
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 10);
display.println("check in setup()...");
display.setFont(&FreeMonoBold12pt7b);
display.printf("InternetRadio");
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 40);
display.println(arrayStation[sflag]);
display.update();
delay(10000);
//
/*
// ======= E-Paper Display 122x250 GxEPD2_BW.h
display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse (instead of display.init())
display.setTextColor(GxEPD_BLACK);
display.firstPage();
display.setRotation(1); // normalerweise hochkant, mit (1) 90° gedreht, üblichere Darstellung quer
delay(100); // was: delay(1000); why?
do{
display.fillScreen(GxEPD_WHITE);
display.setCursor(0, 0);
display.setTextSize(2);
display.println("Radio - EMMGEE_DAC");
display.setTextSize(1);
display.println("With display of Song-Infos");
display.setCursor(0, 35);
display.setTextSize(2);
display.print("STATION");
display.setCursor(0, 60);
display.setTextSize(2);
display.println("TITLE");
} while (display.nextPage());
*/
//audio.setVolume(7); // 0...21
//audio.connecttohost("http://stream.srg-ssr.ch/m/drs3/mp3_128"); // 128k mp3
//audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3
//audio.connecttohost("http://jenny.torontocast.com:8134/stream"); // Mega Shuffle
}
// **************************************************************************************************
// F U N C T I O N S *
// **************************************************************************************************
/*
void show_on_display() // function definition, show volume and stream title on display in a partial window
{
display.setPartialWindow(5,90,240,30); // Startkoordinaten x(z.B.115), y(z.B.50), Fensterbreite ab x(z.B.120), Fensterhöhe ab y(z.B.50)
display.firstPage();
do{
display.fillScreen(GxEPD_BLACK); // schwarzer Hintergrund, war: display.fillScreen(GxEPD_WHITE);
display.setCursor(15, 100);
display.setTextColor(GxEPD_WHITE); // Zeile eingefügt zum Testen Schrift weiss auf schwarzem Grund
display.setTextSize(1);
display.print("Volume: ");
if(volume < 10) // falls 1-9, eine "0" vorne dran schreiben so dass z.B. volume "08" angezeigt wird
display.print("0");
display.print(volume);
display.print(" (0-20)");
} while(display.nextPage());
}
*/
// **************************************************************************************************
// L O O P *
// **************************************************************************************************
void loop()
{
//audio.loop(); // Play radio channel constantly
volume = map ((analogRead(volControl)), 0,4095, 0,20); // Get the volume level from potentiometer input pin 39, map it from 0 to 20 as 'volume'
//audio.setVolume(volume); // Set the volume to 'volume'
//show_on_display();
//
display.setRotation(1); // Try to write something to ePaper display while in loop()
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 10);
display.println("In the loop()...");
display.setCursor(10, 40);
display.print("Volume level: ");
display.printf("vol %d",volume);
display.setCursor(10, 60);
display.setFont(&FreeMonoBold12pt7b);
display.printf("Station #%d", sflag);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(0, 100);
display.println(arrayStation[sflag]);
display.update();
if (digitalread(BTND) == LOW)
{sflag++}
delay(10000);
//
}
// **************************************************************************************************
// E V E N T S *
// **************************************************************************************************
/*
void audio_info(const char *info) // all audio infos on Serial Monitor
{ Serial.print("info "); Serial.println(info); }
*/
/*
void audio_showstation(const char *info) // name of radio station on display
{ do
{ display.setCursor(90, 40);
display.setTextSize(1);
display.print(String(info));
} while (display.nextPage());
}
*/
/*
void audio_showstreamtitle(const char *info) // showstreamtitle, band name and song name on display
{ do
{ display.setCursor(0, 85);
display.setTextSize(1);
display.println(String(info));
} while (display.nextPage());
}
*/
/*
void audio_info(const char *info) // all audio infos on Display
{ do
{ display.setCursor(0, 75);
display.setTextSize(1);
display.print(String(info));
} while (display.nextPage());
}
*/
//
/*
// === ORIGINAL from Schreibfaul, working on ESP32 T5 E-Paper, Output via integrated DAC-Pin 25 (left channel) and DAC Pin 26 (right channel) =====
//**********************************************************************************************************
//* audioI2S-- I2S audiodecoder for ESP32, internal DAC example *
//**********************************************************************************************************
//
// Sep.09/2022
//
// THE SOFTWARE IS PROVIDED "AS IS" FOR PRIVATE USE ONLY, IT IS NOT FOR COMMERCIAL USE IN WHOLE OR PART OR CONCEPT.
// FOR PERSONAL USE IT IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR
// OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
//
#include "Arduino.h"
#include "WiFiMulti.h"
#include "Audio.h"
Audio audio(true, I2S_DAC_CHANNEL_BOTH_EN);
WiFiMulti wifiMulti;
String ssid = "Mi 9 SE";
String password = "Schnaegg99";
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
wifiMulti.addAP(ssid.c_str(), password.c_str());
wifiMulti.run();
if(WiFi.status() != WL_CONNECTED){
WiFi.disconnect(true);
wifiMulti.run();
}
audio.setVolume(12); // 0...21
audio.connecttohost("http://stream.srg-ssr.ch/m/drs3/mp3_128"); // 128k mp3
//audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3
//audio.connecttohost("http://jenny.torontocast.com:8134/stream"); // Mega Shuffle
}
void loop()
{
audio.loop();
}
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}
// ====================================================================================================
*/Loading
epaper-2in9
epaper-2in9