top of page
White Structure

Side Project: Internet radio with LilyGo T-display/ESP32 and the MAX98357a

  • Jan 27
  • 7 min read

Updated: Mar 10


ree

I recently got the big box o' parts (Adventure kit 2) from https://craftingtable.com/ and one of the things it contained was the LilyGo T-display module which has a small display integrated with an ESP32 and all mounted on a development board with a couple of buttons. Since the ESP32 contains built-in WIFI, I wanted to use this for some online project. One idea that captivated me was to make an internet radio.


NOTE: Also see the updated version with volume control and internal speaker at the end of this post.


Background

What is an internet radio you may ask? Basically, an internet radio let's you connect to a URL that is streaming audio. It collects the metadata for display and decodes the digital stream into audio format that can be played through a speaker. Internet radios have been around commercially for some time but are a bit pricey. Considering you can play the same stations through your phone or computer, paying big bucks for a standalone internet radio seems frivolous. But making one for about $30? Totally worth it.


Software


Board Installation

The board to use with the T-display is the ESP32 Dev Module. In the board manager, search for ESP32 and use the entry for ESP32 by Espressif systems. Once installed, choose ESP32 Dev Module. Of course, if you have a different variant use the one for your board. Note that by default, the IDE offers different ways to divide up memory on your microcontroller. For this board and app library set, you will need to go to Tools menu and select Patrition Scheme and set it to Huge APP... This will allow enough space for the software otherwise you will get an error message trying to compile:

Error when Partition Scheme not set to Huge APP
Error when Partition Scheme not set to Huge APP

Libraries

The next step is to get the correct audio.h library that can handle decoding the audio signal and works with esp32. I used ESP32-audiol2S-master by schreibfaul1, version 3.0.13. The Github page is here: https://github.com/schreibfaul1/ESP32-audioI2S


The audio library handles connecting to a station URL and communicating the digital audio data using a protocol known as I2S, developed by Phillips. The library does not decode the data, however. For that we use the MAX98357a module.


The display is controlled by the library TFT_eSPI.h. The Github page is here: https://github.com/Bodmer/TFT_eSPI. For this library after installation, you need to configure it for the display. In the case of the T-display, configure as follows:

  1. Go to the folder where you save your sketches. In this folder will be the "libraries" folder. Inside this folder is the TFT_eSPI folder. Open that folder.

  2. Find the file User_Setup_Select.h. Open it in a text editor like Notepad or Notepad++.

  3. Go to line #include <User_Setup.h> which should be around line 27 in the file. Comment this out.

  4. Find setup 25, which should be about line 58. It should look like #include <User_Setups/Setup25_TTGO_T_Display.h> Make sure this line is UNcommented.

  5. Save the file.


The EEPROM library and other libraries should already be loaded by default.


Hardware

The MAX98357A is a compact, low-cost Class D amplifier with impressive features:

  • Single-Supply Operation: Works with a supply voltage of 2.5V to 5.5V.

  • Output Power: Delivers up to 3.2W into a 4Ω load at 5V.

  • Efficiency: Achieves 92% efficiency with an 8Ω load at 1W output.

  • Quiescent Current: Consumes only 2.4mA when idle.

  • Output Noise: Has a low output noise of 22.8µV RMS at 15dB gain.

  • THD+N: Maintains a low total harmonic distortion plus noise of 0.013% at 1kHz.

  • Sample Rates: Supports sample rates from 8kHz to 96kHz.

  • Digital Audio Interface: Compatible with I²S and 8-channel TDM data.

  • Output Modes: Can produce left, right, or a mixed output from stereo input data.

  • EMI Reduction: Features active emissions-limiting and edge-rate limiting circuitry to reduce electromagnetic interference.


While it is possible to use bit-banging techniques to handle I2S, this module, and the support of the ESP32 for I2S, makes using this protocol easy.


I'm all about easy, and so when I saw the two buttons on the T-display board (one is connected to ESP32 GPIO 0 and one is connected to GPIO 35). I decided to just use them for changing stations. I wanted the user to be able to go forwards or backwards through a list of channels so both buttons are used for choosing the station. To connect to the displayed station a separate button is used connected to GPIO 12.


For power, I put two options: an internal 9V battery or an external connection to a 9V 1A AC adapter. Then I use a 3-position, double-input switch. This switch connects either the battery positive or the adapter positive to a voltage regulator to make 5V for powering the ESP32 and the MAX98357. The middle position of the switch connects neither side to common, so it is effectively the OFF position.


Speakers

If you are connecting directly to a speaker, then you probably want to add volume control to the user interface. The audio library has a volume function (see setup routine), and the MAX98357 has several gain options. If you are using a direct speaker connection, you probably want to raise the gain by removing the resistor to Vcc which would raise the gain from 3 db to 9 db. More info on adjusting the gain, and possible speaker wattages are here https://learn.adafruit.com/adafruit-max98357-i2s-class-d-mono-amp/pinouts?form=MG0AV3


In my implementation output is to a powered speaker with integrated volume control so I did not include a volume in the project. Also, I only had one MAX98357 handy, so I used the MAX98357 setting which combined both channels into one and then put that mono audio signal to both sides of the powered speaker (which was stereo). I found that for a powered speaker I had the best sound quality with a low gain, low volume output. Gain is set to 3 db by putting the 100k resistor to Vcc, and I found a volume level of 4 was about right (this is set in the setup function, permissible values are 0 to 21). But feel free to adjust the volume to whatever sounds best with your speaker.


Here is a Fritzing diagram of the final project:


Internet Radio wiring.  Top power rail not used.  Resistor is 100k to Vcc giving a gain of 3.
Internet Radio wiring. Top power rail not used. Resistor is 100k to Vcc giving a gain of 3.

Here is a zip of the sketch and wiring diagram. There are lots of comments in the sketch, so it should be pretty easy to modify.



Before loading the sketch, put in your SSID and password (~lines 41-42), upload the sketch and it should run. You will probably want to substitute your own list of stations, though. Where do you find the URLs of stations? Good question, because most Internet Radio websites hide this info. Here is one web site that lets you search and then you can just copy the URLs. To test whether you like a station, just paste the URL into another tab on your web browser and it should start playing if it is a valid site.


Improvements

There are some stations that can't seem to keep up, even though their bitrate is supposed to be high. Be patient and find radio stations that minimize dropouts. There may also be certain times of day that are better for listening than others if you want to hear a low-bitrate station.


Rechargeable battery: Anybody care to update this with a rechargeable battery instead of the 9V?


Bluetooth: It should be possible to add Bluetooth, since Bluetooth is supported by the ESP32. With the right library you should be able to connect this to Bluetooth speakers. Anybody want to try adding Bluetooth?


A few pics

Here are a few pics of the finished project. I re-used a nice box I had lying around.


Front view
Front view

Rear view
Rear view

Inside view
Inside view

Parts list





Podcast

You can listen to a podcast reviewing this blog here: https://www.grandpasgizmos.com/post/podcast-internet-radio


Update March 10, 2025 -- now with volume and internal speaker

Due to popular request, I have updated the above project to include an internal speaker and a volume control.


To set the volume, I use a 3-position DIP switch because you can see what the volume setting last was without even turning on the radio. (OK and also because I am a total nerd and love setting the volume in binary!). In the code I use an array to map the switch position reading (0-7) to a volume setting (0-21). The volume is set when the station select button is pressed.


There is also a gain setting on the amplifier module as described above. This can be adjusted to give the best volume range for your particular speaker. The wiring options for the gain are also in the header for the updated code below.


If you are normally going to be using an unpowered speaker, then you probably want a higher gain setting. For a powered speaker I use the lowest gain setting (3 dB) and lowest volume setting (all switches off --> mapped to a volume of 4). But if you are using an unpowered speaker, then a higher gain and volume might be better. Right now I am listening to the unpowered speaker with a gain of 9 dB and a volume setting of 14 and that is fine for nearby listening like on your desk.


The other thing that was added for this version is a toggle switch to change between the internal speaker and an external speaker plugged into an audio jack (also added to the new version).


I mounted the entire thing in a wooden box with a decorative glass panel on the lid. When using the internal speaker, I noticed that you can control the tone by how much you lift the lid. Fully open gives the loudest response but it is a little heavy on the high end to listen to when you are right next to it. Lowering the lid so there is about 1/4 inch open at the front tones down the highs a bit and gives a more balanced sound.


By experimenting with the gain, volume, and baffling from the box lid, the sound is quite acceptable from the internal speaker. The external powered speaker still can still be used when appropriate, simply by toggling the speaker switch. You can also plug in headphones, but of course as built the sound is mono, not stereo.


With these new options, the radio us much more versatile. However, use some common sense and only change the speaker when the radio is off. And remember if you are changing to a powered speaker from the non-powered, turn the volume to minimum first.


Here is a nerdy picture:

Nerdy view of internals of internet radio 5.1
Nerdy view of internals of internet radio 5.1

And here is a more pretty picture:

User view, internet radio 5.1
User view, internet radio 5.1

back view:

rear view showing 3-position power toggle and external connectors
rear view showing 3-position power toggle and external connectors
Wiring diagram for Internet Radio 5.1
Wiring diagram for Internet Radio 5.1


Here is the ino file:



Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page