This project is inspired by several other internet radio projects, but all projects lacked direct output via Bluetooth speakers. The first idea came from a project published by Gerald Lechner in an article at the AZ Delivery blog. I've ported the original code from an Arduino IDE compatible structure to a PlatformIO version.
But this version suffers from a permanently interrupted tcp audio stream. So I looked for a solution to this problem and found these projects ESP32-MiniWebRadio and ESP32-audioI2S. Especially the last one contained the solution on how to optimize the tcp settings to get better streaming performance with the arduino framework - thank you Wolle for your support.
And then there was the Bluetooth challenge...
First Try: As I wanted to connect bluetooth speakers to my webradio I searched for similar projects that had done this before. I found ... nothing, but pschatzmann and his great projects/libs ESP32-A2DP and arduino-audio-tools. Finally I found his post "The ESP32 only supports either Bluetooth or WIFI, but not both at the same time. So if you use A2DP, you will not be able to use any functionality which depends on WIFI (e.g. FreeRTOS queues)" in his project wiki - dead end.
Second try: I stumbled across the KCX_BT_EMITTER in Ralph S Bacon's VLOG. I got it working, but this device couldn't pair with my Marshall Emberton II BT Speaker. It's a nice little device and it's fun to play with serial interface and these old AT+commands. Again, dead end.
Third try: I bought this little gadget ORIA Bluetooth Aux Adapter, 2 in 1 Bluetooth 5.0 to connect my BT speakers. The next picture shows how I integrated the ORIA in my case. It came with a rechargeable battery and I had to get rid of it (for details see post). The two holes at the side of the case are for the status LEDs and between the holes is the grey BT-connect push-button.
Fourth try: I didn't like all these solutions I've tried so far, because the audio data is converted mulitple times (D->A->D) - that is superfluous. So I continued my search. I've found & ordered the TSA5001 module that utilizes I2S as input. It works as a drop-in replacement of my PCM5102a. But I forgot, that different radio stations broadcasting with different sample rates and the TSA5001 specs are saying, it supports only one fixed sample rate:
- Sampling Rate: 48KHz
- Bit per Sample: 16 bit, 24bit, 32bit.
- aptX, aptX Low Latency, aptX HD, SBC and AAC
- Bluetooth protocol: A2DP
This works perfectly for radio stations with a sample rate of 48KHz. Streams with other sample rates (e.g. 44,1Khz or 24KHz) are played back with regular interruptions or at a wrong pitch.
To find a way to convert all radio streams to 48KHz I have to learn how to use Phil Schatzmanns Arduino Audio Tools in depth.
To remember my research results I wrote down many of the information, e.g.
- various ESP32 models
- hardware communication protocols
- information on variuos displays
- analouge and I2C amplifiers
- useful libraries
- Reliable operation
- Easy to use
- Good sound quality
- Connectivity for Bluetooth speakers
- Analog output-jack for active speakers
- Function as clock when radio is off
- Simple user interface in the style of old car radios
- Visualization of information about current song and station
- Store stations as JSON-file in mcu filesystem
- Web-based wifi-setup
- OTA update for firmware and radio station JSON
Components used for this project
- ESP32 DevKit V4 with WROOM32 U (and external antenna)
- LCD blue 4x20 Zeichen, HD44780, I2C
- PCM5102 DAC, I2S
- Rotary Encoder KY-040
- ORIA Bluetooth Aux Adapter, 2 in 1 Bluetooth 5.0
- I2S to bluetooth transmitter (in test phase)
Pin | Function | Application | Arduino | Comment |
---|---|---|---|---|
GPIO21 | SDA | Disp I2C | D2 | |
GPIO22 | SCL | Disp I2C | D1 | |
GPIO32 | DigIn | Rotary 1 CLK (A) | D6 | select Volume |
GPIO33 | DigIn | Rotary 1 DT (B) | D5 | |
GPIO35 | DigIn | Rotary 1 SW | D7 | add 10K Pullup Resistor |
GPIO17 | DigIn | Rotary 2 CLK (A) | select Station | |
GPIO14 | DigIn | Rotary 2 DT (B) | ||
GPIO16 | DigIn | Rotary 2 SW | add 10K Pullup Resistor | |
GPIO25 | LRC | PCM 5102 (I2S) | I2S Amplifier | |
GPIO26 | BCLK | PCM 5102 (I2S) | I2S Amplifier | |
GPIO27 | DIN | PCM 5102 (I2S) | I2S Amplifier |
My implementation works with different states. Events like pressing a button or a successful firmware upload triggers the transition to another state.
- show upload state on display e.g. progress bar
- fix display error when title contains "special chars"
- handle wifi connection loss while in standby
- use F-macro and safe some RAM
- use mini CSS lib for html
- Change button long-press behaviour: When button is pressed long enough, the action happens without releasing the pressed button. So you don't have to count to know when it's time to release the button
- personalized favlist
- debug menu
Function | GPIO |
---|---|
MOSI (Master Out slave in) | 23 |
MISO (Master in Slave out) | 19 |
SCK (Serial Clock) | 18 |
DC | 21 |
RST | 22 |
CS/SS (Chip Select) | 5 |
Use SPI Pin Test to ask MCU for actual pins.
Default I2C pins on ESP32:
Function | GPIO |
---|---|
SDA | 21 |
SCL | 22 |
Use I2C Scanner Code to test if device is detected and to get its address
There are two I2S periphals on the ESP32 and "arbitrary" GPIO pins can be choosen.
Some I2S basics from Wikipedia:
Label | Synonyms | Function |
---|---|---|
SCK | BCLK | Bit clock line: Officially "continuous serial clock (SCK)".[1] Typically written "bit clock (BCLK)" |
WS | LRCLK, FS | Officially "word select (WS)". Typically called "left-right clock (LRCLK)" or "frame sync (FS)". |
SD | SDIN, SDATA | Officially "serial data (SD)", but can be called SDATA, SDIN, SDOUT, DACDAT, ADCDAT, etc.[3] |
MC | Master clock: This is not part of the I2S standard,but is commonly included for synchronizing the internal operation of the analog/digital converters. |
- Espressif Docs
- ALL YOU NEED TO KNOW ABOUT I2S
- ESP32 Audio Tutorial with lots of examples (Andreas Spiess): Video
- DroneBot Workshop ESP32 Sound - Working with I2S Blog, Video
- Blog post explains I2S
- https://forum.arduino.cc/t/giving-two-outputs-in-one-i2s-port/988109
- Video: Great Scott explains I2S
-
ESP API Guide Partion Tables
-
Video: How do OTA Updates work, including an explanation of partion tables
-
More Memory for the ESP32 without Soldering (How-to adapt partition sizes)
- Pinout
- Supplier AZ Delivery
- ESP32 with ext. antenna esp32-devkitc-v4-wroom32u
PLATFORM: Espressif 32 (6.4.0) > Espressif ESP32 Dev Module HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
Chip is ESP32-D0WDQ6 (revision v1.0) Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None Crystal is 40MHz MAC: 84:cc:a8:5e:c3:ac
- Technische Daten
- I2C device found at address 0x27
- Scrolling Text Example
The display
- is extremely dependent on the viewing angle
- is extremely slow via I2C
- brightness is not changeable via I2C
- https://www.waveshare.com/w/upload/8/80/1.5inch_OLED_Module_User_Manual_EN.pdf
- https://eckstein-shop.de/Waveshare128x128General15inchOLEDdisplayModuleEN
- SPI Connection Display ESP32
- Display Lib SSD1327 lcdgfx
- Display Lib SSD1327 hexaguin
- NEW: https://robpo.github.io/Paperino/exampleGFXdemo/, https://learn.adafruit.com/096-mini-color-oled
Eigenschaft | Wert |
---|---|
Betriebsspannung | 3.3V bis 5V |
Bus | I2C |
Address | I2C device found at address 0x3C |
Input via I2S
Input via I2S
- KY-040
- Rotary encoder with RGB LED Push Button
- Debouncing Circuit Video by Ralph S Bacon
- https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/internetradio-mit-esp32-und-max-98357a
- https://www.elektormagazine.de/labs/esp32-internet-radio-1
- OLED Display on Board, 8-Bit Audio? see Video
https://www.instructables.com/Internet-Radio-Using-an-ESP32/
Ralph shows how he built and improved his webradio in several VLOG videos:
- #204 TFT Touch Screen ILI9341 SPI for ESP32 (Internet Radio Research)
- #205 ESP32 Internet Radio with VS1053 MP3 decoder and ILI9341 TFT
- #206 ESP32 Circular Buffer for Internet Radio - and ESP32 WiFi Woes
- #208 Using an ESP32 Task for my Web Radio - using the Arduino IDE
- #235 Bluetooth Audio🔊Transmitter (KCX_BT_EMITTER) - with AT commands