Документация Engee
Notebook

Генерация кода для Arduino (линейная частотная модуляция с фильтром нижних частот)

В этом демонстрационном примере производятся расчёт, моделирование и выполнение на целевом устройстве цифрового фильтра нижних частот при линейной частотной модуляции.

Введение

Цель этого примера - разработать фильтр нижних частот по заданным параметрам. Для его расчёта воспользуемся библиотекой DSP языка Julia. Работу фильтра проверим в модели Engee на сигнале, полученном линейной частотной модуляцией. После генерации кода из модели Engee воспроизведем фильтрацию сигнала на отладочной плате Arduino.

Аппаратная часть

В этом примере используется отладочная плата Arduino MEGA 2560. Выходной сигнал формируется на выходе № 9. Цифро-аналоговое преобразование сигнала выполняется при помощи ШИМ и RC-фильтра нижних частот. Частота ШИМ составляет 62.5 кГц, частота среза RC-фильтра - 14.185 кГц, порядок фильтра - 2. Схема соединения представлена на рисунке ниже.

pcb_lpf.png

Параметры RC-цепи: $R = 330 Ом ,\ C = 34 нФ$. На выходе цепочки через токоограничивающий резистор $R_д = 10 кОм$ подключено гнездо аудиовыхода 3.5 мм для вывода сигнала на динамик.

Описание модели

Функциональная часть модели, рассматриваемой в этом примере - это подсистема FM, формирующая переменную скважности Duty. Эта переменная в пользовательском скетче будет передана в модуль ШИМ контроллера для формирования выходного аналогового сигнала.

image.png

Содержимое подсистемы FM описывает линейную частотную модуляцию по формуле $y = sin(2\cdot\pi \cdot f \cdot t)$. Частота сигнала изменяется линейно: $f = 50\cdot t$ После прохождения через фильтр нижних частот в блоке LPF отфильтрованный сигнал $y_ф$ получает смещение и масштабируется. Это необходимо для корректного и максимально точного формирования скважности ШИМ. Разрешение ШИМ в этом примере составляет всего 5 бит, однако это позволяет достичь высокой частоты ШИМ.

image.png

Скважность ШИМ определяется формулой $Duty = 16\cdot (y_ф+1)$.

Следует заметить, что в целях дополнительной экономии вычислительных мощностей целевого устройства изменение частоты сигнала связано напрямую с временем симуляции. Таким образом, частота модулируемого сигнала в определенный момент превысит и частоту Найквиста, и частоту дискретизации. Следовательно, для корректного представления результатов работы фильтра необходимо выбрать такую частоту среза, которая будет ниже частоты Найквиста.

Расчёт фильтра нижних частот

Для фильтрации нижних частот выберем эллиптический фильтр с параметрами:

  • частота дискретизации - 2000 Гц (отсюда, частота Найквиста - 1000 Гц),
  • частота среза - 400 Гц,
  • число полюсов - 6,
  • неравномерность характеристики в полосе пропускания - 1 дБ,
  • затухания в полосе задержки - 60 дБ.
In [ ]:
fs = 2000
fp = 400;
n = 6;
Rp = 1;
Rs = 60;

Рассчитаем коэффициенты полиномов числителя и знаменателя передаточной функции фильтра:

In [ ]:
using DSP;
myfilt = digitalfilter(Lowpass(fp; fs), Elliptic(n, Rp, Rs));
b = coefb(myfilt);
a = coefa(myfilt);

Скопируем полученные коэффициенты в числитель и знаменатель блока LPF модели.

Результаты моделирования

Загрузим и выполним созданную модель:

In [ ]:
if "chirp_lpf" in [m.name for m in engee.get_all_models()]
    m = engee.open( "chirp_lpf" );
else
    m = engee.load( "$(@__DIR__)/chirp_lpf.engee" );
end

data = engee.run(m);

Из полученных данных модели построим графики выходных переменных - сигнала на входе и выходе ФНЧ: LPF_in и LPF_out соответственно.

In [ ]:
using Plots
plotlyjs()
plot(data["LPF_in"].time, data["LPF_in"].value,
    label="До ФНЧ", size=(900,300), lw=2, st=:step)
plot!(data["LPF_out"].time, data["LPF_out"].value,
    label="После ФНЧ", size=(900,300), lw=2, st=:step)
xlabel!("Время, сек")
ylabel!("Значение")
Out[0]:

Как видно из графика, фильтр выполняет преобразование сигнала по заданным параметрам.

Загрузка кода в Arduino

Для загрузки на Arduino необходимо сгенерировать код из подсистемы FM:

In [ ]:
engee.generate_code( "$(@__DIR__)/chirp_lpf.engee",
                     "$(@__DIR__)/chirp_lpf_code";
                     subsystem_name="FM")
[ Info: Generated code and artifacts: /user/start/examples/codegen/arduino_chirp_lpf/chirp_lpf_code

Сгенерированные в указанной директории файлы подключим в пользовательском скетче chirp_lpf.ino. Скачаем эти файлы и загрузим в Arduino MEGA при помощи Arduino IDE.

Выполнение кода на Arduino

После успешной компиляции и загрузки скетча в целевое устройство на выходе RC-фильтра подключим цифровой осциллограф и снимем переменную составляющую генерируемого сигнала.

Для демонстрации был использован цифровой осциллограф Hantec DSO c подключением к компьютеру и выводом данных в программу DSO Analyzer.

chirp_lp.gif

Как можно заметить, при повышении частоты синусоидального сигнала после 400 Гц наблюдается подавление его амплитуды. Для лучшего представления работы модели с цифровым фильтром на выход RC-цепочки был подключен динамик, а полученный звук записан в файле chirp_lpf_audio.wav. Следующая ячейка кода позволяет загрузить в скрипт полученный аудио-файл и воспроизвести его. Проиграйте аудиодорожку, чтобы убедиться в работоспособности разработанной модели и фильтра.

In [ ]:
using WAV, Base64
x, fs = wavread( "$(@__DIR__)/chirp_lpf_audio.wav" );

buf = IOBuffer();
wavwrite(x, buf; Fs=fs);
data = base64encode(unsafe_string(pointer(buf.data), buf.size));
markup = """<audio controls="controls" {autoplay}>
              <source src="data:audio/wav;base64,$data" type="audio/wav" />
              Your browser does not support the audio element.
              </audio>"""
display( "text/html", markup );

Вывод

В этом примере мы рассмотрели работу цифрового эллиптического фильтра нижних частот, который обрабатывает сигнал ЛЧМ. Рассчитанный фильтр соответствует заданным параметрам как при моделировании, так и при его выполнении на целевом устройстве.

Блоки, использованные в примере