SI4735

SI473X Library for Arduino

View on GitHub

Schematics and Sketches

Please, also check the comments at the beginning of each sketch example available in this library. You will find the SI473X, button, encoder, display and Arduino settings.

IT IS IMPORTANT TO SAY THAT THE CIRCUITS DESIGN BUILT BY THE AUTHOR ARE NOT INTEND TO BE A FINAL PRODUCT. SOME IMPORTANT ASPECTS AND DETAILS ABOUT A GOOD RECEIVER WERE OMITTED HERE. THE IDEA OF THE CIRCUITS MADE BY THE AUTHOR WERE ORIENTED TO BE A PROVE OF CONCEPT OF THE FUNCTIONS IMPLEMENTED IN THE ARDUINO LIBRARY. SO, COMPONENTS LIKE RF FRONT-END, BAND PASS FILTER, ESD, ANTENNA DESIGN ARE NOT THE MAIN PART OF THIS PROJECT.

This project is about a library to control the SI47XX devices and the focus of this project is the library and its functionalities. Please, don’t ask the author of this project to assist you with displays, encoders, buttons or something else out of the “PU2CLR SI4735 Arduino Library” scope. Thanks.

Use the following groups to guide you in your projects

Basic Schematic (Atmega328 based board)

The schematic below shows how to connect the SI473X (SSOP24 package) circuit with Arduino Pro Mini 3.3V/8MHz.

Basic Schematic

All Sketches on SI47XX_01_SERIAL_MONITOR folder


Atmega328 based board and OLED

Atmega328 based board and OLED

Sketche SI47XX_02_ALL_IN_ONE_OLED


ESP32 based board

The schematic below guides you to build a SI473X based receiver using the ESP32 device.

ESP32 basic setup

ESP32 Basic schematic

ESP32 DEVKIT with OLED and Encoder setup

Esp32 based board schematic

All Sketches on SI47XX_06_ESP32 folder



ESP8266

ESP8266_12_F Basic schematic

ESP8266 Basic schematic

ESP8266 OLED

ESP32 Basic schematic


Standalone ATmega328 with or without external Crystal (SI4735-D60 and LCD 16x2).

The schematic below can be also used with a regular Arduino Board based on ATmega328. It is almost the same circuit posted by Mirko Pavleski on his Arduino Project repository. If you use an SI4735-D60 or SI4732-A10, you can have a All band receiver with FM, AM and SSB modes.

Standalone ATmega328 with or without external Crystal (LCD 16x2 version)

Sketch SI47XX_02_for_Mirko_Pavleski_radio.

Please, use the MiniCore setup on your Arduino IDE to deal with standalone Atmega328.

See video:


All band receiver based on SI473X and standalone ATmega328 Modes: FM (VHF) and AM and SSB (HF)



Basic schematic with TFT

The schematic below guides you to build your own receiver based on the SI473X with TFT display. The sketches available on examples/SI47XX_04_TFT/ folder decribe the wire up used by the TFT selected by the author. Please, read the comments at the beginning of each sketch example.

Basic schematic with TFT

Sketches on examples/SI47XX_04_TFT/

See video: Si4735 All in One Receiver running on Arduino Pro Mini 3.3V (8MHz) and TFT Display


Video - SI4735 Arduino Library and SSB/CW support



Arduino DUE/MEGA and touch TFT display.

The schematic below shows just the Arduino DUE and SI473X connections. The touch TFT used by this circuit is a shield that can be connected to the Arduino DUE directly. If you intent to use Arduino Mega, you have to add a bidirectional logic level converter.

Basic schematic with TFT

Sketches on SI47XX_10_RDS

See videos:


Arduino MEGA 2560 and toutch TFT diaplay setup



Arduino Due and toutch TFT diaplay setup



Attiny85 basic circuit

You can use de Si4735 Arduino Library on the very small ATtiny85 or Attiny84. The schematic below can guide you to build a receiver based on attiny85 device.

Attiny85 Basic schematic

Attiny85 with external eeprom

Attiny85 Basic schematic

Sketches on examples/SI47XX_05_ATTINY85

See videos:


SI4735 Arduino Library working with ATtiny85



How to "SI4735 Arduino Library and ATtiny85"



Bluepill - STM32F103C8 basic schematic

STM32F1 and SI4735-D60 or SI4732-A10 wire up

Si4735 SI4732 DESC. ESP32
pin 15 pin 9 RESET PA12
pin 18 pin 12 SDIO B7
pin 17 pin 11 SCLK B6

The schematic below guides you to build a SI473X based receiver using the STM32 device.

The schematics below guide you to build a SI473X based receiver using the STM32 device.

Bluepill Basic schematic V1

This version uses a Encoder with Push Button, and 7 push button.

Bluepill Basic schematic V1

OLED, Encoder and Buttons connections

Device name Device Pin / Description STM32F1  
OLED      
  SDA/SDIO B7  
  SCL/SCLK B6  
Encoder      
  A PA0  
  B PA1  
  PUSH BUTTON (BFO/VFO) PA15 BFO_SWITCH
Buttons      
MODE_SWITCH Switch MODE (Am/LSB/USB) PA2  
BANDWIDTH Bandwidth PA3  
VOL Volume Up PA4  
VOL_DOWN Volume Down PA5  
BAND_UP Next Band PA6  
BAND_DOWN Previous band PA7  
AGC_SWITCH Switch AGC PA8  
STEP_SWITCH Step Switch PA11  

Bluepill Basic schematic V2

This version uses only a Encoder with Push Button

Bluepill Basic schematic V2

OLED and Encoder connections

STM32F1 and components wire up.

Device name Device Pin / Description STM32F1
OLED    
  SDA/SDIO B7
  SCL/SCLK B6
Encoder    
  A PA9
  B PA10
  PUSH BUTTON (encoder) PA11

Sketches on SI47XX_07_STM32

See video:


Si4735 Arduino Library and Bluepill STM32F103



Teensy 3.X and 4.X

The setup bellow works on Teensy 3.X and Teensy 4.X board family.

Teensy and components wire up.

OLED and Encoder

Device name Device Pin / Description Teensy
OLED    
  SDA/SDIO A4
  SCL/SCLK A5
Encoder    
  A 9
  B 10
  PUSH BUTTON (encoder) 11

SI4735-D60 or SI4732-A10 wire up

Si4735 SI4732 DESC. Teensy
pin 15 pin 9 RESET 12
pin 18 pin 12 SDIO A4
pin 17 pin 11 SCLK A5

Teensy Basic schematic with OLED and Encoder

Teensy 3.X or 4.X Basic schematic with OLED

Sketches on SI47XX_14_TEENSY

Arduino Pro Mini 3.3V and 7SEG Display based on TM1638

It is a receiver prototype based on SI4735 controlled by TM1638 based devices with buttons, LEDs and 7 segment display. This receiver covers AM and SSB (LW, MW and SW) and FM from 64 to 108 MHz.

The photo below shows the TM1638 based device.

TM1638 photo

SI4735, Arduino Pro Mini 3.3V, encoder and TM1638

Arduino and TM1638 schematic

Sketches on SI47XX_08_TM1638

See video:


FM, AM and SSB receiver with Arduino and TM1638 7 segments display device


Android and iOS Remote Control for PU2CLR Arduino Library DSP receivers

The schematic below is a simple example that shows a way to use your smartphone as a remote control via Bluetooth. You will find more details here.

Mobile device remote control Schematic

See Android and iOS Remote Control for PU2CLR Arduino Library DSP receivers.

See video

Si4735 receiver prototype controlled by iPhone via Bluetooth


External Mute Circuit

The SI47XX devices have about DC bias component in the analog audio output pins (SI4735-D60 pins 23 and 24). When the device goes to power down mode, the voltage on the audio pins drops to 0V. The device do it internally and there is not a way to avoid that. When the device goes to power up, that audio pins suddenly goes to high DC again. This transition causes the loud pop in the speaker. It is possible to solve this problem by adding an extra mute circuit and control it by the MCU (Atmega, ESP32, STM32, ATtiny85 etc).

External Mute Circuit

Considering that you are using a MCU based on Atmega328, when the D14 is HIGH the Si47XX output audio will be drained to the ground. At this condition, no audio will be transferred to the amplifier input and, consequently, to the speaker. So, no loud click in the speaker.

When the D14 is LOW, the most of signal audio output from the Si47XX will be transfered to the input of the amplifier.

The code below shows all you have to do in your sketch to implement this resource.


#include <SI4735.h>
#define AUDIO_MUTE 14      // Pin A0 - Switch AGC ON/OF

Si4735 r;

void setup() {
  .
  
  // It is all you have to do to control a external audio mute circuit if you have one. 
  r.setAudioMuteMcuPin(AUDIO_MUTE); // Tells the system to control an external audio mute circuit. 

  r.setup(RESET_PIN, -1, 1, SI473X_ANALOG_AUDIO); // Starts on FM mode and ANALOG audio mode. 
  .
  .
  .

} 

Some low power audio amplifiers IC also implement mute circuit that can be controlled externally. You can find this resource on LM4906, LM4863, KA8602B, MC34119, PAM8403 and HT82V739 devices.

See Video:

Removing the loud click in the speaker during power down and power up


Video about external circuit and audio mute control



SI473X and external active crystal oscillator or signal generator

You can use a signal generator or a active crystal oscillator instead the passive 32768kHz passive crystal with Si473X devices. This setup can be useful to improve the receiver performance or deal with digital audio output. The schematic below shows this setup.

SI473X and external active crystal oscillator or signal generator

Check the PU2CLR SI4735 Arduino Library API documentation to deal with external clock reference. The code below shows how to setup external clock.

void setup(void)
{

  .
  .
  .
  si4735.setRefClock(32768);
  si4735.setRefClockPrescaler(1);   // will work with 32768  
 
  si4735.setup(RESET_PIN, -1, POWER_UP_FM, SI473X_ANALOG_AUDIO, XOSCEN_RCLK);
  .
  .
  .
}

See the sketch example: I47XX_02_RDS_TOUCH_SHIELD_REF_CLOCK

Video:

SI4735-D60 and external reference clock test


SI4735-D60 and external reference clock test


Band Pass Filter controlled by Arduino

It is a HF band pass filter controlled by Arduino. It is designed for HF receivers. With this project, you can use a set of up to four HF bandpass filters that can be selected by Arduino. To do that you will need just two digital Arduino pins. All about this project on here.

Band Pass Filter controlled by Arduino

See videos:


HF Auto Bandpass filter controlled by Arduino (first test)



HF auto bandpass filter controlled by Arduino (real test)


Storing data into the internal EEPROM before shutdowning

This example uses the Arduino Pro Mini 3.3V (8MHz), the SI4735 and OLED.

The EEPROM has a lifetime around 100,000 write/erase cycles. On “Atmel, ATmega328P, 8-bit AVR Microcontroller with 32K Bytes In-System Programmable Flash” DATASHEET, page 19, you will find: “The Atmel® ATmega328P contains 1Kbyte of data EEPROM memory. It is organized as a separate data space, in which single bytes can be read and written. The EEPROM has an endurance of at least 100,000 write/erase cycles”. Therefore, writing data to eeprom with each system status change could give an application a very short life. To mitigate this problem, some approaches can be used to save recordings on the EEPROM.

The following circuit illustrates a way to configure an Arduino based on Atmega328 to record useful information on its internal EEPROM. The idea of this approach is to obtain the last status of the system after turning it on. Observe in the circuit that a 1000uF electrolytic capacitor has been added. Depending on the arduino board, the time needed to record the information and the shutdown check time, the capacitor value may be different. This capacitor is powered by the battery voltage or external power supply while the system is working. When the user turns the system off, the capacitor will still keep the arduino running for a few seconds. Observe also that the Arduino pin 16 (A2), is connected to the power supply. That setup works as a shutdown detector. I mean, the pin 16 status will keep HIGH while the power supply is on. However, when the user turns the system off (no power supply), the pin 16 status will be LOW. In this condition, a few lines of code have to be added to the loop function to check the pin 16 status frequently. If the pin 16 is LOW, the Arduino will have few seconds to save data into the internal EEPROM. Be aware the capacitance of the capacitor must be high enough to allow the arduino to record all needed data. Increase the capacitance value if 1000uF does not provide enough time for your setup. Actually, the best way to save data immediately is using the interrupt approaching via digital pins 2 or 3 of Atmega328 . However, this example uses with success the pulling approach.

Due to the voltage drop caused by the diode D1, it is important to raise the input voltage to 3.7V. This way the Arduino will continue operating steadily with about 3V. The SI4735 and OLED are powered with 3.7V, a safe voltage for both devices. Only the arduino will keep running for a few seconds after system shutdown. See circuit and sketch reference below.


Storing data into the internal EEPROM before shutdowning


Arduino sketch setup



#include <SI4735.h>
#include <EEPROM.h>

#define SHUTDOWN_DETECTOR 16 // A2 - Arduino pin 16 configured as digital

const uint8_t app_id =  35; // Useful to check the EEPROM content before processing useful data
const int eeprom_address = 0;

void setup() {
  pinMode(SHUTDOWN_DETECTOR, INPUT); // If HIGH power supply detected; else, no power supply detected
  pinMode(VOLUME_DOWN, INPUT_PULLUP);
  pinMode(VOLUME_UP, INPUT_PULLUP);  
  .
  .
  // If you want to reset (erase) the eeprom, keep the VOLUME_UP button pressed during statup
  if (digitalRead(VOLUME_UP) == LOW)
  {
    EEPROM.write(eeprom_address, 0); // In our case, just the app_id is enough.
    oled.print("EEPROM RESETED");
    delay(2000);
  }

  // Checking the EEPROM content 
  if (EEPROM.read(eeprom_address) == app_id) { // There are useful data stored to rescue
    volume = EEPROM.read(eeprom_address + 1); // Gets the stored volume;
    freqByteHigh = EEPROM.read(eeprom_address + 2); // Gets the frequency high byte
    freqByteLow = EEPROM.read(eeprom_address + 3);  // Gets the frequency low  byte
    currentFrequency = (freqByteHigh << 8) | freqByteLow; // Converts the stored frequency to SI473X frequency.
  } else { // No data found
    volume = 45;
    currentFrequency = 10390; // 103.9MHz
  }
  .
  .
  .
  rx.setup(RESET_PIN, FM_FUNCTION);
  rx.setFM(8400, 10800, currentFrequency, 10);
  rx.setVolume(volume);
  .
  .
  .
}

/** 
 *  Saves the current volume and frequency into the internal EEPROM
 */
void writeReceiverData() {
  EEPROM.write(eeprom_address, app_id); // stores the app id;
  EEPROM.write(eeprom_address + 1, rx.getVolume()); // stores the current Volume
  EEPROM.write(eeprom_address + 2, (currentFrequency >> 8) );   // stores the current Frequency HIGH byte
  EEPROM.write(eeprom_address + 3, (currentFrequency & 0xFF));  // stores the current Frequency LOW byte
}


void loop {
  .
  .
  .
  // Checks the shutdown status
  if (digitalRead(SHUTDOWN_DETECTOR) == LOW ) {
    writeReceiverData();
    while(1); // Stop working
  }
}


See the complete sketches on examples/TOOLS/SI47XX_02_STORE_EEPROM_BEFORE_SHUTDOWN

See video:


Storing the current status of the SI473X based receivers into the Arduino eeprom automatically


Back to the main page

Another method to store data into the EEPROM

You also can store useful data without a special circuit. This approach will store data every time some important status changes. The idea is store data only if it is necessary.

Steps:

Example


#define STORE_TIME 10000      // Time of inactivity to make the current receiver status writable (10 seconds).

const uint8_t app_id = 35;     // Application ID. Any value from 1 to 255.  It will be useful to check the EEPROM content before processing useful data
const int eeprom_address = 0;  // Address where the data will be stored into EEPROM
long storeTime = millis();     // elapsed time control 


void setup() {

  .
  .
  .

  // If you want to reset the eeprom, keep the  button pressed during statup
  if (digitalRead(GIVEN_BUTTON) == LOW)
  {
    EEPROM.write(eeprom_address, 0); // Changes the application ID. It invalidates all stotred information. 
    delay(2000);
  }

  .
  .
  .

  // Checking the EEPROM content and read if it has valid information
  if (EEPROM.read(eeprom_address) == app_id)
  {
    readAllReceiverInformation();
  }

  .
  .
  .

}


void saveAllReceiverInformation()
{
  EEPROM.update(eeprom_address, app_id);                      // stores the app id;
  EEPROM.update(eeprom_address + 1, si4735.getVolume());      // stores the current Volume
  EEPROM.update(eeprom_address + 2, currentMode);             // Stores the current Mode (FM / AM / SSB)
  EEPROM.update(eeprom_address + 3, currentFrequency >> 8);   // Store the current frequency
  EEPROM.update(eeprom_address + 4, currentFrequency & 0XFF);
  .
  .
  .
  
}


void readAllReceiverInformation()
{
  volume = EEPROM.read(eeprom_address + 1);                 // Gets the stored volume;
  currentMode = EEPROM.read(eeprom_address + 2);            // Gets the stored mode
  currentFrequency = EEPROM.read(eeprom_address + 3) << 8;  // Gets the stored frequency 
  currentFrequency |= EEPROM.read(eeprom_address + 4);
  .
  .
  .
}


void loop() {
  .
  .
  .
  // Monitor your data and set statusChanged variable to true if any useful data has changed. 
  .
  .
  .
  
  // check if some status was changed  
  if ( statusChanged )
  {
    // If the status has changed and the elapsed time is less than minimal time, wait a bit more for saving new data. 
    if ((millis() - storeTime) > STORE_TIME) 
    {
      saveAllReceiverInformation();
      storeTime = millis();
      statusChanged = false;
    }
  }
   
}

See this aproach working on SI47XX_03_ALL_IN_ONE_NEW_INTERFACE_V2