|
ESP32 dev kit board |
x 1 | |
|
ILI9341 TFT Display 2.8 inch |
x 1 | |
|
TEA5767 Radio module |
x 1 | |
|
Rotary encoder with push button |
x 1 | |
|
Small D-class audio amplifier board |
x 1 | |
|
and Speaker |
x 1 |
![]() |
arduino IDEArduino
|
|
![]() |
Soldering Iron Kit |
Linear Scale ТЕА5767 FM Radio on ili9341 TFT Display
This time I will present you how to make a simple FM Radio with a beautiful retro look linear scale. The idea for the project was taken from the Volos Projects channel, where is presented the code that was specially made for the LilyGO T-Embed device, which has a TFT screen with a resolution of 320 x 170 pixels.
I just adapted the code for the ILI9341 TFT Display which has a resolution of 320×240 pixels powered by an ESP32 dev kit module. The radio interface is the same, and in the remaining part of the screen I added a small clock that shows the time. Actually, as a beginner in programming, I did a little practice drawing figures and placing text on the Display. The way the scale moves is especially effective for me as a big fan of retro radios. For the FM radio part, the TEA5767 radio module is used, which is characterized by good features and a relatively low price.
I was currently using a board without an audio amplifier, although there is also a board with a built-in stereo amplifier. In that part I use a PAM8304 amplifier module and a custom made small sound box.
If you want to make a PCB for this project, or for any other electronic project, PCBway is a great choice for you. PCBway is one of the most experienced PCB manufacturing company in China in field of PCB prototype and fabrication. They have a large online community where you can find a Open Source projects, and you can also share your project there. From my personal experience I can tell you that on this community you can find many useful projects
Well, as you can see, the device is very simple to build and consists of several components:
- ESP32 dev kit board
- ILI9341 TFT Display 2.8 inch
- TEA5767 Radio module
- Rotary encoder with push button
- Small D-class audio amplifier board
- and Speaker
A few notes about compiling and uploading the code. In order for the code to run without errors, you should use the libraries provided with the code, as they have been modified (TFT_eSPI) specifically for this project.
Аnd now let's see how the device works in reality:
The most striking part of the display is the linear scale that moves with the rotation of the rotary encoder. Then in the middle of the display is the selected frequency, the signal strength icon, as well as the stereo reception and "mute" mark. On the upper left part are the frequencies with the names of favorite stations, which for now are just information, and could be memorized in a future version of the software. Also the battery capacity icon is currently not working. In the lower part under the radio there is a clock that synchronizes with the PC clock when uploading the code.
Finally, the device is installed in a suitable housing made of PVC plastic with a thickness of 5 and 3 mm, and covered with colored self-adhesive wallpaper.
#include <Wire.h> #include <TEA5767.h> #include <TFT_eSPI.h> #include <RotaryEncoder.h> #include <SPI.h> #define TFT_GREY 0x5AEB TFT_eSPI tft = TFT_eSPI(); TFT_eSprite spr = TFT_eSprite(&tft); #define PIN_IN1 16 #define PIN_IN2 17 RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03); #define color1 0xC638 #define color2 0xC638 int value=980; int minimal=880; int maximal=1080; int strength=0; String sta[6]={"Ant.5","92.0","Metro","94.8","Super","97.0"}; float freq=0.00; TEA5767 radio = TEA5767(); bool muted=0; int deb=0; uint32_t targetTime = 0; // for next 1 second timeout static uint8_t conv2d(const char* p); // Forward declaration needed for IDE 1.6.x uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6); // Get H, M, S from compile time byte omm = 99, oss = 99; byte xcolon = 0, xsecs = 0; unsigned int colour = 0; void setup() { tft.begin(); tft.writecommand(0x11); tft.setRotation(1); tft.fillScreen(TFT_BLACK); tft.setTextSize(1); tft.setTextColor(TFT_WHITE, TFT_BLACK); targetTime = millis() + 1000; pinMode(0, INPUT_PULLUP); Wire.begin(21,22); spr.createSprite(320,170); spr.setTextDatum(4); spr.setSwapBytes(true); spr.setFreeFont(&Orbitron_Light_24); spr.setTextColor(color1,TFT_BLACK); drawSprite(); } void readEncoder() { static int pos = 0; encoder.tick(); if(digitalRead(0)==0){ if(deb==0){ deb=1; muted=!muted; radio.setMuted(muted); drawSprite(); delay(200); } }else deb=0; int newPos = encoder.getPosition(); if (pos != newPos) { if(newPos>pos) value=value-1; if(newPos<pos) value=value+1; pos = newPos; drawSprite(); } } void drawSprite() { freq=value/10.00; if(muted==false) radio.setFrequency(freq); strength=radio.getSignalLevel(); spr.fillSprite(TFT_BLACK); spr.setTextColor(TFT_WHITE,TFT_BLACK); spr.drawFloat(freq,1,160,64,7); spr.setFreeFont(&Orbitron_Light_24); spr.drawString("FM Radio",160,12); spr.drawString("STATIONS",38,14,2); spr.drawRoundRect(1,1,76,110,4,0xAD55); spr.drawRoundRect(240,20,76,22,4,TFT_WHITE); spr.drawRect(290,6,20,9,TFT_WHITE); spr.fillRect(291,7,12,7,0x34CD); spr.fillRect(310,8,2,5,TFT_WHITE); spr.setTextFont(0); spr.setTextColor(0xBEDF,TFT_BLACK); for(int i=0;i<6;i++){ spr.drawString(sta[i],38,32+(i*12)); spr.fillCircle(16,31+(i*12),2,0xFBAE); } spr.setTextColor(TFT_WHITE,TFT_BLACK); spr.drawString("SIGNAL:",266,54); spr.drawString("MUTED",260,102,2); spr.fillRoundRect(288,96,20,20,3,0xCC40); if(muted==1) spr.fillCircle(297,105,6,TFT_WHITE); for(int i=0;i<strength;i++) spr.fillRect(244+(i*4),80-(i*1),2,4+(i*1),0x3526); spr.fillTriangle(156,104,160,114,164,104,TFT_RED); int temp=value-20; for(int i=0;i<40;i++) { if((temp%10)==0){ spr.drawLine(i*8,170,i*8,140,color1); spr.drawLine((i*8)+1,170,(i*8)+1,140,color1); spr.drawFloat(temp/10.0,1,i*8,130,2); } else if((temp%5)==0 && (temp%10)!=0) {spr.drawLine(i*8,170,i*8,150,color1); spr.drawLine((i*8)+1,170,(i*8)+1,150,color1); //spr.drawFloat(temp/10.0,1,i*8,144); } else {spr.drawLine(i*8,170,i*8,160,color1);} temp=temp+1; } spr.drawString("Stereo: "+String(radio.isStereo()),275,31,2); spr.drawLine(160,114,160,170,TFT_RED); spr.pushSprite(0,0); } void loop() { readEncoder(); if (targetTime < millis()) { // Set next update for 1 second later targetTime = millis() + 1000; tft.setFreeFont(&Orbitron_Light_24); tft.drawString("Time :", 17,186); tft.drawRoundRect(5,175,310,57,8,TFT_WHITE); //tft.drawRoundRect(240,20,76,22,4,TFT_WHITE) // Adjust the time values by adding 1 second ss++; // Advance second if (ss == 60) { // Check for roll-over ss = 0; // Reset seconds to zero omm = mm; // Save last minute time for display update mm++; // Advance minute if (mm > 59) { // Check for roll-over mm = 0; hh++; // Advance hour if (hh > 23) { // Check for 24hr roll-over (could roll-over on 13) hh = 0; // 0 for 24 hour clock, set to 1 for 12 hour clock } } } // Update digital time int xpos = 110; int ypos = 183; // Top left corner ot clock text, about half way down int ysecs = ypos; // + 24; if (omm != mm) { // Redraw hours and minutes time every minute omm = mm; // Draw hours and minutes if (hh < 10) xpos += tft.drawChar('0', xpos, ypos, 6); // Add hours leading zero for 24 hr clock xpos += tft.drawNumber(hh, xpos, ypos, 6); // Draw hours xcolon = xpos; // Save colon coord for later to flash on/off later xpos += tft.drawChar(':', xpos, ypos - 8, 6); if (mm < 10) xpos += tft.drawChar('0', xpos, ypos, 6); // Add minutes leading zero xpos += tft.drawNumber(mm, xpos, ypos, 6); // Draw minutes xsecs = xpos; // Sae seconds 'x' position for later display updates } if (oss != ss) { // Redraw seconds time every second oss = ss; xpos = xsecs; if (ss % 2) { // Flash the colons on/off tft.setTextColor(0x39C4, TFT_BLACK); // Set colour to grey to dim colon tft.drawChar(':', xcolon, ypos, 6); // Hour:minute colon xpos += tft.drawChar(':', xsecs, ysecs, 6); // Seconds colon tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set colour back to yellow } else { tft.drawChar(':', xcolon, ypos, 6); // Hour:minute colon xpos += tft.drawChar(':', xsecs, ysecs, 6); // Seconds colon } //Draw seconds if (ss < 10) xpos += tft.drawChar('0', xpos, ysecs, 6); // Add leading zero tft.drawNumber(ss, xpos, ysecs, 6); // Draw seconds } } } // Function to extract numbers from compile time string static uint8_t conv2d(const char* p) { uint8_t v = 0; if ('0' <= *p && *p <= '9') v = *p - '0'; return 10 * v + *++p - '0'; }

Linear Scale ТЕА5767 FM Radio on ili9341 TFT Display
- Comments(0)
- Likes(1)

-
Engineer Dec 07,2024
- 0 USER VOTES
- YOUR VOTE 0.00 0.00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
More by Mirko Pavleski
-
DIY simple HUNTER Led Game with Arduino Some time ago I presented you a simple to make, but interesting game, a 1D version simulation of "P...
-
XHDATA D-109WB Radio Short Review with complete disassembly Recently I received a shipment of a radio from the brand XHDATA model: D-109WB, so I immediately de...
-
Arduino Rotary encoder combination lock (Arduino door lock system with Rotary Encoder) Rotary dial safes typically use a mechanical combination lock. They are valued for their simplicity...
-
DIY DRSSTC Music Tesla coil with Interrupter using cheap Driver Module DRSSTC (Dual resonant solid state tesla coil) is a type of Tesla coil that uses solid-state compone...
-
Arduino HPDL1414 Retro Clock with Set and Alarm Functions The HPDL-1414 is a 16-segment LED display with four printable fields that is over twenty years old....
-
How to turn a 7 inch Elecrow pi terminal into a standalone SDR Radio Today I received the Pi Terminal-7” IPS HMI CM4 Panel All-In-One Module Raspberry Pi Computer from E...
-
Arduino 3D Printed self Balancing Cube Self-balancing devices are electronic devices that use sensors and motors to keep themselves balanc...
-
Simple GU50 VTTC Tesla Coil with MOT (25+cm Spark) Vacuum Tube Tesla Coils are a common choice for homebuilders for several practical reasons. At Soli...
-
Hourglass ESP8266 Code A hourglass, also known as an sand clock, is a device used to measure the passage of time. It consi...
-
Tug of War Arduino Game on WS2812 Led strip A Tug of War is a classic team-based game where two opposing teams compete to pull a rope in opposi...
-
DIY ESP32 Bioresonance Rife Machine with ZAPPER function Rife machine therapy is an alternative treatment developed by Dr. Royal Raymond Rife in the 1930s. H...
-
Arduino VFO Project with a Large LCD Display A Variable Frequency Oscillator (VFO) is an electronic oscillator whose output frequency can be adj...
-
Exploring the Tesla Coil Driver Board, Full Review & Test Results Some time ago I presented you a video in which I analyzed a super cheap Tesla Coil driver that cost...
-
Arduino Eatrthquake alarm and protection system with D7S seismic Sensor Earthquakes are extremely common events around the world. On average, there are fifty earthquakes a...
-
Review and Comparison of Three Inexpensive Metal Detector Kits A metal detector is a device used to detect the presence of metal objects in the ground or other ma...
-
How to make simple Arduino RGB Led strip VU Meter VU meter or volume unit meter is a device intended for visual presentation of the audio signal. It ...
-
DIY Simple Antistress and Relaxation PEMF Device based on Schumannn resonance frequency 7.83 Hz Schumann resonances are global electromagnetic resonances, generated by lightning discharges in the...
-
DIY Si4825 A10 multiband Radio (MW,SW,FM) Thanks to the production of specialized radio chips, nowadays it is possible to make a quality mult...
-
DIY simple HUNTER Led Game with Arduino Some time ago I presented you a simple to make, but interesting game, a 1D version simulation of "P...
-
XHDATA D-109WB Radio Short Review with complete disassembly Recently I received a shipment of a radio from the brand XHDATA model: D-109WB, so I immediately de...
-
Arduino Rotary encoder combination lock (Arduino door lock system with Rotary Encoder) Rotary dial safes typically use a mechanical combination lock. They are valued for their simplicity...
-
DIY DRSSTC Music Tesla coil with Interrupter using cheap Driver Module DRSSTC (Dual resonant solid state tesla coil) is a type of Tesla coil that uses solid-state compone...
-
Arduino HPDL1414 Retro Clock with Set and Alarm Functions The HPDL-1414 is a 16-segment LED display with four printable fields that is over twenty years old....
-
How to turn a 7 inch Elecrow pi terminal into a standalone SDR Radio Today I received the Pi Terminal-7” IPS HMI CM4 Panel All-In-One Module Raspberry Pi Computer from E...
-
Arduino 3D Printed self Balancing Cube Self-balancing devices are electronic devices that use sensors and motors to keep themselves balanc...
-
Simple GU50 VTTC Tesla Coil with MOT (25+cm Spark) Vacuum Tube Tesla Coils are a common choice for homebuilders for several practical reasons. At Soli...
-
Hourglass ESP8266 Code A hourglass, also known as an sand clock, is a device used to measure the passage of time. It consi...
-
Tug of War Arduino Game on WS2812 Led strip A Tug of War is a classic team-based game where two opposing teams compete to pull a rope in opposi...
-
DIY ESP32 Bioresonance Rife Machine with ZAPPER function Rife machine therapy is an alternative treatment developed by Dr. Royal Raymond Rife in the 1930s. H...
-
Arduino VFO Project with a Large LCD Display A Variable Frequency Oscillator (VFO) is an electronic oscillator whose output frequency can be adj...
-
-
Instrumentation Input, high impedance with 16 bit 1MSPS ADC for SPI
278 0 0 -
RGB LED Matrix input module for the Framework Laptop 16
469 0 2 -
-
📦 StackBox: Modular MDF Storage Solution 📦
290 0 2 -