Практически все функциональные возможности микросхемы 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.
Если этот текст читают студенты изучающие курс «Радиоприемные устройства», напишите в комментариях, по каким российским учебникам сейчас изучается эта наука и какие микросхемы используются при выполнении лабораторных работ. Очень интересно почитать современные учебные материалы.
Спасибо всем, кто дочитал до конца.
