
В предыдущей статье я рассказывал, что такое амплитудная модуляция и проделал программные эксперименты по переносу спектра аудиосигнала на несущую частоту. Сейчас я хочу продемонстрировать проект в плате Марсоход2 - простой АМ передатчик из ПЛИС.
Идея проекта простая:
- Аудиофайл буду посылать из компьютера в плату Марсоход2 через последовательный порт с параметрами передачи: скорость 230400 бод, 8 бит, без четности, один стоп бит. Таким образом, последовательный порт передает примерно 23040 байт в секунду. Для передачи файла в последовательный порт использую программу TeraTerm.
- Чтобы упростить себе жизнь сперва конвертирую с помощью редактора звука Audacity обычный аудиофайл SleepAway.wav в формат WAV, 8 bit, mono, 22050 выборок в секунду. Мой поток из последовательного порта 23040 байт в секунду примерно соответствует требуемой частоте выборок звука 22050 выборок в секунду.
- В проекте в ПЛИС имеется таблица синусов на 64 элемента - значения синусов предварительно вычислены и хранятся там в виде 16-ти битных знаковых чисел.
- Входные выборки-байты из последовательного порта конвертируются в 16-ти битные знаковые числа и умножаются на числа из таблицы синусов - происходит модуляция аудио сигнала. Там же, в модуле am_modulator добавляется несущая. Таким образом, весь процесс модуляции происходит численными методами.
- С выхода модулятора берутся только 6 самых старших бита и отправляются на шестибитный R2R ЦАП выполненный на внешних резисторах на плате Марсоход2. На самом деле на плате Марсоход2 есть 3 ЦАП обычно используемых для формирования сигналов high-color видео R, G, B. Сигнал "зеленый" самый емкий - шестибитный. Вот этот сигнал и идет на антенну, как видно на фото:

Проект Altera Quartus II в ПЛИС не очень сложный. Его топ модуль выполнен в графическом виде (можно кликнуть на картинку, чтобы посмотреть в увеличенном виде):
Вот сам модуль амплитудного модулятора написан на языке Verilog HDL:
module am_modulator(
input wire clk,
input wire [7:0]signal,
input wire signed [15:0]mod_sin,
output wire [5:0]out
);
//make signed 16bit signal from input unsigned 8bit signal
reg signed [15:0]ssignal;
always @(posedge clk)
ssignal <= { signal, 8'h00 } - 16'h8000;
//modulate by multiplying useful signal on modulation freq sinusoida
reg signed [31:0]multiplied;
always @(posedge clk)
multiplied <= ssignal * mod_sin;
reg signed [15:0]multiplied_th; //top half
always @(posedge clk)
multiplied_th <= multiplied[31:16];
//add modulation freq carrier to signal
reg signed [15:0]s_after_mod;
always @(posedge clk)
s_after_mod <= ( (mod_sin>>>1)+multiplied_th );
//make unsigned
reg [15:0]after_mod;
always @(posedge clk)
after_mod <= s_after_mod + 16'h8000;
assign out = after_mod[15:10];
endmodule
Здесь в Verilog модуле очень важно следить за диапазонами вычисляемых значений, нужно учитывать, что вычисления знаковые, а результат всего 6 бит - беззнаковые числа, которые пойдут на R2R ЦАП.
Знаковые числа объявляются в Verilog HDL как "reg signed". Если нужна явная конвертация типов из беззнакового регистра в зноковый регистр, то можно писать $signed(...).
В принципе, можно было бы сказать, что проект уже и готов, но вот что делать с антенной? Изначально я сделал этот проект передатчика и расчитывал на несущую частоту 1 Мгц. Это где-то посередине радио диапазона АМ. Но в таком виде, при подключенном куске провода 2 метра мой радиоприемник почти ничего не ловил. Оно и понятно, антенна должна быть хотя бы четверть волны. При частоте 1МГц длина волны 300 метров. Значит антенну мне надо 300 метров / 4 ~ 75 метров !!!?
Решил попробовать сделать что-то вроде простейшей компактной антенны - колебательный контур.
Воспользовался в интернете онлайн калькулятором расчета контура: http://tel-spb.ru/lc.html и получилось, что при емкости 1000pF мне нужны индуктивность около 25uH, чтобы резонанс контура был на частоте 1МГц.
В другом онлайн калькуляторе http://coil32.narod.ru/calc/one_layer.html посчитал, что мне нужно 5 витков катушки 300мм, чтобы получить эти самые 25 микрогенри индуктивности. Вот так сделал колебательный контур.

Потом решил, что хорошо бы проверить реальную частоту резонанса. А то ведь бывает думаешь, что все сделал правильно и должно быть как задумал, а получается все не так. У нас как-то был проет "исследование колебательного контура в плате Марсоход2". Взял этот проект и измерил, что получается с резонансом моей антенны.

В SignalTap увидел возбужденные колебания контура и понял, что мой контур по параметрам отличается от расчетных. Хотел 1МГц, а получилось где-то 1,4МГц. Ну переделывать контур уже не стал. 1,4 МГц так же укладывается в диапазон радио АМ. Просто в своем проекте Quartus II сменил несущую частоту (а заодно и коэффициент приемника последовательного порта).
Теперь, хоть верьте хоть нет, но с такой импровизированной антенной в виде колебательного контура стало передавать радиосигнал гораздо лучше. Особенно если правильно сориентировать радиоприемник относительно моей антенны.
Ниже представлена видео демонстрация проекта. Смотреть, конечно, нужно со звуком. На этом ролике виден ноутбук с программой TeraTerm, которая передает файл в последовательный порт, видна плата Марсоход2 с антенной и бытовой радиоприемник. Фоновая музыка раздается из радиоприемника - это то, что я транслирую в эфир.
Исходные данные по проекту скачать можно на нашем сайте в разделе загрузки или вот здесь:
PS: а у нас на сайте еще и FM передатчик когда-то был сделан..



I am from Vietnam
can you re-up your project, I can't download the it and the FM radio
не знаю правильно или нет.. phi_inc_i это входной сигнал, который определяет частоту на выходе генератора NCO. NCO используется, когда нужно перестраивать частоту в некотором диапазоне. Вам нужно перестраивать частоту? Или она у вас на выходе должна быть постоянная?
В документации на мегафункцию NCO есть формула
Fout=φinc *Fclk / 2^m Hz, то есть на phi_inc_i нужно подавать Fout * 2^m / Fclk, где Fout - желаемая частота на выходе NCO, Fclk - это тактовая на NCO (например 20МГц), а 2^m - это зависит от разрядности phi_inc_i, если 32 разряда, то 0x100000000.
да, хочу сделать
да, теперь, когда у меня есть свой АМ передатчик я хочу заняться SDR приемником в плате Марсоход2.
reg signed [31:0]multiplie d; и reg signed [15:0]multiplied_th;
происходит опережение сигнала mod_sin на два такта относительно сигнала multiplied_th перед суммированием.
При большом кол-ве отсчетов в таблице синуса ошибка небольшая, но все же правильно задержать сигнал mod_sin.
Про CTS - спасибо. Я наткнулся на описание DTR/DSR метода и думал, что он единственный для бинарных потоков.
А про PAL-кодер... Ну так тем интереснее же, а если не получится, то всегда есть запасной вариант
opencores.org/.../
Можно. Ножка "FTDI_BD3" подключена к "CTS#" СОМ-порта. Ей можно останавливать передачу.Когда- то так делал.
А на счет цветного видеосигнала, мой вам совет, незаморачивайте сь, уж очень там все сложно.
Разумеется я проверял корректность низкочастотного сигнала. Такое впечатление, что при модуляции ТВ сигнала надо довольно строго соблюдать глубину модуляции и уровни сигналов, в частности нельзя чтобы уровень модулирующего сигнала был нулевым (а у низкочастотного это можно). Ладно - раз говорите, что прямоугольник не страшно, то буду пробовать дальше. В идеале я хотел бы сделать ЧМ модулятор для цветности и AM модулятор радиочастоты - чтобы из марсохода шел цветной сигнал в антенный вход телевизора.
Вы сначала сделайте низкочастотный сигнал и подайте на "AV" телевизора. Если будет показывать, то тогда уж
им модулируйте. "Просто прямоугольник" подходит,
только могут быть помехи на других каналах (от верхних гармоник)
Спрашиваю в связи с интересом к TB-модулятору на ПЛИС. Я сделал простенький (с прямоугольником переменной амплитуды) - видно что телевизор что-то там ловит, но картинки пока не видно:( Грешу на несоблюдение полярности и уровней составляющих сигнала (синхросмеси и картинки).