Si4703 (Arduino)

Модуль Si4703 представляет собой FM-радиоприёмник (УКВ от 76 МГц до 108 МГц) с цифровым управлением и функцией RDS. Так же модуль содержит маломощный усилитель мощности звуковой частоты TPA6111A2, позволяющий подключать наушники к модулю используя разъем 3,5 мм, при этом подключенные наушники используются в качестве антенны.

Radio Data System ( RDS) — многоцелевой стандарт, предназначенный для передачи информационных сообщений по каналам ЧМ-радиовещания в диапазоне УКВ.

Основные параметры SI4703:

  • Диапазон принимаемых частот: 76–108 МГц
  • Интерфейс: 2-Wire, 3-Wire
  • Напряжение питания: от 2,7 В до 5,5 В
  • Потребляемый ток: до 17 мА
  • Управление громкостью: цифровое
  • Автоматическая регулировка усиления (AGC)
  • Измерение уровня сигнала
  • Адаптивное подавление шума
  • Регулятор громкости (16 уровней)
  • Аналоговый выход линейного уровня
  • RDS/RBDS
  • Авто поиск станций с шагом 50, 100 и 200 кГц

Для тестового запуска модуля Si4703 на базе Arduino необходимо собрать следующую схему:

Управление модулем на Si4703 осуществляется при помощи шины 3-Wire (SDIO, SCLK, SEN), для перевода микросхемы для работы с шиной 3-Wire выход GPIO1 должен замкнут на землю. Выход RST используется для сброса настроек модуля после подачи питания.

Для управления Si4703 используется библиотека — si4703.zip

Библиотека поддерживает следующие функции:

  • radio.fm_start( int f ) — функция установки частоты радиостанции, применяется один раз при включении приемника
    • int f = F x 10 — 760
      • где F — частота станции в МГц
  • radio.init() — функция содержит все необходимые настройки для запуска приемника
  • si4703 radio( 3,2,4,5 ) — функция подключения, необходимо указать номера пинов Arduino (SDIO, SCLK, SEN, RST)
  • radio.si_volume( int vol ) — установка громкости, 16 шагов
    • int vol  от 0 до 15
  • radio.seek_up() — авто поиск станции, увеличение частоты (шаг 0,1 МГц)
  • radio.seek_down() — авто поиск станции, уменьшение частоты (шаг 0,1 МГц)
  • radio.nom_ch() — чтение текущей установленной частоты int f
    • F = ( int f + 760 ) / 10
      • F — частота станции в МГц
  • radio.seach() — чтение флага установки частоты станции в режиме поиска, 1 — частота станции установлена, 0 — поиск станции
  • radio.rss() — чтение уровня сигнала
  • radio.st_mn() — чтение установки режимов моно\стерео
  • radio.readRDS() — чтение данных RDS (название станции — 8 символов)

Тестовый скетч:

#include <si4703.h>
 si4703 radio(3,2,4,5); // SDIO, SCLK, SEN, RST
 int f_cannel = 1019;
 
void setup() {
  radio.init();
  Serial.begin(9600); 
 
  radio.fm_start(f_cannel-760);// 101.9 МГц (1019-760 = 259)
  radio.si_volume(10);// 0...15
}
 
void loop() {
  if(Serial.available()){
    char serial = Serial.read();
    if(serial == 'u'){radio.seek_up();}
    if(serial == 'd'){radio.seek_down();}
    }  
 
Serial.print(" F = ");
Serial.print(float((radio.nom_ch()+760.00)/10),2);
Serial.print(" RDS =");
Serial.print(radio.readRDS());
Serial.print(" STC =");
Serial.print(radio.seach());
Serial.print(" RSSI =");
Serial.print(radio.rss());
Serial.print(" ST =");
Serial.println(radio.st_mn());
}

После загрузки скетча в мониторе порта можно увидеть данные о текущей частоте, RDS, флаг поиска станции, уровень сигнала и значение флага моно\стерео. Если в стоке ввода монитора порта указать и отправить символы u или d, то можно начать поиск станции при повышении или понижении частоты поиска.


Используя дисплей LCD2004 с модулем I2C (I2C модуль на базе микросхем PCF8574 позволяют подключить символьный дисплей 1602 к плате Arduino всего по двум проводам SDA и SCL (А4 и А5), что дает возможность не использовать цифровые выходы Arduino при подключении дисплея) и 4-е кнопки, можно собрать простой радиоприёмник.

Радиоприемник имеет следующие функциональные возможности:

  • Поиск станции — увеличение и уменьшение частоты
  • Запуск станции при включении
  • Регулировка громкости
  • Запоминание уровня громкости (0…15) и последней выбранной станции (была включена не менее одной минуты) перед выключением.
  • RDS — название станции
  • Индикатор уровня сигнала
  • Индикатор моно/стерео

#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <si4703.h>
 si4703 radio(3,2,4,5); // SDIO, SCLK, SEN, RST
 LiquidCrystal_I2C lcd(0x27,20,4);
 byte v1[8] = {0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07};
 byte v2[8] = {0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00};      
 byte v3[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v4[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x1F,0x1F};
 byte v5[8] = {0x1C,0x1C,0x00,0x00,0x00,0x00,0x1C,0x1C};
 byte v6[8] = {0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C};
 byte v7[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07};
 byte v8[8] = {0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00};
 byte d1,d2,d3,d4,d5,d6,e1,e2,e3;
 int a[6],x;
 bool w=1,save_ch,w1;
 int canel,vol; 
 unsigned long times,times1;
 byte t;
 char  old[8];
 char * print_rds;
 
void setup() {
  Wire.begin();lcd.init();lcd.backlight();
  lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);lcd.createChar(4, v4);
  lcd.createChar(5, v5);lcd.createChar(6, v6);lcd.createChar(7, v7);lcd.createChar(8, v8);
  //Serial.begin(9600);  
  radio.init();
  pinMode(7,INPUT_PULLUP);// button up
  pinMode(8,INPUT_PULLUP);// button down
  pinMode(9,INPUT_PULLUP);// button volume UP
  pinMode(10,INPUT_PULLUP);// button volume DOWN
  canel = ((EEPROM.read(400)<<8))|EEPROM.read(401);vol=EEPROM.read(402);
  if(canel>320){canel=0;}if(vol>15){vol=10;}
  Serial.print("Device ID: ");Serial.println(radio.read_device_id(),HEX);
  Serial.print("Chip ID: ");Serial.println(radio.read_chip_id(),HEX);
  radio.si_volume(vol);
}
 
void loop() {
//////// BUTTON /////////////////////////////////////////////////  
 if(digitalRead(7)==LOW){radio.seek_up();save_ch=1;times=millis();delay(100);}
 if(digitalRead(8)==LOW){radio.seek_down();save_ch=1;times=millis();delay(100);}
 
 if(digitalRead(9)==LOW){vol++;save_ch=1;times=millis();if(vol>15){vol=15;}radio.si_volume(vol);delay(100);}
 if(digitalRead(10)==LOW){vol--;save_ch=1;times=millis();if(vol<0){vol=0;}radio.si_volume(vol);delay(100);}
///////////////////////////////////////////////////////////////// 
 
/////// EEPROM ////////////////////////////////////////////////// 
 if(millis()-times>60000&&save_ch==1){save_ch=0;canel = radio.nom_ch();
 EEPROM.update(400,(canel>>8) & 0b11);EEPROM.update(401,canel & 0xFF);EEPROM.update(402,vol);}
 
/////// LCD STEREO/MONO SIGNAL VOLUME /////////////////////////////////////////////////
 if(w==1){w=0;radio.fm_start(canel);}
 if(millis()-times1>1000){times1=millis();lcd.setCursor(13,2);lcd.print("SIG ");lcd.print(radio.rss());lcd.print(" ");
 if(radio.st_mn()==0){lcd.setCursor(13,1);lcd.print("MONO  ");}
  else{lcd.setCursor(13,1);lcd.print("STEREO");}}
  lcd.setCursor(13,0);lcd.print("VOL ");lcd.print(vol);lcd.print(" ");
  lcd.setCursor(2,2);lcd.print("FM RADIO");
 
////// LCD PRINT RDS ST_NAME ///////////////////////////////////////////////  
if(radio.seach()==1 && radio.rss()>30){print_rds = radio.readRDS();}
  if(t==0){for(int i=0;i<8;i++){old[i]=print_rds[i];}}t++;
  if(radio.seach()==0){
  for(int i=0;i<8;i++){print_rds[i]=61;}t=0;lcd.setCursor(6,3);lcd.print(" No RDS ");} 
  byte d=0;for(int i=0;i<8;i++){if(old[i]==print_rds[i]){}else{d++;}}
  if(d==0 && t==5){t=0;
  for(int i=0;i<8;i++){lcd.setCursor(6+i,3);lcd.print(print_rds[i]);}}
  if(t>8){t=0;}
  lcd.setCursor(0,3);lcd.print("======");
  lcd.setCursor(14,3);lcd.print("======");
 
///////// LCD BIG ///////////////////////////////////////////////
 int f_ch = radio.nom_ch() + 760;
     a[0]=f_ch/1000;
     a[1]=f_ch/100%10;
     a[2]=f_ch/10%10;
     a[3]=f_ch%10;
     if(f_ch<1000){a[0]=10;}
   for(x=0;x<4;x++){
    switch(x){
        case 0: e1=0;e2=0,e3=1;break;
        case 1: e1=2,e2=3,e3=4;break;
        case 2: e1=5,e2=6,e3=7;break;
        case 3: e1=9,e2=10,e3=11;break;
   }digit();}
   lcd.setCursor(8,1);lcd.print(".");
//////////////////////////////////////////////////////////////////
delay(1);
 
}// loop
 
void digit(){switch(a[x]){
case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
case 10:d1=150,d2=150,d3=150,d4=150,d5=150,d6=150;break;}
if(x>0){lcd.setCursor(e1,0);lcd.write((uint8_t)d1);}
lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);}

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=421

Datasheet — Si4703_datasheet

Comments

    1. Громкость берется из EEPROM, стоит защита, если в EEPROM записано значение больше 15, то громкость сбрасывается на 0.
      В новых платах всегда EEPROM имеет значение 255

Добавить комментарий

Войти с помощью: