Introduction: Full Digital FM Receiver With Arduino and TEA5767

By Hesam Moshiri, hesam.moshiri@gmail.com

FM transmitters/receivers are among the top favorite circuits of any electronic enthusiast. In this article/video, I have introduced a complete digital FM receiver design that has equipped with an LCD screen and three push-buttons. It can search for the FM signals from 76MHz to 108MHz manually and automatically (Scan mode). The signal strength is also displayed as a bar graph on the LCD screen. The output sound is amplified by a 3W+3W Class-D stereo amplifier that handles high-quality and strong enough audio power. As a controller, I have used the cheap and popular Arduino-Nano board. So let’s get started!

Supplies

Step 1: A Video of the Test & Operation

A. Circuit Analysis
Figure 1 shows the schematic diagram of the device. As it is clear, the circuit consists of 3 main parts: Arduino-Nano (Controller), FM receiver module, and the audio amplifier.

Step 2: Figure 1 Schematic Diagram of the Digital FM Receiver

A-1. FM Receiver Module
The FM receiver module is based on the TEA5767 [1, 2] chip. It is a well-known module that could be controlled via the I2C bus. It covers the FM frequency range from 76MHz to 108MHz. At the output, it handles L and R stereo audio signals that should be amplified, otherwise, the sound level is weak and can not be heard even by an earphone. The frequency selection and signal-strength measurement tasks are performed by the Arduino-Nano code.

R3, C7, C8, and C9 build a first-order low pass RC filter that reduces the supply noise. R1 and R2 are mandatory pull-up resistors for the I2C bus and CON1 is a UFL connector that provides an antenna connection. Figure 2 shows the TEA5767 module.

Step 3: Figure 2 the TEA5767 FM Receiver Module

A.2 Audio Amplifier
The audio amplifier part consists of the PAM8403 [3, 4] chip. This chip is a 3W+3W HiFi Class-D amplifier that can operate with only a single 5V supply. The maximum output power can be achieved using 4-ohm speakers. According to the datasheet: “The PAM8403 is a 3W, class-D audio amplifier. It offers low THD+N, allowing it to achieve high-quality sound reproduction. The new filterless architecture allows the device to drive the speaker directly, requiring no low-pass output filters, thus saving the system costs and PCB area”.

C13, C14, and C15 are used to reduce the supply noise as much as possible. R4, R5, C11, and C12 are used to transfer the output audio to the amplifier. Also, they create high-pass RC filters to remove any low-frequency noises. Figure 3 shows the reference circuit of the PAM8403 chip. P2 and P3 are right-angle 2-pin XH connectors that are used to connect the speakers to the board.

Step 4: Figure 3 Datasheet Reference Circuit of the PAM8403

A.3 Controller
The controller of the circuit consists of an Arduino-Nano board (AR1). Figure 4 shows the Arduino-Nano board. The board drives an 8*2 LCD (LCD1) and also reads the status of the SW1, SW2, and SW3 push buttons. It also sends/receives the TEA5767 data through the I2C bus. R6 sets the contrast level of the LCD and C4, C5, and C6 are used to reduce the mechanical push-button noises (debouncing).

Step 5: Figure 4 the Arduino-Nano Board

A.4 Power Supply
The TS2937 [5, 6] is the main component of the power supply that provides a stable +5V supply for the circuit. C1, C2, and C3 are used to reduce the noise, and POT1 is a 50K 2-way (dual) potentiometer with a switch. The POT1 both turns ON/OFF the device and increases or decreases the sound level. Picture 5 shows a picture of the POT1.

Step 6: Figure 5 2-Way (Dual) Potentiometer With Switch

B. PCB Layout
Figure 6 shows the PCB layout of the digital FM receiver. It is a 2 layers PCB board, last revision. The Arduino-Nano board is mounted on the bottom side and LCD on the top side of the board, preferably on female pin headers. This is more clear in 3D views and real photos. Figure 7 shows the 3D views of the board. Figure 8 shows the high-quality fabricated PCB boards of the digital FM receiver circuit.

Step 7: Figure 6 the PCB Layout of the Digital FM Receiver

Step 8: Figure 7 the Top and Bottom 3D Views of the PCB Board

Step 9: Figure 8 High Quality Fabricated PCB Boards

I used the SamacSys component libraries (for IC1 and IC2) in this PCB project as usual. It saves a lot of time and prevents design mistakes which leads to a lower product cost. All SamacSys component libraries (Schematic symbols, PCB footprints, and 3D models) are FREE and they follow strict industrial IPC footprint standards. You can download and install the libraries from the componentsearchengine.com or you can install them directly using the provided CAD plugins. I used the Altium plugin, however, almost all electronic designing CAD software are supported, such as Eagle, KiCad, OrCAD, Proteus .. etc [7]. Figure 9 shows the supported CAD software and figure 10 shows selected component libraries from the Altium plugin.

Step 10: Figure 9 Supported CAD Software by the SamacSys Plugin

Step 11: Figure 10 Selected PAM8403 and TS2937 Libraries From the Altium Plugin

C. Assembly and Test
The smallest component package is 0805. You should not have any problem with soldering the board, however, you can order the professionally assembled board as well. Figure 11 shows the assembled PCB board from the top and figure 12 shows the assembled PCB board from the bottom. The board has been hand-soldered by me. You would also need four 5mm FF spacers to fix the LCD on the PCB board.

Step 12: Figure 11 Assembled PCB Board (top View)

Step 13: Figure 12 Assembled PCB Board (bottom View)

You should use a UFL to SMA-F connector to connect your antenna to the board. Figure 13 shows this type of connector.

Step 14: Figure 13 UFL to SMA-F Connector

C.1 Arduino Code
The Arduino code is available in the below code block. Just connect your Arduino-Nano to the computer and compile/upload the code.

C.2 Testing
The lower limit of the frequency is 76.0MHz and the upper limit is 108.0MHz. You can increase or decrease the frequency by 0.1MHz by pressing the Up and Down buttons. Similarly, if you long-press these buttons, the frequency will be increased/decreased continuously. So it is pretty easy to fix the receiver on your desired frequency (FM station). Moreover, the Scan button can automatically search for powerful-enough FM stations and fix the receiver on the frequencies. To search for the next station, you should press the Scan button again. The strength of the FM signal is displayed on the LCD screen as a bar graph. In figure 14, the receiver has been set on a powerful FM station, at 100.0MHz frequency.

Step 15: Code

#include <TEA5767.h>
#include <Wire.h>
#include <JC_Button.h>
#include <LiquidCrystal.h>

float frequency = 76.0;
unsigned char buf[5];
unsigned int counter = 0, btn_counter = 0;
unsigned char level = 0;

TEA5767 radio;
const byte RS = 7, EN = 6, D4 = 4, D5 = 5, D6 = 2, D7 = 3;
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);


byte L1[] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111
};

byte L2[] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111
};

byte L3[] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111,
  B11111
};

byte L4[] = {
  B00000,
  B00000,
  B00000,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};

byte L5[] = {
  B00000,
  B00000,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111
};

void setup() {
  Wire.begin();

  lcd.begin(8, 2);
  lcd.createChar(0, L1);
  lcd.createChar(1, L2);
  lcd.createChar(2, L3);
  lcd.createChar(3, L4);
  lcd.createChar(4, L5);
  lcd.clear();

  radio.init();
  radio.set_frequency(frequency);
  DispSigStrenght();
  Freq_Mono_Stereo(frequency);

  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);

}

void loop() {

  if (digitalRead(11) == 0 && frequency < 108.0)
  {
    btn_counter++;
    if (btn_counter == 5000) {
      frequency += 0.1;
      radio.set_frequency(frequency);
      Freq_Mono_Stereo(frequency);
      btn_counter = 0;
    }
  }

  if (digitalRead(12) == 0 && frequency > 76.0)
  {
    btn_counter++;
    if (btn_counter == 5000) {
      frequency -= 0.1;
      radio.set_frequency(frequency);
      Freq_Mono_Stereo(frequency);
      btn_counter = 0;
    }
  }

  if (digitalRead(10) == 0)
  {
    btn_counter++;
    if (btn_counter == 5000) {
      if (frequency >= 108.0)
      {
        frequency = 76.0;
        radio.set_frequency(frequency);
      }
      radio.read_status(buf);
      radio.search_up(buf);
      radio.process_search (buf, TEA5767_SEARCH_DIR_UP);
      frequency =  floor (radio.frequency_available (buf) / 100000 + .5) / 10;
      Freq_Mono_Stereo(frequency);
      btn_counter = 0;
    }

  }

  counter ++;

  if (counter == 15000)
  {
    counter = 0;
    DispSigStrenght();
  }

}


void DispSigStrenght()
{

  lcd.setCursor(0, 1);
  radio.read_status(buf);
  level = radio.signal_level(buf);
  switch (level)
  {

    case 1 ... 3:
      lcd.print("\x08");
      lcd.setCursor(1, 1);
      lcd.print("    ");
      break;

    case 4 ... 6:
      lcd.print("\x08\x01");
      lcd.setCursor(2, 1);
      lcd.print("   ");
      break;

    case 7 ... 9:
      lcd.print("\x08\x01\x02");
      lcd.setCursor(3, 1);
      lcd.print("  ");
      break;

    case 10 ... 12:
      lcd.print("\x08\x01\x02\x03");
      lcd.setCursor(4, 1);
      lcd.print(" ");
      break;

    case 13 ... 15:
      lcd.print("\x08\x01\x02\x03\x04");
      break;
  }
}


void Freq_Mono_Stereo(float freq)
{

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(String(frequency, 1) + "MHz");

  radio.read_status(buf);
  if (radio.stereo(buf))
  {
    lcd.setCursor(6, 1);
    lcd.print("ST");
  }
  else
  {
    lcd.setCursor(6, 1);
    lcd.print("MN");
  }
}

Step 16: Figure 14 the Receiver Has Been Set on a Powerful FM Station at 100.0MHz Frequency

D. Bill of Materials
Figure 15 shows the bill of materials. Build the device and have fun!

Step 17: Figure 15 Bill of Materials (BOM)

Correction: The value of the R7 is 0R (1206). It is better to use TS2940CW50 (SOT-223) for the IC1. Use 8-ohm speakers to prevent probable thermal stress on the IC1 regulator at high output power, or use a more powerful regulator.