Практически все функциональные возможности микросхемы RDA5807M реализованы в примерах ардуиновских библиотек Radio от Matthias Hertel и PU2CLR_RDA5807 от Ricardo Lima Caratti. Обе ищутся и устанавливаются в IDE.
Меня интересовала в основном реализация RDS, но не устраивало большое количество кнопок управления (не менее 4-х), так как в основном я ориентировался на управление энкодером. Просмотрев все примеры, я обратился к поиску радиоприемников, ориентируясь только на те модули, которые были у меня: модуль RDA5807M c кварцем, OLED SSD1306 128х64 синий с желтой верхней полосой, энкодер TZT и Arduino Nano (далее МК). Варианты с дополнительными кнопками, как в примерах библиотек, не рассматривались. В результате я остановился на двух вариантах. Первый.
Схемы подключения модулей приемника и дисплея стандартные — это шина I2C, организованная на выводах А4 и А5 МК; D2, D3, D4 для энкодера. Для написания кода я использовал в основном DeepSeek (далее просто чат-бот). Grok и YandexGPT применялясь от случая к случаю, об этом ниже. Выбор был основан в основном на доступности без бальных танцев из-за блокировок. Правда, совсем без танцев не обошлось, а решилось совсем просто. Ну, вы поняли, о чем речь.
Описал первое задание и боты взялись за дело. Конечно, с первого раза ничего путного не получилось и со второго тоже. Дело пошло лучше, когда я стал использовать диалоги, подбрасывая в диалог сообщения об ошибках компиляции. В результате получил более-менее работающий код, но с одним недостатком. На дисплей не выводилась кириллица. Чат-боты печатают очередную итерацию, но становится только хуже. В какой-то момент Arduino IDE написала мне, что для шрифтов не хватает памяти МК. Тут я понял, что надо остановиться — дело зашло в тупик.
На примете у меня давно была конструкция приемника О.В. Полякова и тут я отвел душу. Заработало что называется «из коробки». После консультаций с автором в чате, внес всего изменения — свою предустановленную частоту и задержку в 2 секунды на инициализацию RDA5807M. Последнее скорее вызвано тем, что у меня все компоненты и в первую очередь МК так называемые noname.
И вот тут я столкнулся лицом к лицу c RDS в том виде, как его понимают местные вещатели. То есть с его отсутствием. На паре радиостанций эта система работает, передает свое название и номер телефона для рекламы. И все. В общем ожидания не оправдались. Переходим ко второму варианту.
Постоянно я слушаю две радиостанции, еще пару от случая к случаю. Следовательно дисплей мне не нужен вообще. Немного подумав, я решил, что будет достаточно одного СИД и одной кнопки. При включении приемника он устанавливается на первую частоту; СИД мигает один раз в две секунды. Нажимаем кнопку, приемник переключается на вторую частоту, СИД мигает два раза с интервалом 2 секунды. И так далее.
Я описал это все на русском языке и отправил чат-боту. Получил что-такое неработающее даже после третьей итерации, а к пятой дело пошло к бреду. Тогда переформулировал задание, что далось с некоторым трудом — утратились навыки такой технической писанины. А для чистоты эксперимента сделал автоматический перевод на английский.
Новый чат и … я получаю работающий код с первого раза! Замечаю только одну ошибку: СИД работает с инверсией — вместо вспышек гаснет заданное число раз с заданным интервалом. Меняю подключение и все. Вот такой код получился.
Скрытый текст
/*
* Arduino Nano Radio Controller for RDA5807M
*
* Libraries:
* - RDA5807M (https://github.com/mathertel/Radio) v3.0.1
* - Wire (built-in) for I2C communication
*
* Connections:
* - RDA5807M:
* SDA -> A4
* SCL -> A5
* VCC -> 3.3V
* GND -> GND
* - Button:
* One side -> D2 and D2 with resistor 10k to +3.3V
* Other side -> GND
* - LED:
* Anode -> D4
* Cathode -> GND (with appropriate current-limiting resistor)
*/
#include <Arduino.h>
#include <Wire.h>
#include <radio.h>
#include <RDA5807M.h>
// Pin definitions
#define BUTTON_PIN 2
#define LED_PIN 4
// Radio frequencies (in MHz)
const float PRESET_FREQS[] = {100.6, 104.6, 102.1, 107.2};
const int PRESET_COUNT = sizeof(PRESET_FREQS) / sizeof(PRESET_FREQS[0]);
// Radio settings
#define VOLUME_LEVEL 10
#define BASS_BOOST false
// LED patterns
const unsigned long LED_INTERVAL = 2000; // 2 second
const unsigned long LED_DURATION = 200; // 200 ms on/off
// Variables
RDA5807M radio;
int currentPreset = 0;
unsigned long lastButtonPress = 0;
unsigned long lastLedUpdate = 0;
int ledState = LOW;
int blinkCount = 0;
int blinkStep = 0;
void setup() {
// Initialize serial for debugging
Serial.begin(9600);
while (!Serial);
// Initialize pins
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
// Delay for receiver initialization
delay(1000);
// Initialize radio
Wire.begin();
if (!radio.initWire(Wire)) {
Serial.println("Radio init failed!");
while (1);
}
// Set radio parameters
radio.setVolume(10);
radio.setBassBoost(BASS_BOOST);
radio.setMono(false);
radio.setMute(false);
// Set initial frequency
radio.setFrequency(PRESET_FREQS[currentPreset] * 100);
Serial.print("Tuned to: ");
Serial.print(PRESET_FREQS[currentPreset]);
Serial.println(" MHz");
}
void loop() {
// Handle button press for frequency change
if (digitalRead(BUTTON_PIN) == LOW&& millis() - lastButtonPress > 400) {
lastButtonPress = millis();
currentPreset = (currentPreset + 1) % PRESET_COUNT;
radio.setFrequency(PRESET_FREQS[currentPreset] * 100);
Serial.print("Tuned to: ");
Serial.print(PRESET_FREQS[currentPreset]);
Serial.println(" MHz");
// Reset LED timing
lastLedUpdate = millis();
blinkStep = 0;
}
// Handle LED blinking pattern based on current preset
unsigned long currentTime = millis();
if (currentTime - lastLedUpdate >= LED_INTERVAL) {
lastLedUpdate = currentTime;
blinkStep = 0;
blinkCount = currentPreset + 2; // Number of blinks (1 for first freq, 2 for second, etc.)
}
if (blinkStep < blinkCount * 2) {
if (blinkStep % 2 == 0) {
// LED on
if (ledState == LOW) {
ledState = HIGH;
digitalWrite(LED_PIN, ledState);
}
} else {
// LED off
if (ledState == HIGH) {
ledState = LOW;
digitalWrite(LED_PIN, ledState);
}
}
if (currentTime - lastLedUpdate >= (blinkStep * LED_DURATION)) {
blinkStep++;
}
} else {
// Keep LED off between patterns
if (ledState == HIGH) {
ledState = LOW;
digitalWrite(LED_PIN, ledState);
}
}
}
Немного изменил комментарии и все. Дальше были опыты с другими чат-ботами. Я давал им задание на написание кода, меняя только язык. Grok справился с заданием, но допустил ошибки с версией библиотеки Radio и параметрами инициализации приемника, а с YandexGPT ничего путного не получилось ни в английском варианте задания, ни в русском.
Примерно через пару недель я дал чат-боту точно такое же задание, как в случае, когда он выдал мне рабочий код. Каково же было мое удивление, когда я получил совершенно другой код; совпали только комментарии в шапке. Сравнил два кода в NotePad++ и вот что получилось.

Как видите различия большие. При компиляции выдавалась одна ошибка. Я исправил ее вручную и попробовал загрузить. Скомпилировалось, загрузилось и ничего не работало.
Общее впечатление от общения с чат-ботами у меня сложилось такое. Задание для простых задач боты выполняют с первого раза. Для более сложных задач нужно очень тщательно писать задание и желательно на английском языке. Надеюсь, когда-нибудь боты станут настолько умными, что в ответ будут писать словами персонажа известного фильма: - Ну барин, ты задачи ставишь! Тут гомо сапиенс нужен!
Технические проблемы
Модуль приемника можно питать как от стороннего источника +3 … 3,3 В, так и от вывода МК. В последнем случае надо ставить конденсатор 22 … 100 мкФ, так как это напряжение идет от микросхемы CH340.
В качестве антенны у меня был кусочек провода 10 см длиной. Прием был отличный. Как только я подключил конструкцию к аккумулятору, прием резко ухудшился. Касаюсь рукой корпуса разъема USB на МК — прием резко улучшается. В даташите RDA5807M на антенном входе стоит паралельный контур на 102 МГц, а на звуковых выходах FM-фильтры.

Это для того, чтобы в качестве антенны работал общий провод кабеля наушников. Я их не использую, а хороший прием получился с обычной антенной.
Пока занимался общением с чат-ботами, я не особо обращал внимание на качество звука; играет без шипения и ладно. В процессе изучения опыта применения RDA5807M мне часто попадались комментарии типа «не работает», «сгорела через пару часов» и т. д. В какой-то момент я обратил внимание, что звук в одном канале заметно тише. Включил осциллограф и обнаружил вот такую картину.

Выходное напряжение одного из каналов ограничено снизу. При этом уровни смещения в обеих каналах были одинаковыми примерно 0,9 В. Так бывает, если в двухтактном выходном каскаде нижний транзистор не работает. Тогда между выходом этого канала и общим проводом был включен резистор 2,7 кОм. Уровень смещения уменьшился примерно на 100 мВ, а форма сигнала полностью восстановилась.

Конечно, наушники такой выход не потянет, но с внешним усилителем работает.
Заключение
Микросхема RDA5807M привлекательна тем, что имеет низкую цену и имеет множество конструкций с большим разнообразием индикаторов и органов управления. Среди недостатков многие отмечают низкую надежность, слабую документацию и нестандартный конструктив под названием RRD-102 Ver 2.0. Хороший обзор проблем и возможностей этой микросхемы приведен на сайте радиолюбителя OE3HBW.
Если этот текст читают студенты изучающие курс «Радиоприемные устройства», напишите в комментариях, по каким российским учебникам сейчас изучается эта наука и какие микросхемы используются при выполнении лабораторных работ. Очень интересно почитать современные учебные материалы.
Спасибо всем, кто дочитал до конца.