Цифровой трехпрограммный радиоприемник на STM32F4Discovery

Сразу скажу, что речь идет про проводное радио (это такое радио из специальной розетки, которое слушают в основном наше старшее поколение). А также про SDR (software-defined radio), когда процесс радиоприема полностью реализован методами цифровой обработки сигналов.

Предыстория: мне как-то однажды необходимо было записать на компьютер радиопередачу, которая транслируется по проводному радио. Поскольку трехпрограммный радиоприемник покупать было тупо дорого (порядка 1000 рублей, $30), то единственным выходом было — взять имеющуюся у меня плату STM32F4Discovery и реализовать на ней цифровой АМ-радиоприемник. 😉

1. Немного теории.

Проводное радиовещание (которое к сожалению, сейчас уже редкость и в скором времени ожидается его полное вымирание) — это три канала звукового сигнала. Один канал передается в виде электрического сигнала звуковой частоты амплитудой 30 В или 15 В. Два других канала передаются как амплитудно-модулированные сигналы с несущими 78 и 120 кГц соответственно, амплитудой порядка 2 В. Все это смешивается вместе и выводится по двум проводам в розетку.

Классическим способом реализации цифрового радиоприемника является синхронное детектирование. Рассмотрим как это работает для AM сигналов. Пусть у нас есть полезный сигнал s(t). Мы его промодулировали по амплитуде и получили: x(t) = s(t) \sin(\omega t) (без потери общности я считаю, что коэффициент модуляции — единица).

Далее, уже в радиоприемнике, этот сигнал оцифровывается. Также в радиоприемнике есть генератор частоты \omega, выдающий два сигнала z_s(t)=\sin(\omega t + \delta t) и z_c(t)=\cos(\omega t + \delta t), где \delta — погрешность формирования частоты.

Все что нужно — это перемножить входной сигнал x(t) с z_s(t) и z_c(t):

x(t)z_s(t) = s(t) \sin(\omega t) \sin(\omega t + \delta t) = s(t) \dfrac{\cos(\delta t) + \cos(2 \omega t + \delta t)}{2}
x(t)z_c(t) = s(t) \sin(\omega t) \cos(\omega t + \delta t) = s(t) \dfrac{\sin(\delta t) + \sin(2 \omega t + \delta t)}{2}

Далее эти произведения пропускаются через фильтры низких частот с полосой, достаточной для прохождения s(t), например с даже полосой \omega. В результате, слагаемые с частотой 2 \omega можно отбросить:

x(t)z_s(t) \to y_s(t) = \dfrac{s(t)}{2} \cos(\delta t)
x(t)z_c(t) \to y_c(t) = \dfrac{s(t)}{2} \sin(\delta t)

Дальше к прошедшим через фильтр сигналам y_s(t) и y_c(t) применяется теорема Пифагора:

y(t) = \sqrt{y_s^2(t) + y^2_c(t)} = \dfrac{s(t)}{2} \sqrt{\cos^2(\delta t) + \sin^2(\delta t)} = \dfrac{s(t)}{2}

Таким образом, дрейф \delta скомпенсирован и сигнал s(t) полностью восстановлен.

2. Как это сделано.

В качестве аппаратной платформы была выбрана плата STM32F4Discovery, поскольку  во-первых быстрый процессор, потом есть 3,5 jack для подключения наушников.

Сигнал с радиотрансляционной линии пропускается через две CR-цепочки, срезающие звуковые частоты первой программы радио.

SDR_Radio_in

Таким образом реализуется первичная обработка сигнала — редуцированный RF-front-end 😉

Далее сигнал оцифровывается микропроцессором. Используется АЦП ADC1 с циклическим запуском по таймеру TIM8. Максимальная частота, которую я смог выжать от этого АЦП в режиме 12 бит — порядка 460 кГц. В данном устройстве АЦП работает на частоте 300 кГц.

Цифровая обработка сигнала реализована в прерывании по таймеру TIM8. Для синтеза гармонических сигналов синхронного детектора использован алгоритм DDS. Фильтры низких частот реализованы с помощью модифицированного скользящего среднего (MMA). Вся арифметика — целочисленная (было лень включать математический сопроцессор).

Принимаемый сигнал после детектирования выводится через ЦАП (кстати, ЦАП в stm32 быстрый — порядка 1 МГц тянет) и пропускается через микросхему CS43L22 (кодек/усилитель класса D) на разъем для наушников. Кстати, большая часть времени работы была потрачена на запиливание CS43L22. Как оказалось для режима passthrough (просто чтобы пропустить сигнал насквозь) необходимо все равно включать тактовый сигнал I2S.

С помощью кнопочки на плате можно переключать программы.

Вот фотка того, что получилось в действии:

SAM_2233

Исходники можно скачать в двух версиях:

полная версия с выводом на разъем наушников

промежуточная версия без использования CS43L22, если например планируется применение внешнего усилителя (сигнал на выводе PA4).

3. Что еще нужно сделать.

– На самом деле, радиоприемник не трехпрограммный, а двухпрограммный 😉 Предполагается, что сигнал из розетки будет через резистивный делитель поступать на еще один какой-нибудь вход АЦП, и при включении первой программы АЦП будет переконфигурироватья, а код с него загоняться в ЦАП без обработки. Ну это как-бы тривиально, и я это не делал.

– Было бы круто сделать настоящий радиоприемник: выкинуть начинку старого трехпрограммного радио и положить туда STM32F4Discovery. Это тоже дело техники.

– Еще одна интересная идея — отказаться от питания и запитать устройство прямо энергией сигналов радиотрансляционной сети. По стандарту, 1 Вт мощности можно без проблем снять. Нужно взять трансформатор от абонентского громкоговорителя, выпрямитель, большой конденсатор и стабилизатор на 3.3 В. К сожалению, сделать не могу из-за отсутствия именно трансформатора.

3 thoughts on “Цифровой трехпрограммный радиоприемник на STM32F4Discovery

  1. Такая же идея приходила 10 лет назад, когда работал на радиоузле. Не думал, что кто-то ее реализует.

  2. Собрал вашу схемку только у меня проблемы с избирательность, я вход схемы подаю на Лин. Вход компьютера. И детектирую каждый семпл с помощью формулы найденной в интернете – demodulated = Sqrt((modulated) * (modulated++) + (modulated) * (modulated++));
    Не подскажете как ввести избирательность?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s