Production
Разработка устройства от идеи до реализации заняла около 6 месяцев, что, с практически полным отсутствием опыта в данной области, не так уж и плохо. На данный момент у нас есть около 10 полностью собранных комплектов, которые включают в себя всё необходимое для сборки своего собственного устройства: — МК Atmega328P-PU — Преобразователь уровня CD4050BE — Дисплей Nokia 5110 — Приемник RDA5807M — Программатор USBasp — Операционный усилитель LM386N — Разъемы под МК и программатор — USB B, Audio Jack 3.5, три кнопки, провода, однорядные коннекторы — 11 резисторов и 12 конденсаторов, 4 индуктивности, кварц, стабилитрон и светодиод — Динамик — Печатная плата Для сборки понадобится припой, флюс и паяльник, больше ничего не нужно. Все комплектующие упакованы в небольшую коробку из «крафтового» картона: Исходники прошивки уже выложены на Github; Gerber-файл, принципиальная схема и инструкция по сборке будут также опубликованы позднее. Микросхема RDA5807M — это FM радиоприемник нового поколения с поддержкой RDS/RBDS и цифровым управлением по I2C. Микросхема выполнена по CMOS технологии, что определяет ее минимальное энергопотребление. RDA5807M уже содержит все необходимые узлы и требует лишь небольшого числа внешних компонентов. А мощный аудиопроцессор обеспечивает оптимальное качество звука при различных условиях приема. Все это делает RDA5807M удачным выбором для носимых, портативных устройств. В интернет магазинах распространен модуль RRD-102v2, на котором распаяны RDA5807M, кварцевый резонатор и пара компонентов обвязки. В данной статье я опишу как подключить этот модуль к Ардуино и что нужно знать для создания радиоприемника на его основе.
Приемник RDA5807
RDA5807 представляет собой однокристальный модуль (микросхему) FM стерео радиоприёмника с интегрированным в него синтезатором частоты. Модуль способен работать в диапазоне частот 50 – 115 МГц, обеспечивать управление уровнем громкости и владеть информацией об уровне принимаемого сигнала. Модуль содержит кварцевый генератор на 32.768 КГц, цифровой усилитель и другие компоненты. Структурная схема модуля RDA5807M представлена на следующем рисунке.
Модуль построен на цифровой архитектуре и включает малошумящий усилитель, работающий в диапазоне от 50 до 115 МГц. Также модуль содержит программируемый усилитель на ПЛИСах (PGA), АЦП (аналого-цифровой преобразователь) высокого разрешения и высокоточный ЦАП (цифро-аналоговый преобразователь). Амплитудный ограничитель на входе модуля предотвращает его перегрузку (по уровню) и ограничивает число интермодуляционных составляющих, создаваемых соседними каналами. Усилитель на ПЛИСах усиливает входной сигнал, который затем преобразуется в цифровую форму с помощью АЦП. Ядро цифровой обработки сигналов модуля управляет выбором каналов, демодуляцией FM сигналов и разуплотнением стерео сигнала. Назначение контактов (распиновка) микросхемы RDA5807 представлено на следующем рисунке.
Питающее напряжение для модуля составляет от 1.8 до 3.3V. Подключить модуль RDA5807 к микроконтроллеру можно по интерфейсу I2C. Модуль имеет 13 16-битных регистров, каждый из которых выполняет свою определенную функцию. Адреса регистров начинаются с 00H и заканчиваются 0FH. Во всех 13 регистрах некоторые биты зарезервированы. Регистры выполняют такие функции как изменение уровня, смена канала и т.д.
Модуль проблематично использовать для подключения к нему соединительных проводов, поэтому мы использовали перфорированную плату, чтобы с ее помощью и олова сделать контакты для подключения проводов как показано на выше приведенном рисунке.
Предыстория
Я думаю, многие из вас не только слышали, но и непосредственно сталкивались с такой платформой, как Arduino. И как показывает моя личная статистика, очень немногие заходят дальше, чем поморгать светодиодами. Когда я познакомился с Arduino в первый раз, меня останавливало то, что не было идей, как именно я бы мог использовать все возможности того же UNO на «полную катушку». Хватило только на сборку простенького робота на двух колёсах и сигнализации. Вместе с тем, хотелось сделать что-то более основательное. Тогда я вспомнил о своем детстве, в котором были так называемые «радиоконструкторы». Суровый советский DIY Kit, который при правильной сборке и грамотной пайке даже начинал работать, и ловил радиостанции в различных диапазонах: Юность, Электрон-М и другие.
Ни один из таких Kit’ов мне не достался, зато достался ЭКОН-1:
Основной «фишкой» этого конструктора было то, что с его помощью можно было быстро и просто собрать большое количество различных устройств, от простых «пищалок» до вполне полноценного радиоприемника. ЭКОН-1 — одна из многих причин, по которой я вообще оказался в сфере IT. И мне пришло в голову, что было бы неплохо создать современную версию подобного конструктора, чтобы все желающие могли получить удовольствие от только что собранного своими руками девайса.
Прошивка
Отдельно стоит остановиться на прошивке. Она написана на C++ и мы распространяем её по лицензии GPLv3: https://github.com/xtremespb/fm_receiver.Я практически не разрабатывал на C/C++, поэтому (вероятно) код далёк от идеала и может содержать ошибки, но GPL на то и GPL, чтобы можно было его дорабатывать сообществом Текущие возможности прошивки включат в себя: — Ручную и автоматическую настройку станций — RDS — Управление громкостью — Включение режима усиленных басов — Включение и отключение подсветки дисплея — Отображение и динамическая визуализация уровня сигнала В следующей, четвёртой по счёту ревизии, мы сделаем ещё несколько полезных «фишек»: подключим левый и правый каналы к аналоговым входам на МК, что позволить «визуализировать» поступающий аудиосигнал. Кстати, возможности устройства не ограничиваются радио! Никто не мешает, например, написать какую-нибудь игру (интереса ради я сделал старый добрый Arkanoid) или другую программу, использующую возможности платы.
Заказ печатных плат
В Китае можно заказать печатные платы, выполненные промышленным способом. Стоимость выходит относительно небольшой даже при малых тиражах, а время ожидания (включая доставку) как правило не превышает 2-3 недель. Первую «партию» плат заказали на PCBWay. Так она выглядела: Одна из проблем, с которой мы по неопытности столкнулись: металлизация «съедает» значительную часть размера самого отверстия, поэтому некоторые компоненты с трудом «влезали» в нужные отверстия. При проектировании схемы необходимо учитывать этот момент. По результатам тестирования мы ещё немного доработали конструкцию, добавив несколько конденсаторов для более стабильной работы устройства. Собрали ещё один прототип: Разъём USB используется для питания приёмника. Питание также подаётся при подключении программатора. Всё работает!
Library Installation
The easiest method to install this library is via your Arduino IDE. All you have to do is:
- Select Tools menu;
- Select Manage Libraries option;
- In the text box (top windows), type PU2CLR or RDA5807;
- Select the PU2CLR RDA5807.
The images below show how you can install this library via your Arduino IDE from Manage Libraries tool.
Installing via the repository
With this approach, you will have the most current version of the library. However, it may not be the most stable version. This is because the current version is always in development. Prefer releases. Do you need some old version (release) of this library? If yes, check here.
First, you have to download this library in zip format.
After, unzip the RDA5807-master.zip file in your Arduino Library folder.
- On Windows: «My Documents\Arduino\libraries»
- On MAC OS: ˜/Documents/Arduino/libraries
- On Linux: ˜/Documents/Arduino/libraries
Характеристики RDA5807M
Сразу даю ссылку на даташит: RDA5807M_datasheet_v1.1, наиболее полную информацию о характеристиках RDA5807M вы можете найти в нем. Я перечислю некоторые из них:
- Напряжение питания 2.7 — 3.3В
- Потребляемый ток (при напряжении питания 3В):
- в рабочем режиме — не более 20мА
- в режиме сна — не более 15мкА
- Диапазон принимаемых частот 50 — 115МГц
- Выбираемый шаг изменения частоты: 200кГц, 100кГц, 50кГц, 25кГц
- Выбираемый источник тактового сигнала: внешний или внутренний генератор (для внутреннего генератора требуется резонатор 32.768кГц)
- Поддержка RDS/RBDS
- Управление по шине I2C
- Возможность прямого подключения нагрузки от 32Ом
Диапазон напряжения питания не самый удобный, например, от лития без стабилизации запитать не получится. Зато наушники можно подключать прямо к выводам микросхемы, дополнительное усиление не требуется. Также можно отметить небольшой потребляемый ток микросхемы, что позволяет запитывать ее от цифрового вывода микроконтроллера (по крайней мере AVR) в тех случаях, когда требуется отключение питания радио в целях энергосбережения.
Программирование RDA5807M
Давайте начнем с простенького скетча. Если вы попробуете управлять RDA5807M из моей программы, то обнаружите, что для того чтобы заставить его работать достаточно установить несколько битов: ENABLE, DHIZ, DMUTE, SEEK. Установка последнего запустит поиск радиостанции. Эти же действия можно выполнить программно при помощи следующего скетча:
voidsetup() { Wire.begin(); setRegister(0x02, 0xC101); } voidloop() { } void setRegister(uint8_t reg, const uint16_t value) { Wire.beginTransmission(0x11); Wire.write(reg); Wire.write(highByte(value)); Wire.write(lowByte(value)); Wire.endTransmission(true); }
Подключите RDA5807M к Ардуино по приведенной ранее схеме и залейте в нее скетч. Приемник выполнит поиск и настроится на первую найденную радиостанцию. Бит Tune при этом сбрасывается. Нажатие кнопки Reset на Ардуино и повторное выполнение функции setup будут снова устанавливать этот бит, инициируя поиск следующей станции. Работает? Двигаемся дальше. В примере скетча выше мы записали в регистр 02h заранее определенное значение. На деле такое требуется редко, разве что для инициализации некоторых регистров. В основном же значения регистров формируются в процессе работы программы при изменении отдельных битов. В таких случаях удобно использовать константы, содержащие номера этих битов или маски для их установки. Ниже приведен пример такого скетча. Он позволяет настроиться на конкретную радиостанцию, установить громкость и получить RSSI.
uint8_t volume = 1; uint16_t freq = 1073; uint16_t reg02h, reg03h, reg05h, reg0Bh; voidsetup() { Serial.begin(9600); Wire.begin(); reg02h = RDA5807M_FLG_ENABLE | RDA5807M_FLG_DHIZ | RDA5807M_FLG_DMUTE; setRegister(RDA5807M_REG_CONFIG, reg02h); reg02h |= RDA5807M_FLG_BASS; setRegister(RDA5807M_REG_CONFIG, reg02h); reg03h = (freq - 870) << RDA5807M_CHAN_SHIFT; setRegister(RDA5807M_REG_TUNING, reg03h | RDA5807M_FLG_TUNE); reg05h = getRegister(RDA5807M_REG_VOLUME); reg05h &= ~RDA5807M_VOLUME_MASK; reg05h |= volume << RDA5807M_VOLUME_SHIFT; setRegister(RDA5807M_REG_VOLUME, reg05h); } voidloop() { reg0Bh = getRegister(RDA5807M_REG_RSSI); uint8_t RSSI = (reg0Bh & RDA5807M_RSSI_MASK) >> RDA5807M_RSSI_SHIFT; Serial.print("RSSI = "); Serial.print(RSSI); Serial.println(" (0-min, 127-max)"); delay(500); } void setRegister(uint8_t reg, const uint16_t value) { Wire.beginTransmission(0x11); 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(0x11, 2, true); result = (uint16_t)Wire.read() << 8; result |= Wire.read(); return result; }
В этом примере значения регистров получаются установкой отдельных разрядов. Для этого используются определенные в начале скетча флаги и маски. Я описал несколько из них для примера, остальные добавляются по аналогии. Чтобы настроить RDA5807M на интересующую частоту необходимо установить значения BAND и SPACE и затем изменять только значение CHAN. Итоговая частота определяется по формуле:F = BAND + CHAN * SPACE. В скетче используются определенные по умолчанию BAND и SPACE (87..108МГц и 100кГц соответственно). По ним можно определить значение, которое должно быть записано в биты CHAN для получения интересующей частоты. Не забывайте при записи CHAN устанавливать также бит TUNE. Для изменения громкости значение регистра 05h считывается из RDA5807M в переменную. Затем осуществляется сброс битов VOLUME. И уже после этого можно устанавливать новое значение громкости и записывать результат в регистр. Для получения RSSI выполняются обратные действия: в считанном из регистра 0Bh значении сбрасываются все биты, кроме содержащих RSSI. Затем результат сдвигается вправо, чтобы младший бит RSSI оказался в младшем разряде переменной. Так мы получим нужное нам значение. Теперь, когда описаны основные приемы управления RDA5807M, можно приступить к программированию. Нужно лишь определиться с функционалом и интерфейсом.
Общие принципы работы FM приёмника
Принцип работы радиостанций заключается в том, что они преобразуют первичные электрические сигналы в радиосигналы (более высокой частоты чем первичные сигналы), усиливают их до необходимого уровня и затем излучают их в окружающее пространство с помощью антенны. В процессе преобразования сигналов в радиостанции они подвергаются модуляции. Одними из самых известных (старейших) методов модуляции являются амплитудная (AM — amplitude modulation) и частотная модуляции (FM — frequency modulation).
Мы в нашем проекте будем рассматривать приемник, предназначенный для приема сигналов частотной модуляции (FM, в рус. языке — ЧМ). В данном виде модуляции частота несущего колебания модулируется (изменяется) по закону амплитуды первичного низкочастотного сигнала. Проектируемый нами приемник сможет принимать сигналы частотной модуляции (ЧМ) на определенной частоте и преобразовывать их в сигналы звуковой частоты (первичный электрический сигнал). Наш FM приемник будет построен на основе микросхемы RDA5807.
Интерфейс управления
Здесь я хочу обратить внимание на имеющуюся в технической документации неточность (даташит на эту микросхему вообще очень мутный): в ней говорится, что I2C адрес микросхемы 0x10h, что внутренние адреса ее регистров не видны и что чтение и запись выполняются последовательно, начиная с фиксированного стартового адреса (0x0Ah для чтения, 0x02h для записи). После каждой операции чтения/записи происходит инкремент внутреннего счетчика и очередная операция будет выполняться уже для следующего регистра
Так до тех пор, пока внутренний счетчик не дойдет до верхней границы 0x3Ah, после этого он вернется к своему начальному значению. На самом деле RDA5807M отзывается на три I2C адреса, в чем легко убедиться, воспользовавшись I2C сканером:
I2C адреса RDA5807M |
Адрес 0x10h используется для последовательного обращения к регистрам, как было описано выше.Адрес 0x11h позволяет обращаться к произвольным регистрам.Адрес 0x60h позволяет работать с RDA5807M в режиме совместимости с TEA5767. Упоминание адреса 0x11h можно найти в документе RDA5807P_ProgManual_1.0. Хоть он и предназначен для другой микросхемы, но практически всё применимо и для RDA5807M. Ниже приведен фрагмент из данного документа, описывающий формат I2C обмена при использовании адреса 0x11h:
Формат обмена с RDA5807M по I2C адресу 0x11h |
Как можно видеть, при записи в режиме произвольного доступа первым передается адрес интересующего регистра (REGISTER ADDRESS), затем старший и младший байты данных. Для чтения содержимого регистра из RDA5807M микроконтроллер сначала передает его адрес, затем считывает старший и младший байты. Чуть позже я приведу пример чтения/записи регистров, а пока разберемся с их назначением.
ЛУТ, фоторезист и отладка
После успешных испытаний на монтажной плате мы решили создать ещё несколько прототипов методом ЛУТ (а в дальнейшем — фоторезистом). Также мы решили усовершенствовать приемник, добавив туда ещё один усилитель звука для подключения не только наушников, но и внешнего динамика. Выбор пал на PAM8403, это простой и недорогой усилитель, который требует питания 5В. Первый прототип, изготовленный методом ЛУТ, выглядел следующим образом: ЛУТ — хорошая штука для относительно быстрого прототипирования в домашних условиях, но когда дело доходит до двухсторонних плат, начинаются сложности. Количество компонентов на плате увеличивалось — например, мы решили разместить на плате разъем для программатора, чтобы не было необходимости каждый раз извлекать МК для перепрошивки. Так, последующий прототип стал двухсторонним, был изготовлен методом фоторезиста и стал выглядеть намного приятнее: В сборке: Следующим шагом был отказ от «навесных» компонентов, которые мы размещали на плате при помощи однорядных PINов. Так, было принято заменить усилитель на LM386N, установить преобразователь уровней CD4050BE. Всё это усложнило конструкцию, но устройство стало выглядеть намного лучше. Итоговый прототип, изготовленный нами в домашних условиях, выглядел так:
Тестирование работы FM приёмника
Когда на схему нашего проекта подается питание происходит сброс модуля RDA5807M и установка в нем канала по выбору пользователя. При вращения ручки потенциометра, отвечающего за настройку приемника на требуемую частоту, подключенного к контакту A0, значения, считываемые платой Arduino Nano с этого контакта, изменяются. Если разница между старым и новым значениями больше 10, мы считаем это изменение истинным (то есть произошедшим не вследствие действия шума) и изменяем в соответствии с ним канал, на который будет настроен радиоприемник. Уровень громкости звука мы изменяем с помощью потенциометра, подключенного между контактом 3 и GND.
Более подробно работа нашего FM приёмника представлена в видео, приведенном в конце статьи.
MIT License
Copyright (c) 2019 Ricardo Lima Caratti
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.