1

Тема: Радио RDA5807M

Основная статья http://rcl-radio.ru/?p=53149
Приветствую, заинтересовался данным проектом и решил повторить. В статье две схемы не пойму какой из них верить. Подскажите какой нужен конденсатор, например такой подойдёт 10V 1000mkF или на большее напряжение брать? Какие динамики лучше у меня есть 4ом 3ватт? Там где антенна будет получается тоже кондёр нужен, его напряжение?

2

Re: Радио RDA5807M

Основная схема расположена в статье, конденсаторы 10 мкФ и выше (но выше смысла нет), радио модуль не предназначен для работы с низкоомной нагрузкой, только наушники. Для подключения динамиков нужен усилитель. Антенна подсоединяется напрямую без конденсатора (он есть на плате).

3

Re: Радио RDA5807M

pam8403 усилитель туда как-то прикрутить можно ?

4

Re: Радио RDA5807M

Да.
http://forum.rcl-radio.ru/uploads/images/2020/02/44473b73d78579f2fec5c3e99c24a245.png

5

Re: Радио RDA5807M

Получается без конденсаторов подключение?

6

Re: Радио RDA5807M

Можно не ставить, они есть на плате усилителя

7

Re: Радио RDA5807M

Спасибо, буду пробовать собрать

8

Re: Радио RDA5807M

Собрал работает, подскажите кнопки заменить одним энкодером с кнопкой возможно? Как послушать диапазон  ниже 87 МГц у приемника описание 50 МГц - 115 МГц

9

Re: Радио RDA5807M

Посмотрю что можно сделать.

10

Re: Радио RDA5807M

https://tsibrov.blogspot.com/2019/11/rd … part1.html
Вот по ссылке тему энкодера затронули, но не раскрыли.
Я так понял нужно записывать значения регистров RDA5807M один и 4х:
00 - 87..108МГц
01 - 76..91МГц
10 - 76..108МГц
11 - 65..76МГц или 50..65МГц

11

Re: Радио RDA5807M

RDA5807M.cpp
#define RADIO_REG_CHAN_BAND_FM      0x0000
переправить на
#define RADIO_REG_CHAN_BAND_FM      0x1100
Возможно это поможет

12

Re: Радио RDA5807M

не могу найти где это?
C:\Users\.......\Arduino\libraries\RDA5807M-master в ней RDA5807M.cpp
открываю NotePad++ но этой строчки нигде не вижу, возможно у нас разные библиотеки

13

Re: Радио RDA5807M

/// \file RDA5807M.cpp
/// \brief Implementation for the radio library to control the RDA5807M radio chip.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014-2015 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/License.aspx
///
/// This library enables the use of the radio chip RDA5807M from http://www.rdamicro.com/.
///
/// More documentation and source code is available at http://www.mathertel.de/Arduino
///
/// History:
/// --------
/// * 05.08.2014 created.


#include <Arduino.h>
#include <Wire.h>

#include <radio.h>
#include <RDA5807M.h>

// ----- Register Definitions -----

// this chip only supports FM mode
#define FREQ_STEPS 10

#define RADIO_REG_CHIPID  0x00

#define RADIO_REG_CTRL    0x02
#define RADIO_REG_CTRL_OUTPUT 0x8000
#define RADIO_REG_CTRL_UNMUTE 0x4000
#define RADIO_REG_CTRL_MONO   0x2000
#define RADIO_REG_CTRL_BASS   0x1000
#define RADIO_REG_CTRL_SEEKUP 0x0200
#define RADIO_REG_CTRL_SEEK   0x0100
#define RADIO_REG_CTRL_RDS    0x0008
#define RADIO_REG_CTRL_NEW    0x0004
#define RADIO_REG_CTRL_RESET  0x0002
#define RADIO_REG_CTRL_ENABLE 0x0001

#define RADIO_REG_CHAN    0x03
#define RADIO_REG_CHAN_SPACE     0x0003
#define RADIO_REG_CHAN_SPACE_100 0x0000
#define RADIO_REG_CHAN_BAND      0x000C
#define RADIO_REG_CHAN_BAND_FM      0x0000
#define RADIO_REG_CHAN_BAND_FMWORLD 0x0008
#define RADIO_REG_CHAN_TUNE   0x0010
//      RADIO_REG_CHAN_TEST   0x0020
#define RADIO_REG_CHAN_NR     0x7FC0

#define RADIO_REG_R4    0x04
#define RADIO_REG_R4_EM50   0x0800
//      RADIO_REG_R4_RES   0x0400
#define RADIO_REG_R4_SOFTMUTE   0x0200
#define RADIO_REG_R4_AFC   0x0100


#define RADIO_REG_VOL     0x05
#define RADIO_REG_VOL_VOL   0x000F


#define RADIO_REG_RA      0x0A
#define RADIO_REG_RA_RDS       0x8000
#define RADIO_REG_RA_RDSBLOCK  0x0800
#define RADIO_REG_RA_STEREO    0x0400
#define RADIO_REG_RA_NR        0x03FF

#define RADIO_REG_RB          0x0B
#define RADIO_REG_RB_FMTRUE   0x0100
#define RADIO_REG_RB_FMREADY  0x0080


#define RADIO_REG_RDSA   0x0C
#define RADIO_REG_RDSB   0x0D
#define RADIO_REG_RDSC   0x0E
#define RADIO_REG_RDSD   0x0F

// I2C-Address RDA Chip for sequential  Access
#define I2C_SEQ  0x10

// I2C-Address RDA Chip for Index  Access
#define I2C_INDX  0x11


// ----- implement

// initialize the extra variables in RDA5807M
RDA5807M::RDA5807M() {
  // t.b.d. ???
}

// initialize all internals.
bool RDA5807M::init() {
  bool result = false; // no chip found yet.
  DEBUG_FUNC0("init");

  Wire.begin();
  Wire.beginTransmission(I2C_INDX);
  result = Wire.endTransmission();
  if (result == 0) {
    DEBUG_STR("radio found.");
    result = true;

    // initialize all registers
    registers[RADIO_REG_CHIPID] = 0x5804;  // 00 id
    registers[1] = 0x0000;  // 01 not used
    registers[RADIO_REG_CTRL] = (RADIO_REG_CTRL_RESET | RADIO_REG_CTRL_ENABLE);
    setBand(RADIO_BAND_FM);
    registers[RADIO_REG_R4] = RADIO_REG_R4_EM50;//  0x1800;  // 04 DE ? SOFTMUTE
    registers[RADIO_REG_VOL] = 0x9081; // 0x81D1;  // 0x82D1 / INT_MODE, SEEKTH=0110,????, Volume=1
    registers[6] = 0x0000;
    registers[7] = 0x0000;
    registers[8] = 0x0000;
    registers[9] = 0x0000;

    // reset the chip
    _saveRegisters();

    registers[RADIO_REG_CTRL] = RADIO_REG_CTRL_ENABLE;
    _saveRegister(RADIO_REG_CTRL);
  }  // if
  return(result);
} // init()


// switch the power off
void RDA5807M::term()
{
  DEBUG_FUNC0("term");
  setVolume(0);
  registers[RADIO_REG_CTRL] = 0x0000;   // all bits off
  _saveRegisters();
} // term


// ----- Volume control -----

void RDA5807M::setVolume(uint8_t newVolume)
{
  RADIO::setVolume(newVolume);
  newVolume &= RADIO_REG_VOL_VOL;
  registers[RADIO_REG_VOL] &= (~RADIO_REG_VOL_VOL);
  registers[RADIO_REG_VOL] |= newVolume;
  _saveRegister(RADIO_REG_VOL);
} // setVolume()


void RDA5807M::setBassBoost(bool switchOn)
{
  RADIO::setBassBoost(switchOn);
  uint16_t regCtrl = registers[RADIO_REG_CTRL];
  if (switchOn)
  regCtrl |= RADIO_REG_CTRL_BASS;
  else
  regCtrl &= (~RADIO_REG_CTRL_BASS);
  registers[RADIO_REG_CTRL] = regCtrl;
  _saveRegister(RADIO_REG_CTRL);
} // setBassBoost()


// Mono / Stereo
void RDA5807M::setMono(bool switchOn)
{
  RADIO::setMono(switchOn);

  registers[RADIO_REG_CTRL] &= (~RADIO_REG_CTRL_SEEK);
  if (switchOn) {
    registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_MONO;
  }
  else {
    registers[RADIO_REG_CTRL] &= ~RADIO_REG_CTRL_MONO;
  }
  _saveRegister(RADIO_REG_CTRL);
} // setMono


// Switch mute mode.
void RDA5807M::setMute(bool switchOn)
{
  RADIO::setMute(switchOn);

  if (switchOn) {
    // now don't unmute
    registers[RADIO_REG_CTRL] &= (~RADIO_REG_CTRL_UNMUTE);
  }
  else {
    // now unmute
    registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_UNMUTE;
  } // if
  _saveRegister(RADIO_REG_CTRL);
} // setMute()


// Switch softmute mode.
void RDA5807M::setSoftMute(bool switchOn)
{
  RADIO::setSoftMute(switchOn);

  if (switchOn) {
    registers[RADIO_REG_R4] |= (RADIO_REG_R4_SOFTMUTE);
  }
  else {
    registers[RADIO_REG_R4] &= (~RADIO_REG_R4_SOFTMUTE);
  } // if
  _saveRegister(RADIO_REG_R4);
} // setSoftMute()


// ----- Band and frequency control methods -----

// tune to new band.
void RDA5807M::setBand(RADIO_BAND newBand) {
  uint16_t r;
  RADIO::setBand(newBand);

  if (newBand == RADIO_BAND_FM)
  r = RADIO_REG_CHAN_BAND_FM;
  else if (newBand == RADIO_BAND_FMWORLD)
  r = RADIO_REG_CHAN_BAND_FMWORLD;
  registers[RADIO_REG_CHAN] = (r | RADIO_REG_CHAN_SPACE_100);
} // setBand()


// retrieve the real frequency from the chip after automatic tuning.
RADIO_FREQ RDA5807M::getFrequency() {
  // check register A
  Wire.requestFrom (I2C_SEQ, 2);
  registers[RADIO_REG_RA] = _read16();

  uint16_t ch = registers[RADIO_REG_RA] & RADIO_REG_RA_NR;
  
  _freq = _freqLow + (ch * 10);  // assume 100 kHz spacing
  return (_freq);
}  // getFrequency


void RDA5807M::setFrequency(RADIO_FREQ newF) {
  DEBUG_FUNC1("setFrequency", newF);
  uint16_t newChannel;
  uint16_t regChannel = registers[RADIO_REG_CHAN] & (RADIO_REG_CHAN_SPACE | RADIO_REG_CHAN_BAND);

  if (newF < _freqLow) newF = _freqLow;
  if (newF > _freqHigh) newF = _freqHigh;
  newChannel = (newF - _freqLow) / 10;

  regChannel += RADIO_REG_CHAN_TUNE; // enable tuning
  regChannel |= newChannel << 6;
  
  // enable output and unmute
  registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_OUTPUT | RADIO_REG_CTRL_UNMUTE | RADIO_REG_CTRL_RDS | RADIO_REG_CTRL_ENABLE; //  | RADIO_REG_CTRL_NEW
  _saveRegister(RADIO_REG_CTRL);

  registers[RADIO_REG_CHAN] = regChannel;
  _saveRegister(RADIO_REG_CHAN);

  // adjust Volume
  _saveRegister(RADIO_REG_VOL);
} // setFrequency()


// start seek mode upwards
void RDA5807M::seekUp(bool toNextSender) {
  // start seek mode
  registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_SEEKUP;
  registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_SEEK;
  _saveRegister(RADIO_REG_CTRL);

  if (! toNextSender) {
    // stop scanning right now
    registers[RADIO_REG_CTRL] &= (~RADIO_REG_CTRL_SEEK);
    _saveRegister(RADIO_REG_CTRL);
  } // if
} // seekUp()


// start seek mode downwards
void RDA5807M::seekDown(bool toNextSender) {
  registers[RADIO_REG_CTRL] &= (~RADIO_REG_CTRL_SEEKUP);
  registers[RADIO_REG_CTRL] |= RADIO_REG_CTRL_SEEK;
  _saveRegister(RADIO_REG_CTRL);

  if (! toNextSender) {
    // stop scanning right now
    registers[RADIO_REG_CTRL] &= (~RADIO_REG_CTRL_SEEK);
    _saveRegister(RADIO_REG_CTRL);
  } // if
} // seekDown()


// Load all status registers from to the chip
// registers 0A through 0F
// using the sequential read access mode.
void RDA5807M::_readRegisters()
{
  Wire.requestFrom (I2C_SEQ, (6 * 2) );
  for (int i = 0; i < 6; i++) {
    registers[0xA+i] = _read16();
  }
} // _readRegisters()


// Save writable registers back to the chip
// The registers 02 through 06, containing the configuration
// using the sequential write access mode.
void RDA5807M::_saveRegisters()
{
  DEBUG_FUNC0("-saveRegisters");
  Wire.beginTransmission(I2C_SEQ);
  for (int i = 2; i <= 6; i++)
  _write16(registers[i]);
  Wire.endTransmission();
} // _saveRegisters


// Save one register back to the chip
void RDA5807M::_saveRegister(byte regNr)
{
  DEBUG_FUNC2X("-_saveRegister", regNr, registers[regNr]);

  Wire.beginTransmission(I2C_INDX);
  Wire.write(regNr);
  _write16(registers[regNr]);
  Wire.endTransmission();
} // _saveRegister



// write a register value using 2 bytes into the Wire.
void RDA5807M::_write16(uint16_t val)
{
  Wire.write(val >> 8); Wire.write(val & 0xFF);
} // _write16


// read a register value using 2 bytes in a row
uint16_t RDA5807M::_read16(void)
{
  uint8_t hiByte = Wire.read();
  uint8_t loByte = Wire.read();
  return(256*hiByte + loByte);
} // _read16


// return current Radio Station Strength Information
// uint8_t RDA5807M::getRSSI() {
//   _readRegisters();
//   uint8_t rssi = registers[RADIO_REG_RB] >> 10;
//   return(rssi);
// } // getRSSI


void RDA5807M::checkRDS()
{
  // DEBUG_FUNC0("checkRDS");

  // check RDS data if there is a listener !
  if (_sendRDS) {

    // check register A
    Wire.requestFrom (I2C_SEQ, 2);
    registers[RADIO_REG_RA] = _read16();

    if (registers[RADIO_REG_RA] & RADIO_REG_RA_RDSBLOCK) {
      DEBUG_STR("BLOCK_E found.");
    } // if

    if (registers[RADIO_REG_RA] & RADIO_REG_RA_RDS) {
      // check for new RDS data available
      uint16_t newData;
      bool result = false;
      
      Wire.beginTransmission(I2C_INDX);                // Device 0x11 for random access
      Wire.write(RADIO_REG_RDSA);                   // Start at Register 0x0C
      Wire.endTransmission(0);                         // restart condition
      
      Wire.requestFrom(I2C_INDX, 8, 1);                  // Retransmit device address with READ, followed by 8 bytes
      newData = _read16();
      if (newData != registers[RADIO_REG_RDSA]) { registers[RADIO_REG_RDSA] = newData; result = true; }

      newData = _read16();
      if (newData != registers[RADIO_REG_RDSB]) { registers[RADIO_REG_RDSB] = newData; result = true; }

      newData = _read16();
      if (newData != registers[RADIO_REG_RDSC]) { registers[RADIO_REG_RDSC] = newData; result = true; }

      newData = _read16();
      if (newData != registers[RADIO_REG_RDSD]) { registers[RADIO_REG_RDSD] = newData; result = true; }

      // _printHex(registers[RADIO_REG_RDSA]); _printHex(registers[RADIO_REG_RDSB]);
      // _printHex(registers[RADIO_REG_RDSC]); _printHex(registers[RADIO_REG_RDSD]);
      // Serial.println();
      
      if (result) {
        // new data in the registers
        // send to RDS decoder
        _sendRDS(registers[RADIO_REG_RDSA], registers[RADIO_REG_RDSB], registers[RADIO_REG_RDSC], registers[RADIO_REG_RDSD]);
      } // if
    } // if
  }
}


/// Retrieve all the information related to the current radio receiving situation.
void RDA5807M::getRadioInfo(RADIO_INFO *info) {

  RADIO::getRadioInfo(info);

  // read data from registers A .. F of the chip into class memory
  _readRegisters();
  info->active = true; // ???
  if (registers[RADIO_REG_RA] & RADIO_REG_RA_STEREO) info->stereo = true;
  if (registers[RADIO_REG_RA] & RADIO_REG_RA_RDS) info->rds = true;
  info->rssi = registers[RADIO_REG_RB] >> 10;
  if (registers[RADIO_REG_RB] & RADIO_REG_RB_FMTRUE) info->tuned = true;
  if (registers[RADIO_REG_CTRL] & RADIO_REG_CTRL_MONO) info->mono = true;
} // getRadioInfo()


// ----- Debug functions -----

void RDA5807M::debugScan()
{
  DEBUG_FUNC0("debugScan");
  uint16_t regChannel = registers[RADIO_REG_CHAN] & (RADIO_REG_CHAN_SPACE | RADIO_REG_CHAN_BAND);
  RADIO_FREQ f = _freqLow;
  int channel = 0;
  
  while (f < _freqHigh) {
    registers[RADIO_REG_CHAN] = regChannel | RADIO_REG_CHAN_TUNE | (channel << 6);
    _saveRegister(RADIO_REG_CHAN);
    
    delay(500);
    debugStatus();

    f += _freqSteps;
    channel += 1;
  } // while
} // debugScan


// send a status report to the serial port
// dump all registers to Serial output
void RDA5807M::debugStatus()
{
  char s[12];

  // read data from registers A .. F of the chip into class memory
  _readRegisters();

  formatFrequency(s, sizeof(s));
  Serial.print("Frequency="); Serial.print(s);

  uint16_t pi = registers[RADIO_REG_RDSA];
  Serial.print(" PI="); _printHex4(pi);

  Serial.print((registers[RADIO_REG_RA] & RADIO_REG_RA_STEREO) ? " Stereo" : " Mono  ");
  Serial.print((registers[RADIO_REG_RA] & RADIO_REG_RA_RDS)    ? " ---"    : " RDS");
  
  int rssi = registers[RADIO_REG_RB] >> 10;

  Serial.print(" Sig="); if (rssi < 10) Serial.write(' ');
  Serial.print(rssi);
  Serial.print(' ');
  for(int i = 0;i < rssi - 15;i++) {Serial.write('*');} // Empfangspegel ab 15. Zeichen
  Serial.println();

  // ruler
  Serial.println("0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F");
  // variables
  for (int n = 0; n < 16; n++) { _printHex4(registers[n]); }
  Serial.println();
  
  // registers
  Wire.beginTransmission(I2C_INDX);                // Device 0x11 for random access
  Wire.write(0x00);                   // Start at Register 0x0C
  Wire.endTransmission(0);                         // restart condition
  Wire.requestFrom(I2C_INDX,32,1);                  // Retransmit device address with READ, followed by 8 bytes
  for (int n = 0; n < 16; n++) {
    _printHex4(_read16());
  }
  Serial.println();
  
  // clear text information in Registers
  if (getBassBoost()) Serial.print("BassBoost ");
  if (getMono()) Serial.print("Mono ");
  int v = getVolume();
  Serial.print("Volume="); Serial.print(v); Serial.print(' ');
  Serial.println();

} // debugStatus


// ----- internal functions -----


// The End.

14

Re: Радио RDA5807M

Как сделаете правки воспользуйтесь тестовым скетчем, для проверки работоспособности на нужной Вам частоте:

#include <Wire.h>
#include <radio.h>
#include <RDA5807M.h>
#define FIX_BAND    RADIO_BAND_FM   
RDA5807M radio; 

void setup() {
  radio.init();
  radio.debugEnable();
  //radio.setMono(1);
  radio.setBandFrequency(FIX_BAND, 10800);// 10800 === 108.00 MHz
  radio.setVolume(10);// 0...15

}

void loop() {}

15

Re: Радио RDA5807M

Попробовал, увы не помогло ниже 87.50  не ловит что нужно, антенна метров 10 кабеля в окно бросил, выше 87 приём отличный, у нас 4 станции должны быть на УКВ  66.30, 69.47, 71.66, 73.10 их не слышно гармоники есть, каналы от тв слышно даже. Да и ладно, как время будет посмотрите как энкодер к радио прикрутить с ним было бы удобнее.

16

Re: Радио RDA5807M

66.30, 69.47, 71.66, 73.10

Шаг измерения частоты нужно снизить

#define RADIO_REG_CHAN_BAND_FM      0x1111 // 11 - 65..76МГц   11 - 25кГц

17

Re: Радио RDA5807M

Без результатов, всё то же

18

Re: Радио RDA5807M

Пожалуйста помогите с энкодером вместо кнопок самому не осилить, вот здесь https://tsibrov.blogspot.com/2019/11/rd … part1.html примерно это сделано, но нет рдс и вывод на дисплей убогий. Вот код

#define DEBUG
#include "RDA5807M.h"
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C_Menu.h> // https://github.com/VladimirTsibrov/LiquidCrystal_I2C_Menu
LiquidCrystal_I2C_Menu lcd(0x27, 20, 4);

#define EEPROM_START_ADDRESS 0
#define PIN_CLK 2 // Энкодер пин A
#define PIN_DT  3 // Энкодер пин B
#define PIN_SW  4 // Кнопка

void OneBigHandler(); // Прототип обработчика меню

enum {mkBack, mkRoot, mkSeekUp, mkSeekDown, mkSetVolume, mkSetFreq, mkRotatePurpose,
      mkSoundOptions, mkBassBoost, mkSoftMute, mkSoftBlend, mkSoftBlendThreshold, 
      mkForceMono, mkTunerOptions, mkNewDemodulation, mkSeekThreshold, mkSaveSettings};

sMenuItem menu[] = {
  {mkBack, mkRoot, "Menu"},
    {mkRoot, mkSeekUp, "Seek up"},
    {mkRoot, mkSeekDown, "Seek down"},
    {mkRoot, mkSetVolume, "Set volume", OneBigHandler},
    {mkRoot, mkSetFreq, "Set frequency", OneBigHandler},
    {mkRoot, mkRotatePurpose, "Encoder purpose",OneBigHandler},
    {mkRoot, mkSoundOptions, "Sound options"},
      {mkSoundOptions, mkBassBoost, NULL, OneBigHandler},
      {mkSoundOptions, mkForceMono, NULL, OneBigHandler},
      {mkSoundOptions, mkSoftMute, NULL, OneBigHandler},
      {mkSoundOptions, mkSoftBlend, NULL, OneBigHandler},
      {mkSoundOptions, mkSoftBlendThreshold, NULL, OneBigHandler},
      {mkSoundOptions, mkBack, "Back"},
    {mkRoot, mkTunerOptions, "Tuner options"},
      {mkTunerOptions, mkNewDemodulation, NULL, OneBigHandler},
      {mkTunerOptions, mkSeekThreshold, NULL, OneBigHandler},
      {mkTunerOptions, mkBack, "Back"},
    {mkRoot, mkSaveSettings, "Save settings", OneBigHandler},
    {mkRoot, mkBack, "Back"}
};

uint8_t menuLen = sizeof(menu) / sizeof(sMenuItem);
bool Searching = false;
bool NeedRepaint = false;
double Freq;
enum {RotateVolume, RotateStation} EncoderPurpose = RotateStation;
unsigned long tm = 0;
char *listOffOn[] = {"OFF", "ON"};

int getItemIndexByKey(uint8_t key) {
  for (uint8_t i = 0; i < menuLen; i++)
    if (menu[i].key == key)
      return i;
  return -1;
}

void updateCaption(uint8_t key, const char format[], const char value[]) {
  uint8_t index = getItemIndexByKey(key);
  char* buf = (char*) malloc(40);
  sprintf(buf, format, value);
  menu[index].caption = (char*) realloc(menu[index].caption, strlen(buf) + 1);
  strcpy(menu[index].caption, buf);
  free(buf);
}

void setup() {
  Wire.begin();
  lcd.begin();
  lcd.attachEncoder(PIN_DT, PIN_CLK, PIN_SW);  

  #if defined(DEBUG)
    Serial.begin(57600);
    lcd.attachIdleFunc(checkSerial);
  #endif
    
  // Читаем настройки из EEPROM
  readEEPROM();

  // Обновляем заголовки в меню
  updateCaption(mkBassBoost, "Bass boost (%s)", listOffOn[(reg02h & RDA5807M_FLG_BASS) > 0]);
  updateCaption(mkSoftMute,  "Soft mute (%s)", listOffOn[(reg04h & RDA5807M_FLG_SOFTMUTE) > 0]);
  updateCaption(mkSoftBlend, "Soft blend (%s)", listOffOn[(reg07h & RDA5807M_FLG_SOFTBLEND) > 0]);
  updateCaption(mkSoftBlendThreshold, "Soft blend threshold (%s)", String((reg07h & RDA5807M_SOFTBLENDTH_MASK) >> RDA5807M_SOFTBLENDTH_SHIFT).c_str());
  updateCaption(mkForceMono, "Force mono (%s)", listOffOn[(reg02h & RDA5807M_FLG_MONO) > 0]);
  updateCaption(mkNewDemodulation, "New demodulation (%s)", listOffOn[(reg02h & RDA5807M_FLG_NEW) > 0]);
  updateCaption(mkSeekThreshold, "Seek threshold (%s)", String((reg05h & RDA5807M_SEEKTH_MASK) >> RDA5807M_SEEKTH_SHIFT).c_str());
}

#if defined(DEBUG)
  void checkSerial() {
    uint8_t b;
    if (Serial.available()) {
      delay(1);
      b = Serial.read();
      if (b == 255) { // Прочитать регистр
        b = Serial.read(); // Адрес регистра
        Wire.beginTransmission(0x11);
        Wire.write(b);
        Wire.endTransmission(false);
        Wire.requestFrom(0x11, 2, true);
        Serial.write(b);
        Serial.write(Wire.read());
        Serial.write(Wire.read());
      }
      else { // Записать регистр
        Wire.beginTransmission(0x11);
        Wire.write(b);
        Wire.write(Serial.read());
        Wire.write(Serial.read());
        Wire.endTransmission(true);
      }
    }
  }
#endif  

void loop() {
  #if defined(DEBUG)
    checkSerial();
  #endif
  
  // Опрос энкодера
  eEncoderState encoderState = lcd.getEncoderState();
  if (encoderState == eButton) { // Нажата кнопка. Покажем меню
      uint8_t selectedMenuItem = lcd.showMenu(menu, menuLen, 1);
      if (selectedMenuItem == mkSeekUp) { // Поиск радиостанции вверх
        seekStation(1);
      }
      else if (selectedMenuItem == mkSeekDown) { // Поиск радиостанции вниз
        seekStation(0);
      }
      // Остальные пункты меню в обработчике
    NeedRepaint = true; // После выхода из меню нужна перерисовка дисплея
  }
  else if (encoderState == eLeft){ // Энкодер повернули влево
    if (EncoderPurpose == RotateVolume) { // Убавить громкость
      uint16_t volume = (reg05h & RDA5807M_VOLUME_MASK);
      if (volume > 0) {
        reg05h &= ~RDA5807M_VOLUME_MASK;
        reg05h |= --volume;
        setRegister(RDA5807M_REG_VOLUME, reg05h);
        if (volume  < 10)
          lcd.printfAt(0, 1, "<   %d    >", volume);
        else
          lcd.printfAt(0, 1, "<   %d   >", volume);
        tm = millis();
      }
    }
    else if (EncoderPurpose == RotateStation) { // Искать вниз
      seekStation(0);
      NeedRepaint = true;
    }
  }
  else if (encoderState == eRight){
    if (EncoderPurpose == RotateVolume) { // Прибавить громкость
      uint16_t volume = (reg05h & RDA5807M_VOLUME_MASK);
      if (volume < 15) {
        reg05h &= ~RDA5807M_VOLUME_MASK;
        reg05h |= ++volume;
        setRegister(RDA5807M_REG_VOLUME, reg05h);
        if (volume  < 10)
          lcd.printfAt(0, 1, "<   %d    >", volume);
        else
          lcd.printfAt(0, 1, "<   %d   >", volume);
        tm = millis();
      }
    }
    else if (EncoderPurpose == RotateStation) { // Искать вверх
      seekStation(1);
      NeedRepaint = true;
    }
  }
  
  if (Searching) { // Проверим найдена ли радиостанция
    reg0Ah = getRegister(RDA5807M_REG_STATUS1);
    if (reg0Ah & RDA5807M_FLAG_STC) {
      // Найдена 
      Searching = false;
      NeedRepaint = true;
      reg03h = getRegister(RDA5807M_REG_TUNING);
      Freq = 87 + double((reg03h & RDA5807M_CHAN_MASK) >> RDA5807M_CHAN_SHIFT) / 10;
    }
  }
  
  if ((NeedRepaint) or (tm and (millis() - tm > 3000)))
    LCDRepaint();
}

void LCDRepaint(){
  // Перерисовать дисплей
  lcd.clear();
  if (Searching) 
    lcd.print("Searching...");
  else {
    String s(Freq, 1);
    lcd.printf("%sFM", s.c_str());
  }

  if (EncoderPurpose == RotateVolume)
    lcd.printAt(0, 1, "< Volume >");
  else if (EncoderPurpose == RotateStation)
    lcd.printAt(0, 1, "< Station >");
    
  NeedRepaint = false;
  tm = 0;
}

void OneBigHandler(){
  // Обработчик для пунктов меню. Здесь только те пункты,
  // при выборе которых не требуется выход из меню
  uint8_t selectedMenuItem = lcd.getSelectedMenuItem();
  if (selectedMenuItem == mkSetVolume) { // Установить громкость
    uint16_t volume = (reg05h & RDA5807M_VOLUME_MASK);

    /* Можно и так, но громкость будет изменяться только после выхода из inputVal
    volume = lcd.inputVal<uint16_t>("Volume", 0, 15, volume); 
    reg05h &= ~RDA5807M_VOLUME_MASK;
    reg05h |= volume;
    setRegister(RDA5807M_REG_VOLUME, reg05h);
    */
    
    lcd.clear();
    lcd.print("Input volume");
    lcd.printAt(0, 1, volume);
    while (1) {
      eEncoderState encoderState = lcd.getEncoderState();
      if (encoderState == eNone) {
        #if defined(DEBUG)
          checkSerial();
        #endif
        continue;
      }
      else if (encoderState == eButton) break;
      else if (encoderState == eLeft) {
        if (volume > 0) volume--; else continue;
      }
      else if (encoderState == eRight) {
        if (volume < 15) volume++; else continue;
      }
      lcd.printAt(0, 1, volume);
      lcd.print(" ");
      reg05h &= ~RDA5807M_VOLUME_MASK;
      reg05h |= volume;
      setRegister(RDA5807M_REG_VOLUME, reg05h);      
    }
  }
  else if (selectedMenuItem == mkSetFreq) { // Запросить и установить частоту
    double newFreq = Freq;
    if (! lcd.inputValBitwise("Input freq", newFreq, 4, 1, 0)) return; // XXX.X
    while ((newFreq < 87) or (newFreq > 108)) {
      lcd.printMultiline("Invalid frequency. Should be in 87..108");
      if (!lcd.inputValBitwise("Input freq", newFreq, 4, 1, 0)) return;
    }
    Freq = newFreq;
    uint16_t chan = uint8_t((newFreq - 87) * 10);
    reg03h &= ~RDA5807M_CHAN_MASK;
    reg03h |= chan << RDA5807M_CHAN_SHIFT;
    setRegister(RDA5807M_REG_TUNING, reg03h | RDA5807M_FLG_TUNE);
  }
  else if (selectedMenuItem == mkRotatePurpose) { // Поведение при вращении энкодера
    String listEncPurpose[] = {"Set volume", "Set station"};
    EncoderPurpose = lcd.selectVal("Encoder purose", listEncPurpose, 2, (int)EncoderPurpose);
  }  
  else if (selectedMenuItem == mkBassBoost) { // Предложим включить усиление басов
    bool bassBoost = reg02h & RDA5807M_FLG_BASS;
    bassBoost = lcd.selectVal("Bass boost", listOffOn, 2, bassBoost);
    if (bassBoost) reg02h |=  RDA5807M_FLG_BASS;
    else           reg02h &= ~RDA5807M_FLG_BASS;
    setRegister(RDA5807M_REG_CONFIG, reg02h);
    updateCaption(mkBassBoost, "Bass boost (%s)", listOffOn[bassBoost]);
  }
  else if (selectedMenuItem == mkForceMono) { // Предложим переключиться в моно
    bool forceMono = reg02h & RDA5807M_FLG_MONO;
    forceMono = lcd.selectVal("Force mono", listOffOn, 2, forceMono);
    if (forceMono) reg02h |=  RDA5807M_FLG_MONO;
    else           reg02h &= ~RDA5807M_FLG_MONO;
    setRegister(RDA5807M_REG_CONFIG, reg02h);
    updateCaption(mkForceMono, "Force mono (%s)", listOffOn[forceMono]);
  }
  else if (selectedMenuItem == mkSoftMute) { // Предложим включить softmute
    bool softMute = reg04h & RDA5807M_FLG_SOFTMUTE;
    softMute = lcd.selectVal("Soft mute", listOffOn, 2, softMute);
    if (softMute) reg04h |=  RDA5807M_FLG_SOFTMUTE;
    else          reg04h &= ~RDA5807M_FLG_SOFTMUTE;
    setRegister(RDA5807M_REG_DEEMPH, reg04h);
    updateCaption(mkSoftMute, "Soft mute (%s)", listOffOn[softMute]);
  }
  else if (selectedMenuItem == mkSoftBlend) { // Предложим включить softblend
    bool softBlend = reg07h & RDA5807M_FLG_SOFTBLEND;
    softBlend = lcd.selectVal("Soft blend", listOffOn, 2, softBlend);
    if (softBlend) reg07h |=  RDA5807M_FLG_SOFTBLEND;
    else           reg07h &= ~RDA5807M_FLG_SOFTBLEND;
    setRegister(RDA5807M_REG_THRESH, reg07h);
    updateCaption(mkSoftBlend, "Soft blend (%s)", listOffOn[softBlend]);
  }
  else if (selectedMenuItem == mkSoftBlendThreshold) { // Изменить порог softblend
    uint16_t threshold = (reg07h & RDA5807M_SOFTBLENDTH_MASK) >> RDA5807M_SOFTBLENDTH_SHIFT;
    threshold = lcd.inputVal<uint16_t>("Input blend theshold", 0, 31, threshold);
    reg07h &= ~RDA5807M_SOFTBLENDTH_MASK;
    reg07h |= (threshold << RDA5807M_SOFTBLENDTH_SHIFT);
    setRegister(RDA5807M_REG_THRESH, reg07h);
    updateCaption(mkSoftBlendThreshold, "Soft blend threshold (%s)", String(threshold).c_str());
  }
  else if (selectedMenuItem == mkNewDemodulation) { // Предложим включить новый метод демодуляции
    bool newDemodulation = reg02h & RDA5807M_FLG_NEW;
    newDemodulation = lcd.selectVal("New demodulation", listOffOn, 2, newDemodulation);
    if (newDemodulation) reg02h |=  RDA5807M_FLG_NEW;
    else                 reg02h &= ~RDA5807M_FLG_NEW;
    setRegister(RDA5807M_REG_CONFIG, reg02h);
    updateCaption(mkNewDemodulation, "New demodulation (%s)", listOffOn[newDemodulation]);
  }
  else if (selectedMenuItem == mkSeekThreshold) { // Изменить порог для поиска
    uint16_t threshold = (reg05h & RDA5807M_SEEKTH_MASK) >> RDA5807M_SEEKTH_SHIFT;
    threshold = lcd.inputVal<uint16_t>("Input seek theshold", 0, 15, threshold);
    reg05h &= ~RDA5807M_SEEKTH_MASK;
    reg05h |= (threshold << RDA5807M_SEEKTH_SHIFT);
    setRegister(RDA5807M_REG_VOLUME, reg05h);
    updateCaption(mkSeekThreshold, "Seek threshold (%s)", String(threshold).c_str());
  }
  else if (selectedMenuItem == mkSaveSettings) { // Сохранить настройки в EEPROM
    EEPROM.put(EEPROM_START_ADDRESS, reg02h);
    EEPROM.put(EEPROM_START_ADDRESS + 2, reg03h);
    EEPROM.put(EEPROM_START_ADDRESS + 4, reg04h);
    EEPROM.put(EEPROM_START_ADDRESS + 6, reg05h);
    EEPROM.put(EEPROM_START_ADDRESS + 8, reg07h);
    lcd.printMultiline("Settings have been saved");
  }
}

void seekStation(bool UP){
  if (UP) 
    reg02h |= RDA5807M_FLG_SEEKUP;
  else
    reg02h &= ~RDA5807M_FLG_SEEKUP;  
  setRegister(RDA5807M_REG_CONFIG, reg02h | RDA5807M_FLG_SEEK);
  Searching = true;      
}

void readEEPROM(){
  EEPROM.get(EEPROM_START_ADDRESS, reg02h);
  if ((reg02h == 255) or !(reg02h & RDA5807M_FLG_ENABLE) or 
     !(reg02h & RDA5807M_FLG_DHIZ) or !(reg02h & RDA5807M_FLG_DMUTE) or
      (reg02h & RDA5807M_FLG_RESET)) {
    // В EEPROM что-то не то. Установим настройки по умолчанию
    reg02h = 0xC001;
    reg03h = 0x00;
    reg04h = 0x0800;
    reg05h = 0x88C1;
    reg07h = 0x42C6;
  }
  else {
    EEPROM.get(EEPROM_START_ADDRESS + 2, reg03h);
    EEPROM.get(EEPROM_START_ADDRESS + 4, reg04h);
    EEPROM.get(EEPROM_START_ADDRESS + 6, reg05h);
    EEPROM.get(EEPROM_START_ADDRESS + 8, reg07h);
  }
  setRegister(RDA5807M_REG_CONFIG, reg02h);
  setRegister(RDA5807M_REG_TUNING, (reg03h & RDA5807M_CHAN_MASK) ? reg03h | RDA5807M_FLG_TUNE : reg03h);

  setRegister(RDA5807M_REG_DEEMPH, reg04h);
  setRegister(RDA5807M_REG_VOLUME, reg05h);
  setRegister(RDA5807M_REG_THRESH, reg07h);
  Freq = 87 + double((reg03h & RDA5807M_CHAN_MASK) >> RDA5807M_CHAN_SHIFT) / 10;
  NeedRepaint = true;
}


void setRegister(uint8_t reg, const uint16_t value) {
  Wire.beginTransmission(RDA5807M_RANDOM_ACCESS_ADDRESS);
  Wire.write(reg);
  Wire.write(highByte(value));
  Wire.write(lowByte(value));
  Wire.endTransmission(true);
}

uint16_t getRegister(uint8_t reg) {
  uint16_t result;
  Wire.beginTransmission(RDA5807M_RANDOM_ACCESS_ADDRESS);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(RDA5807M_RANDOM_ACCESS_ADDRESS, 2, true);
  result = (uint16_t)Wire.read() << 8;
  result |= Wire.read();
  return result;
}

RDA5807M.h

#define RDA5807M_RANDOM_ACCESS_ADDRESS 0x11
#define RDA5807M_SERIAL_ACCESS_ADDRESS 0x10

#define MAX_CHAN 108-87 * 10 // для band = 87..108МГц и step = 100кГц

#define RDA5807M_REG_CHIPID 0x00
#define RDA5807M_REG_CONFIG 0x02
#define RDA5807M_REG_TUNING 0x03
#define RDA5807M_REG_DEEMPH 0x04
#define RDA5807M_REG_VOLUME 0x05
#define RDA5807M_REG_THRESH 0x07
#define RDA5807M_REG_STATUS1 0x0A
#define RDA5807M_REG_STATUS2 0x0B

uint16_t reg02h, reg03h, reg04h, reg05h, reg07h, reg0Ah;
// 02h
#define RDA5807M_FLG_DHIZ 0x8000
#define RDA5807M_FLG_DMUTE 0x4000
#define RDA5807M_FLG_MONO 0x2000
#define RDA5807M_FLG_BASS 0x1000
#define RDA5807M_FLG_SEEKUP 0x0200
#define RDA5807M_FLG_SEEK 0x0100
#define RDA5807M_FLG_SKMODE word(0x0080)
#define RDA5807M_FLG_RDS word(0x0008)
#define RDA5807M_FLG_NEW word(0x0004)
#define RDA5807M_FLG_RESET word(0x0002)
#define RDA5807M_FLG_ENABLE word(0x0001)
// 03h
#define RDA5807M_FLG_DIRECT word(0x0020)
#define RDA5807M_FLG_TUNE word(0x0010)
#define RDA5807M_CHAN_MASK 0xFFC0
#define RDA5807M_CHAN_SHIFT 6
#define RDA5807M_BAND_MASK word(0x000C)
#define RDA5807M_BAND_SHIFT 2
#define RDA5807M_SPACE_MASK word(0x0003)
// 04h
#define RDA5807M_FLG_DE 0x0800
#define RDA5807M_FLG_SOFTMUTE 0x0200
#define RDA5807M_FLG_AFCD 0x0100
// 05h
#define RDA5807P_FLG_INTMODE 0x8000
#define RDA5807M_SEEKTH_MASK 0x0F00
#define RDA5807M_SEEKTH_SHIFT 8
#define RDA5807M_LNASEL_MASK word(0x00C0)
#define RDA5807M_LNASEL_SHIFT 6
#define RDA5807M_VOLUME_MASK word(0x000F)
// 07h
#define RDA5807M_SOFTBLENDTH_MASK 0x7C00
#define RDA5807M_SOFTBLENDTH_SHIFT 10
#define RDA5807M_FLG_65M_50M 0x0200
#define RDA5807M_SEEKTHOLD_MASK word(0x00FC)
#define RDA5807M_SEEKTHOLD_SHIFT 2
#define RDA5807M_FLG_SOFTBLEND word(0x0002)
#define RDA5807M_FLG_FREQMODE word(0x0001)
// 0Ah
#define RDA5807M_FLAG_RDSR 0x8000
#define RDA5807M_FLAG_STC 0x4000
#define RDA5807M_FLAG_SF 0x2000
#define RDA5807M_FLAG_RDSS 0x1000
#define RDA5807M_FLAG_BLKE 0x0800
#define RDA5807M_FLAG_ST 0x0400
#define RDA5807M_READCHAN_MASK 0x03FF
// 0Bh
#define RDA5807M_RSSI_MASK 0xFE00
#define RDA5807M_RSSI_SHIFT 9
#define RDA5807M_FLG_FMTRUE 0x0100
#define RDA5807M_FLG_FMREADY word(0x0080)
#define RDA5807M_FLG_ABCD_E word(0x0010)
#define RDA5807M_BLERA_MASK word(0x000C)
#define RDA5807M_BLERA_SHIFT 2
#define RDA5807M_BLERB_MASK word(0x0003)

19 (2023-08-21 13:28:54 отредактировано Hromas2006)

Re: Радио RDA5807M

liman324 добрый день,я не очень силен в написании прошивок, но хочу уточнить.а вообще сложно переделать это радио на дисплей олед 1,3 дюйма на контроллере SH1106 I2C,перерыл много схем,но по функционалу нет хороших прошивок,а те что описаны что не плохие,тупо либо не работают либо не компилируются с кучей ошибок .....просто нужно радио с маленьким дисплеем в новом моем усилителе будет три устройства ,радио - веб радио - блютус модуль и аудиопроцессор,так как все это будет собрано на 2х ардуинах и esp32 то хочу уместить по размерам в место под дисплей, поставив 3 олед дисплея рядышком и под стеклом не будет видно что их 3 там стоит

20

Re: Радио RDA5807M

Я подумаю над этим вопросом. Но если займусь то буду делать на основе http://rcl-radio.ru/?p=53149, только кнопки поменяю на энкодер.

21

Re: Радио RDA5807M

так это еще лучше будет

22

Re: Радио RDA5807M

Предварительное тестирование

OLED 1.3 SH1106 I2C
Encoder D8 D9

#define FIX_BAND    RADIO_BAND_FM  

#include <Wire.h>
#include <radio.h>             // http://rcl-radio.ru/wp-content/uploads/2023/08/radio.zip
#include <RDA5807M.h>          // http://rcl-radio.ru/wp-content/uploads/2023/08/RDA5807-master.zip
#include <RDSParser.h>         // >> radio.h
#include <MsTimer2.h>          // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <Encoder.h>           // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip 
#include <U8glib.h>            // https://github.com/olikraus/u8glib/
#include <EEPROM.h>

RDA5807M radio; 
RADIO_INFO info;
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);  // Dev 0, Fast I2C / TWI
Encoder myEnc(9, 8);// DT, CLK

int v_pos,menu,vol;
float f=10190; //8810 10190
long oldPosition  = -999,newPosition, times,times1;
bool w,w2;
int z;


void setup(){
  delay(300);
  Wire.begin();
  vol=EEPROM.read(0);
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  Serial.begin(9600);
  radio.init();
  radio.debugEnable();
  radio.setBandFrequency(FIX_BAND, f);
  radio.setVolume(vol);
  radio.setMono(false);
  radio.setMute(false);
  u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);
  u8g.drawStr(40,20,"RDA5807M");
  u8g.drawStr(40,50,"RADIO FM");
  } 
  while( u8g.nextPage() );
  delay(100);
  }

void loop(){
   
  if(menu==0){// ГРОМКОСТЬ
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
    vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;if(vol>15){vol=15;}if(vol<0){vol=0;}radio.setVolume(vol);Serial.println(vol);}
 
    u8g.firstPage();do {
    u8g.setFont(u8g_font_profont29r);u8g.setPrintPos(5, 20);u8g.print(f/100);  
    u8g.setFont(u8g_font_profont12r);u8g.drawStr(110,20,"MHz"); 
    u8g.drawLine(0, 25, 128, 25);  
    u8g.drawStr(0,40,"VOLUME");for(int v_pos=0; v_pos<vol*4+1;v_pos+=4){u8g.drawBox(v_pos+53,32, 2, 8);}
    u8g.drawLine(0, 46, 128, 46); 
   if(millis()-times1>1000){ 
    radio.getRadioInfo(&info);
    u8g.setPrintPos(0, 60);u8g.print(info.rssi);u8g.drawStr(15,60,"dBm |");
    u8g.drawStr(50,60,info.tuned  ? "TUNED"  : "-----");
    u8g.drawStr(80,60,info.stereo ? " STEREO  " : "  MONO   ");
    times1-millis();}}
  while( u8g.nextPage() );
    }
  
   
  
 delay(10);

 if(millis()-times>5000 && w==1){EEPROM.update(0,vol);}
 }  


void to_Timer(){newPosition = myEnc.read()/4;} 

23 (2023-08-24 00:14:32 отредактировано Hromas2006)

Re: Радио RDA5807M

ух....все работает радио играет, пришлось правда частоту поменять  ,громкость регулируется ....хотя мне громкость надо просто раз выставить и все ....остальное будет идти через аудио проц,а заместо шкалы громкости можно рдс пустить,ну или предусмотреть в прошивке строчку с выставлением начальной громкости, если кому надо,можно использовать или то или то,в идеале нужны примерно такие менюшки, допустим
1. меню.....  частота станции,  уровень сигнала,в общем как счас есть только шкала регулировки громкости с заменой на рдс бегущей строкой через допустим 10сек бездействия.
остальные меню оставить как было в пред. версии  ну или что то подобное той версия которая только с IR приемником,с автонастройкой и ручной настройкой, мне очень понравилась по функционалу ,и менюшки  автоматом возвращаются на 1 меню через какое то время,еще желательно сделать IR приемник для пульта,хотя бы просто листание станций.
http://forum.rcl-radio.ru/uploads/images/2023/08/7653a23c731465ef84b7e4fa0c915c6b.jpg

24

Re: Радио RDA5807M

Я сначала сделаю проект для сайта, а после изменю его под Ваши пожелания.

Кнопка D2 запускает дополнительное меню
1. Авто сканирование, для запуска нажать кнопку энкодера, по завершению сканирования выход в меню выбора канала
2. Ручная подстройка частоты выбранного канала
3 нажатие выход в меню громкости

Основное меню (нажатие кнопки энкодера)
1. Регулировка громкости
2. Выбор канала

Кнопка D3 - POWER OFF
выход D4 - выход STANDBY для управления усилителем

#define FIX_BAND    RADIO_BAND_FM  
#define RSS 25
#define DELAY_CH 500

#include <Wire.h>
#include <radio.h>             // http://rcl-radio.ru/wp-content/uploads/2023/08/radio.zip
#include <RDA5807M.h>          // http://rcl-radio.ru/wp-content/uploads/2023/08/RDA5807-master.zip
#include <RDSParser.h>         // >> radio.h
#include <MsTimer2.h>          // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip 
#include <Encoder.h>           // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip 
#include <U8glib.h>            // https://github.com/olikraus/u8glib/
#include <EEPROM.h>

RDA5807M radio; 
RADIO_INFO info;
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);  // Dev 0, Fast I2C / TWI
Encoder myEnc(9, 8);// DT, CLK

int v_pos,menu,vol,f0,f_scan[10],k,i1=8700,i;
float f;
long oldPosition  = -999,newPosition, times, times1;
bool w,w2,t, power;
byte start1,start;
int z;


void setup(){
  delay(300);
  Wire.begin();
  if(EEPROM.read(300)!=0){for(int i=0;i<301;i++){EEPROM.update(i,0);}}
  vol=EEPROM.read(0);
  for(int c=0;c<10;c++){f_scan[c]=EEPROM.read(10+c)*100+EEPROM.read(100+c);}
  k=EEPROM.read(3);
  f=EEPROM.read(1)*100+EEPROM.read(2);start=0;
  pinMode(10,INPUT);        // encoder SW
  pinMode(2,INPUT_PULLUP); // КНОПКА SET 
  pinMode(3,INPUT_PULLUP); // КНОПКА POWER  
  pinMode(4,OUTPUT);       // OUT STANDBY
  MsTimer2::set(1, to_Timer);MsTimer2::start();
  Serial.begin(9600);
  radio.init();
  radio.debugEnable();
  radio.setBandFrequency(FIX_BAND, f);
  radio.setVolume(vol);
  radio.setMono(false);
  radio.setMute(false);
  u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);
  u8g.drawStr(40,20,"RDA5807M");
  u8g.drawStr(40,50,"RADIO FM");
  } 
  while( u8g.nextPage() );
  delay(2000);
  }

void loop(){
  if(start==0){radio.setBandFrequency(FIX_BAND, f);delay(400);radio.getRadioInfo(&info);start=1;}
//////////////////////////////////////////////////////////////////////////////////////////////////  
  if(digitalRead(10)==LOW && menu<2){menu++;if(menu>1){menu=0;}w=1;w2=1;delay(200);}
  if(digitalRead(2)==LOW && menu<2){menu=2;times=millis();w=1;w2=1;delay(200);}
  if(digitalRead(2)==LOW && menu==2){menu=3;times=millis();times1=millis()-10000;w=1;w2=1;delay(200);}
  if(digitalRead(2)==LOW && menu==3){menu=0;times=millis();w=1;w2=1;delay(200);}

  if(digitalRead(3)==LOW && power==0){power=1;radio.setMute(true);digitalWrite(4,LOW);
    u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);u8g.drawStr(40,30,"POWER OFF");}
    while( u8g.nextPage() );menu=100;delay(1000);u8g.firstPage();do {} while( u8g.nextPage() );}
  if(digitalRead(3)==LOW && power==1){power=0;radio.setMute(false);menu=0;digitalWrite(4,HIGH);delay(200);}
  
//////////////////////////////////////////////////////////////////////////////////////////////////   
  if(menu==0){ // ГРОМКОСТЬ
   if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
    vol=vol+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;if(vol>15){vol=15;}if(vol<0){vol=0;}radio.setVolume(vol);Serial.println(vol);}
 
    u8g.firstPage();do {
    u8g.setFont(u8g_font_profont29r);u8g.setPrintPos(5, 20);u8g.print(f/100);  
    u8g.setFont(u8g_font_profont12r);u8g.drawStr(110,20,"MHz"); 
    u8g.drawLine(0, 25, 128, 25);  
    u8g.drawStr(0,40,"VOLUME");for(int v_pos=0; v_pos<vol*4+1;v_pos+=4){u8g.drawBox(v_pos+53,32, 2, 8);}
    u8g.drawLine(0, 46, 128, 46); 
    radio.getRadioInfo(&info);
    u8g.setPrintPos(0, 60);u8g.print(info.rssi);u8g.drawStr(15,60,"dBm |");
    u8g.drawStr(50,60,info.tuned  ? "TUNED"  : "-----");
    u8g.drawStr(80,60,info.stereo ? " STEREO  " : "  MONO   ");
    }
  while( u8g.nextPage() );
    }
////////////////////////////////////////////////////////////////////////////////////////
   if(menu==1){ // КАНАЛЫ 
    if(start1==0){f=f_scan[k];start=0;start1=1;radio.setBandFrequency(FIX_BAND, f);}
    if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
      k=k+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w2=1;if(k>9){k=9;}if(k<0){k=0;}times=millis();start=0;f=f_scan[k];}
    
    u8g.firstPage();do { 
    if(f_scan[k]!=0){u8g.setFont(u8g_font_profont29r);u8g.setPrintPos(5, 20);u8g.print((float)f_scan[k]/100); 
      u8g.setFont(u8g_font_profont12r);u8g.drawStr(110,20,"MHz");}
        else{u8g.setFont(u8g_font_profont17r);u8g.drawStr(45, 18,"N/A");}
    u8g.drawLine(0, 25, 128, 25);  u8g.setFont(u8g_font_profont12r);
    u8g.drawStr(0,40,"CHANNEL");u8g.setPrintPos(80, 40);u8g.print(k+1); 
    u8g.drawLine(0, 46, 128, 46); 
    radio.getRadioInfo(&info);
    u8g.setPrintPos(0, 60);u8g.print(info.rssi);u8g.drawStr(15,60,"dBm |");
    u8g.drawStr(50,60,info.tuned  ? "TUNED"  : "-----");
    u8g.drawStr(80,60,info.stereo ? " STEREO  " : "  MONO   ");
    }
  while( u8g.nextPage() );
   }   
/////////////////////////////////////////////////////////////////////////////////////////
    if(menu==2){// АВТО ПОИСК КАНАЛОВ
     if(digitalRead(10)==LOW){
     for(int i=10;i<301;i++){EEPROM.update(i,0);}
     for(int c=0;c<10;c++){f_scan[c]=EEPROM.read(10+c)*100+EEPROM.read(100+c);}
     for(i=0;i<10;i++){
     for(i1;i1<=10800;i1=i1+10){
      radio.setBandFrequency(FIX_BAND, i1);delay(DELAY_CH);
      radio.getRadioInfo(&info);
    if(info.tuned==1 and info.rssi>RSS){f_scan[i]=i1;f0=f_scan[i];i1=f_scan[i]+10;
    EEPROM.update(10+i,f_scan[i]/100);EEPROM.update(100+i,f_scan[i]-(f_scan[i]/100)*100);
    if(i1>=10800){f_scan[i]=0;}break;}  
    u8g.firstPage();do {  
    u8g.setFont(u8g_font_profont29r);u8g.setPrintPos(5, 20);u8g.print((float)i1/100);  
    u8g.setFont(u8g_font_profont12r);u8g.drawStr(110,20,"MHz");
    u8g.drawLine(0, 25, 128, 25);
    u8g.drawStr(5,40,"CH");u8g.setPrintPos(20, 40);u8g.print(i); 
    u8g.setFont(u8g_font_profont12r);u8g.setPrintPos(50, 40);u8g.print((float)f0/100);u8g.drawStr(110,40,"MHz");
    u8g.drawLine(0, 46, 128, 46); 
    u8g.setPrintPos(0, 60);u8g.print(info.rssi);u8g.drawStr(15,60,"dBm |");
    u8g.drawStr(50,60,info.tuned  ? "TUNED"  : "-----");
    u8g.drawStr(80,60,info.stereo ? " STEREO  " : "  MONO   ");
      }
 while( u8g.nextPage() );
  }}
 delay(1000);times=millis();i1=8700;k=0;start1=0;menu=1;}
    u8g.firstPage();do {  
    u8g.setFont(u8g_font_profont12r);
    u8g.drawStr(40,20,"AUTOSCAN");
    u8g.drawStr(30,40,"PRESS BUTTON");
    }while( u8g.nextPage() );
}     
////////////////////////////////////////////////////////////////////////////////////////// 
 if(menu==3){// ПОДСТРОЙКА ЧАСТОТЫ КАНАЛА
    if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;}
      f=f+newPosition*10;myEnc.write(0);newPosition=0;times=millis();t=1;w=1;w2=1;if(f<8700){f=8700;}if(f>10800){f=10800;}times1=millis();start=0;}
    u8g.firstPage();do {  
    u8g.setFont(u8g_font_profont29r);u8g.setPrintPos(5, 20);u8g.print(f/100);  
    u8g.setFont(u8g_font_profont12r);u8g.drawStr(110,20,"MHz"); 
    u8g.drawLine(0, 25, 128, 25);  
    if(millis()-times1<1000){u8g.drawStr(50,40,"SAVE");}
      else{u8g.drawStr(15,40,"FREQUENCY TUNING");}
    u8g.drawLine(0, 46, 128, 46); 
    u8g.setPrintPos(0, 60);u8g.print(info.rssi);u8g.drawStr(15,60,"dBm |");
    u8g.drawStr(50,60,info.tuned  ? "TUNED"  : "-----");
    u8g.drawStr(80,60,info.stereo ? " STEREO  " : "  MONO   ");
    if(t==1){f_scan[k]=f;t=0;EEPROM.update(10+k,f_scan[k]/100);EEPROM.update(100+k,f_scan[k]-(f_scan[k]/100)*100);}
      }
 while( u8g.nextPage() );
  }
  
 delay(10);
 if(millis()-times>5000 && w==1){EEPROM.update(0,vol);EEPROM.update(3,k);EEPROM.update(1,f_scan[k]/100);EEPROM.update(2,f_scan[k]-(f_scan[k]/100)*100);w=0;}
 }  
 
void to_Timer(){newPosition = myEnc.read()/4;} 

25 (2023-08-25 19:45:09 отредактировано Hromas2006)

Re: Радио RDA5807M

добрый вечер iman324 ,все работает как положено,правда сначала кнопки с резисторами поставил,оно постоянно включалось отключалось,поменял на кнопки без резисторов,все заработало,в меню переходит,на D4 во включенном состоянии +5 вольт в повер офф 0 вольт.автонастройка работает четко,причем по моему чувствительность лучше стала,так как некоторые станции у меня не ловятся вообще,а здесь отловило аж 3 штуки. причем их и муз центр в упор не видит....единственное но, всего 10 станций,у меня с этим проблемы так как у нас ловится укв+фм порядка 18 станций ....и до фм просто не доходит ,7 шт только на укв диапазоне ,и на 94 мгц какая то несущая частота сидит и 3 раза радио ее ловит,а ручной настройки и выставление на каналы как в варианте с IR еще нет .....в остальном глюков вроде нет,гонял около часа туда сюда,четко работают кнопки и энкодер,все хорошо smile  http://forum.rcl-radio.ru/uploads/images/2023/08/ab721a07060a0b79dcb7da09be777d34.jpg