Блог UA3REO
Строим цифровой DDC SDR приёмник своими руками (часть 1)
На стыке интересных мне областей программирования и радио зародился долгий, но интересный проект по созданию цифрового приёмника прямого преобразования, в котором аналоговых частей будет абсолютный минимум.
С каждой частью статьи я планирую дорабатывать приёмник, улучшать его характеристики, обвешивать его разными доработками, а в итоге возможно и получить полноценный трансивер.
Базовый комплект будет построен на китайской АЦП AD9226.
Цифровым сердцем приёмника будет являться FPGA матрица Altera EP4CE10.
Для того, чтобы не мучатся с наушниками добавлен простейший УНЧ с питанием в 5 вольт и динамик.
Итак, соединяем все воедино (точки подключения особой роли не играют, всё настраивается и назначается программно).
Идея приёмника заключается в смешивании оцифрованного с помощью АЦП радиосигнала с гетеродином, выдающим 2 сигнала со смещением в 90 градусов (синус и косинус).
Тем самым мы получаем комплексный сигнал (I и Q), с помощью которого достаточно легко добиться подавления зеркального канала и демодулировать полезный сигнал.
Устанавливаем среду разработки Quartus.
Начинаем с подключения АЦП (вход и тактовый сигнал). Т.к. внешнего кварцевого генератора нет, будем тактовать модуль силами самой FPGA (а это очень плохо в плане качества приёма, но для первой версии сгодится).
Добавляем вход кварцевого генератора планы FPGA (50 мегагерц).
Первым делом создаём гетеродин, настроенный на частоту приёма. Его задача состоит в переносе частот с диапазона радиоволн в звуковой.
Его параметры на скриншотах:
Для управления частотой гетеродина в него необходимо передать слово частоты, задающее смещение фазы, для этого подготовим отдельный модуль. Сейчас частота будет статична, но дальше планирую менять её энкодером.
Слово частоты это число, получаемое делением необходимой частоты в герцах на частоту кварцевого генератора и умноженную на двойку в степени, равной разрядности DDS-генератора (гетеродина).
Полученный сигнал подаём на 2 смесителя (умножителя), которые обеспечивают смешивание сигнала АЦП (вход А) с сигналом гетеродина (вход B).
Полученный сигнал смещён на частоту гетеродина, т.е. выбранная частота теперь размещается в нулевой. А слева (да, в отрицательной части) и справа от неё находятся весь необходимый нам спектр.
Чтобы дальше эффективно работать с сигналом, нам необходимо его децимировать (уменьшить частоту выборок), эту роль выполняет CIC фильтр.
После этого частота выборок сокращается с 50 миллионов раз в секунду до 100 000.
Далее нам необходимо сделать полосовой фильтр, т.к. будем принимать SSB сигнал, то фильтр полоса пропускания потребуется в районе 2700гц. Для этого воспользуемся фильтром конечных импульсных характеристик (FIR).
Для его расчёта удобно использовать следующие программы:
Iowa Hills FIR Filter Designer
WinFilter
Также, фильтр сократит число выборок с 100 000 до 50 000, что подходит для вывода на динамик.
Далее сокращаем разрядность (количество бит) в потоке для дальнейшей обработки.
Ещё, потребуется PLL модуль для тактования частоты 50кгц (равной частоте дискретизации потока на текущем этапе).
Полученные сигналы уже можно выводить на динамик, но мы не избавились от основной проблемы приёмников прямого преобразования — зеркального канала. Т.е. слушая передачи слева и справа от принимаемой частоты будем принимать их одинаково хорошо. Необходимо получить однополосный приём.
Для этого поток Q (смешанный с синусом) необходимо довернуть по фазе на 90 градусов, тем самым потоки I и Q будут относительно друг друга в 180 градусах. Их дальнейшее сложение или вычитание будет давать USB и LSB полосу приёма соответственно, подавляя всё лишнее.
Помочь нам в этом может преобразователь (фильтр) Гильберта, рассчитанный в программе MatLab.
Т.к. фильтр Гильберта вызывает задержку сигнала на ((количество ступеней фильтра-1)/2) то необходимо задержать сигнал I на столько же шагов.
Далее мы можем сложить (или вычесть) коплексные составляющие сигнала, получив необходимую полосу приёма.
Итоговый результат подадим на дельта-сигма модулятор, смысл работы которого заключается в восстановлении синусоидального сигнала из ШИМ с помощью RC-цепочки (резистор 3.3к, конденсатор 47нф).
Программный код готов, можно привязать выводы в прошивке к ножкам FPGA.
Готово, можно включить приёмник, подключить антенну ко входу АЦП и наслаждаться его работой.
Следующим шагом наверное буду делать УВЧ, управление частотой, дисплей.
При создании были использованы материалы следующих статей, без которых было бы не реально сделать хоть что-то, огромное спасибо авторам.
13 мыслей о “Строим цифровой DDC SDR приёмник своими руками (часть 1)”
Здравствуйте Дмитрий. Вопрос по коэффициентам FIR-фильтра. Я загружаю в визард коэффициенты одного фильтра но в разном формате: Fixedpoint и Float и получаются разные АЧХ. На форуме Марсохода: https://marsohod.org/forum/5-altera-quartus-ii/1256-voprosy-novichka?start=230#7728 , мне ответили что это масштаб другой. Посмотрите пожалуйста там прикреплены две картинки по таблице видно что данные одни. Получается не важно, какие значения на оси Y, главное относительные величины пропускаемого диапазона частот и подавляемого? В этой статье тоже полезный сигнал «усиливается на сто db», чему верить?
Принципиального различия в формате чисел я не увидел, одно время даже написал конвертер из float в integer https://ua3reo.ru/services/float_to_dec_coeff.php
Дмитрий,
Наконец то нашел автора, который доходчиво объясняет подход к программированию на ПЛИС. Если знаешь структуру ППП, то разобраться в графической среде программирования не сложно, особенно, когда мысли излагаются так доходчиво. Есть один вопрос, не совсем в тему- я хочу собрать приемник с полным управлением и демодуляциеё на компе,и потому мне блоки демодуляции не нужны-их можно организовать программно, например в HDSDR , но вот как организовать управление и передачу на комп I Q потоков например через LAN8720 Модуль. Если бы вы такой проект в блоге написали было бы великолепно, а если нет-то хотя бы носом ткните в подобный проект с графическим отображением такого СДР приемника. А то что-то я подвис…Заранее спасибо!
Источник
Блог UA3REO
Строим цифровой DDC SDR приёмник своими руками (часть 2)
В этой части я решил добавить немного управления в радиоприёмник, а точнее выбор частоты и моды (LSB/USB).
А также заложить все базовые элементы управления, которые очень пригодятся в дальнейшем.
Т.к. мощности используемого FPGA модуля очень ограничены, он является очень бюджетным, то было решено вынести органы управления под управление платы Arduino UNO.
Тем самым сэкономив дорогие логические блоки FPGA, отказавшись от прямого опроса энкодера, вывода на дисплей информации и первой логики управления приёмником, которая дальше будет только расти.
В роли дисплея выступает LCD модуль от Nokia 5110, в роли энкодера модуль KY-040.
Общение между процессором ардуино и FPGA было решено организовать по протоколу UART.
Также, требованием этой части работ было перманентное сохранение конфигурации FPGA во флеш-память, ранее требовалась перепрошивка каждый раз после включения устройства.
После сборки всех элементов получилась следующая цветомузыка конфигурация:
Подключать Arduino UNO сразу к FPGA нельзя, т.к. ардуино использует высокие логические уровни (5 вольт), а ПЛИС до 3.3в (стандарт — 2.5в).
Для этого меняем стабилизатор напряжения на аналогичный, с 3.3в на выходе. Вместо предохранителя питания ставим диод.
Подробнее процесс описан в статье https://learn.adafruit.com/arduino-tips-tricks-and-techniques/3-3v-conversion
Итак, первым делом станет подключение процессора внутри ПЛИС. То есть на логических элементах матрицы FPGA генерируется процессор, эдакая микросхема в микросхеме.
Это просто поразительно — можно совместить огромнейшие вычислительные мощности FPGA и при этом управлять ими с помощью обычного процессора и прошивки на языке C. Например, на одной микросхеме можно собрать видеоадаптер HDMI, эмулировать процессор ZX Spectrum, перефирию и память (и впасть в ностальгию).
Данный эмулируемый процессор называется NIOS II.
Блок схема работы управления будет выглядеть так:
При создании процессора в Quartus программа предлагает добавить к процессору периферию, выбираем:
- clk — тактовый генератор процессора
- nios2 — собственно сам процессор
- pio_freq — GPIO выводы управления частотой гетеродина
- onchip_memory — ОЗУ, в моём случае 24 килобайта, пока этого достаточно
- sysid — система идентификации прошивки процессора
- uart — модуль общения с внешним миром, настроен на скорость в 57600 бод
- epcs_flash — модуль запили прошивки во внешнюю флеш-память
- pio_mode — GPIO вывод управления модой (LSB/USB)
Теперь мы можем добавить процессор на логическую схему.
соединяем выводы clk с кварцевым генератором, пины epcs на выводы, идущие к флеш-памяти. PIO на соответствующие модули гетеродина и демодулятора. UART входы и выходы не забываем переключить в режим 3.3v в Pin Planner.
Открываем среду разработки процессора Nios 2 (Tools->Nios II Software Build Tools for Eclipse) и создаём новый проект.
Программный код очень прост — читаем данные из UART, в зависимости от первого байта (команда) меняем или отсылаем необходимые данные.
Главной особенностью стоит назвать использование библиотеки alt_stdio.h вместо stdio.h, которая тянет за собой огромную кучу зависимостей, мгновенно съедая всю доступную память процессора (и даже больше).
После первой прошивки получившейся сборки у нас открывается возможность программировать память FPGA и его Nios во флеш память. Для этого был написан небольшой bat-файл, автоматизирующий все действия.
SET PATH=%PATH%;C:\intelFPGA\17.1\nios2eds\bin;C:\intelFPGA\17.1\quartus\bin64;C:\intelFPGA\17.1\nios2eds\bin\gnu\H-x86_64-mingw32\bin
sof2flash —input=»output_files\UA3REO.sof» —output=»output_files\hwimage.flash» —epcs —verbose —debug
elf2flash —input=»software\ua3reo_nios\ua3reo_nios.elf» —output=»output_files\swimage.flash» —epcs —after=»output_files\hwimage.flash» —verbose —debug
nios2-flash-programmer «output_files\hwimage.flash» —base=0x11000 —epcs —accept-bad-sysid —device=1 —instance=0 —cable=1 —program —verbose
nios2-flash-programmer «output_files\swimage.flash» —base=0x11000 —epcs —accept-bad-sysid —device=1 —instance=0 —cable=1 —program —verbose —go
pause
Суть команд в следующем:
sof2flash подготавливает SOF прошивку FPGA для прошивки во флеш память;
elf2flash делает аналогичные действия для прошивки Nios 2;
nios2-flash-programmer их поочереди прошивает.
Теперь приёмнику не страшна перезагрузка или отключение питания, всё заработает мгновенно после включения.
Финальным этапом будет разработка приложения для ардуино. Кратко пробежимся по коду.
Задаём настройки выходов, инициализируем переменные.
Важно отметить что ключевые переменные вроде частоты и моды продублированы — это необходимо чтобы разделить выполнение кода прерываний (энкодера) от основного цикла.
Это сделано в силу того, что мы не можем по прерыванию сразу отправлять данные в UART. Во первых, во время работы прерывания не доступны функции delay, millis и прочие, связанные со временем. Во вторых передача данных может занять некоторое время, и «плавность» работы энкодера будет нарушена.
Запрашиваем текущие параметры с приёмника
Избавление от дребезга контактов при нажатии энкодера реализовано через отключение прерывания внутри прерывания)))
Прерывание для обработки вращения энкодера
Остальной код можно увидеть в исходниках, доступных по ссылке ниже.
Видео работы проекта, прошу заметить что приёмник не обладает УВЧ совсем, и 5-ти вольтовый АЦП пытается выудить из микровольтного сигнала хоть что-то. УВЧ думаю доделать в ближайших частях, когда придут запчасти.
Код проекта доступен по ссылке.
Статьи, используемые при разработке этой части:
Источник