Макет ЧМ радиомаяка сделан из Генератора радиосигналов
на Si5351A.
ЧМ реализована при помощи быстрой (на скорости около 700 кбит/сек I2C) смены коррекции
частоты синтезатора Si5351A. Суть ЧМ - колебания частоты в заданной полосе с частотой,
соответствующей звуковому сигналу. Конкретно - в коде реализован цикл, который
периодически (с частотой около 400 Гц) изменяет коррекцию частоты синтезатора так, чтобы
происходила отстройка от основного сигнала в полосе 2.5 кГц.
В отличие от классической ЧМ, в данном случае изменение частоты в полосе
происходит без промежуточных значений.
В прошивке применена библиотека
для работы с синтезатором, в которой специально, для реализации ЧМ, существуют
"урезанные" функции, которые намного быстрее позволяют установить коррекцию частоты.
Прошивка, для генератора сигналов:
#include <si5351.h> #include <avr/wdt.h> #include <avr/sleep.h> #define SPEED 60 Si5351 si5351; void setup() { pinMode(LED_BUILTIN, OUTPUT); cli(); MCUSR &= ~(1<<WDRF); wdt_reset(); WDTCSR |= 1 << WDCE | 1 << WDE; WDTCSR = 0; wdt_enable(WDTO_8S); WDTCSR |= 1 << WDIE; set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); si5351.set_correction(0, SI5351_PLL_INPUT_XO); si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); si5351.set_freq(14557820000ULL, SI5351_CLK0); si5351.pll_reset(SI5351_PLLA); si5351.output_enable(SI5351_CLK0,0); si5351.output_enable(SI5351_CLK1,0); si5351.output_enable(SI5351_CLK2,0); TWBR = 0b00000010; wdt_reset(); } void loop() { sleep_mode(); sleep_mode(); sleep_mode(); si5351.output_enable(SI5351_CLK0,1); si5351.set_freq(14557820000ULL, SI5351_CLK0); delay(SPEED*10); //VVV tx_dot(); tx_dot(); tx_dot(); tx_dash(); delay(SPEED*3); tx_dot(); tx_dot(); tx_dot(); tx_dash(); delay(SPEED*3); tx_dot(); tx_dot(); tx_dot(); tx_dash(); delay(SPEED*7); //DE tx_dash(); tx_dot(); tx_dot(); delay(SPEED*3); tx_dot(); wdt_reset(); delay(SPEED*7); //UB8AFR/B tx_dot(); tx_dot(); tx_dash(); delay(SPEED*3); tx_dash(); tx_dot(); tx_dot(); tx_dot(); delay(SPEED*3); tx_dash(); tx_dash(); tx_dash(); tx_dot(); tx_dot(); delay(SPEED*3); tx_dot(); tx_dash(); delay(SPEED*3); tx_dot(); tx_dot(); tx_dash(); tx_dot(); delay(SPEED*3); tx_dot(); tx_dash(); tx_dot(); delay(SPEED*3); tx_dash(); tx_dot(); tx_dot(); tx_dash(); tx_dot(); delay(SPEED*3); tx_dash(); tx_dot(); tx_dot(); tx_dot(); delay(SPEED*7); wdt_reset(); //MO05QD tx_dash(); tx_dash(); delay(SPEED*3); tx_dash(); tx_dash(); tx_dash(); delay(SPEED*3); tx_dash(); tx_dash(); tx_dash(); tx_dash(); tx_dash(); delay(SPEED*3); tx_dot(); tx_dot(); tx_dot(); tx_dot(); tx_dot(); delay(SPEED*3); tx_dash(); tx_dash(); tx_dot(); tx_dash(); delay(SPEED*3); tx_dash(); tx_dot(); tx_dot(); delay(SPEED*7); wdt_reset(); si5351.output_enable(SI5351_CLK0,0); } ISR (WDT_vect) { WDTCSR |= (1 << WDIE); } void txTone_on(int timer) { for (int i = 0; i < timer/1.3; i++) { delayMicroseconds(400); si5351.set_correction2(-3000, SI5351_PLL_INPUT_XO); si5351.set_correction2(2000, SI5351_PLL_INPUT_XO); } } void txTone_off() { si5351.set_correction2(0, SI5351_PLL_INPUT_XO); } void tx_dot() { txTone_on(SPEED); txTone_off(); delay(SPEED); } void tx_dash() { txTone_on(SPEED*3); txTone_off(); delay(SPEED); }