Программно определяемое радио/радиосистема (Software-defined radio, SDR) – радиопередатчик и/или радиоприёмник, использующий технологию, позволяющую с помощью программного обеспечения устанавливать или изменять рабочие радиочастотные параметры, включая, в частности, диапазон частот, тип модуляции или выходную мощность, за исключением изменения рабочих параметров, используемых в ходе обычной предварительно определённой работы с предварительными установками радиоустройства, согласно той или иной спецификации или системы (Википедия).
SDR выполняет значительную часть цифровой обработки сигналов на обычном персональном компьютере или на ПЛИС. Целью такой схемы является радиоприёмник или радиопередатчик произвольных радиосистем, изменяемый путём программной переконфигурации (отсюда происходит альтернативное наименование таких систем — программно конфигурируемые). В настоящее время подобные радиосистемы находят широкое применение, одним из их основных достоинств является возможность обслуживания большого количество радиопротоколов. Ряд экспертов полагают, что в будущем технология SDR станет доминирующей среди всех радиосистем.
В данной статье мы рассмотрим реализацию технологии SDR на основе платы Arduino и DDS модуле AD9850.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- ЖК дисплей 16х2 (купить на AliExpress).
- DDS модуль AD9850 (купить на AliExpress).
- Инкрементальный энкодер c кнопкой (Rotary Encoder) (купить на AliExpress — не уверен в том, что в нем есть кнопка, но она точно есть в этом лоте — купить на AliExpress № 2, но он продается, к сожалению, только по 5 штук).
- Микросхема 74HC4066.
- Транзистор BF494 (2 шт.).
- Транзистор BC547 (2 шт.) (купить на AliExpress).
- Варикап BB212 (2 шт.).
- Резисторы, конденсаторы, катушки индуктивности согласно далее представленной схемы.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Основные принципы работы проекта
«Сердцем» проекта является DDS модуль AD9850, подключенный к плате Arduino. Аббревиатура DDS (Direct Digital Synthesis) означает прямой цифровой синтез. При этом способе любой сигнал можно сформировать в цифровом виде, а затем преобразовать его в аналоговый вид с помощью цифро-аналогового преобразователя (ЦАП). Ранее на нашем сайте мы рассматривали эту технологию в проекте генератора сигналов на Arduino и DDS модуле AD9833.
AD9850 – это устройство с высокой степенью интеграции, в котором используется комбинация усовершенствованной технологии прямого цифрового синтеза (DDS, direct digital synthesis), высококачественного цифро-аналогового преобразователя и компаратора, обеспечивающая функции синтеза частоты с цифровым программным управлением и генерации тактовых сигналов. При работе от точного опорного источника тактового сигнала AD9850 формирует стабильный аналоговый выходной синусоидальный сигнал с программируемыми частотой и фазой. Этот синусоидальный сигнал может быть использован непосредственно в качестве источника частоты или преобразован внутренними средствами компонента в прямоугольное колебание. Более подробно о данном модуле можно прочитать на сайте analog.com.
Внешний вид DDS модуля AD9850 показан на следующем рисунке.
Ранее автор данного проекта (ссылка на оригинал приведена в конце статьи) создавал на основе модуля AD9850 и платы Arduino простой генератор переменной частоты (VFO), работу которого можно посмотреть в следующем видео:
Этот проект генератора переменной частоты он и использовал в качестве основы для создания данного проекта SDR радио на Arduino и DDS модуле AD9850.
Схема проекта
Аналоговая часть схемы нашего SDR приемника на основе платы Arduino и DDS модуле AD9850 представлена на следующем рисунке.
Далее в схеме располагается усилитель радиочастоты (УРЧ), который улучшает чувствительность приемника и предотвращает просачивание сигнала гетеродина (смесителя) в антенну. Смеситель построен на основе переключателя 74HC4066. С помощью потенциометра 5 кОм производится обнаружение самого слабого AM сигнала от мощных вещательных станций. Чаще всего это производится на критической (граничной) частоте, которую можно найти при помощи перестройки преселектора по диапазону частот. За смесителем следует однотранзисторный усилитель, выход которого подключается ко входу звуковой карты компьютера.
Цифровая часть схемы SDR приемника на основе платы Arduino и DDS модуле AD9850 представлена на следующем рисунке.
- HDSDR «http://www.hdsdr.de»;
- SDRadio «https://www.sdradio.eu/weaksignals/sdradio/index.html».
Автор проекта использовал программу SDRadio как самую простую для обработки радиосигналов. Также с нашим приемником можно использовать бесплатную программу «MULTIPSK» (http://f6cte.free.fr/index_anglais.htm), с помощью которой можно декодировать различные цифровые радиосигналы, например, от WeatherFAX – это можно посмотреть на представленном ниже видео проекта.
Во время записи видео условия для распространения коротких волн (SW) были достаточно плохими, по сравнению с RTLSDR наш проект обеспечивает немного более худшие результаты, но зато как приятно будет многим насладиться приемом коротких волн на радиоприемнике, собранным своими руками.
Исходный код программы (скетча)
Полный комплект всех необходим программ и библиотек для данного проекта от его автора можно скачать по этой ссылке. Здесь, в коде программы я привел только файл основной программы проекта из скачанного архива под названием AD9850_LCD_ROTARY_WMENUS.ino с частично переведенными мною комментариями.
Скетч в файле AD9850_LCD_ROTARY_WMENUS.ino используется для формирования сигнала на выходе схемы в диапазоне от 1 до 30 МГц. Начальная частота устанавливается при помощи внесения изменений в строку: int_fast32_t rx=7200000. Значение частоты на выходе проекта отображается на экране ЖК дисплея 16х2. Если у вас есть возможность воспользоваться калиброванным частотомером, то его с помощью вы можете настроить частоту int32_t freq = frequency * 4294967295/125000000;» чтобы на выходе модуля AD9850 обеспечить более точное значение частоты. При использовании данного скетча вам не нужно подключать переключатель и резистор к контакту A5 платы Arduino.
Также в скачанном архиве проекта вы найдете скетч с именем AD9850_LCD_ROTARY_WMENUS_IF. С помощью этого скетча на выходе устройства также формируется частота в диапазоне от 1 до 30 МГц. Но данный скетч также использует и промежуточную частоту (Intermediate frequency, IF). Начальная частота настраивается также, как и в предыдущем скетче. В случае использования данного скетча вам необходимо подключить переключатель и резистор к контакту A5 платы Arduino как показано на представленной выше схеме проекта. Промежуточная частота (IF) в данном скетче задается с помощью строки: int_fast32_t iffreq = 4192000. Это значение частоты будет вычитаться из частоты нашего основного сигнала. Когда контакт A5 платы Arduino будет замкнут на землю (на нем будет low), то выходная частота и частота, отображаемая на ЖК дисплее, будут равны. А когда на контакте A5 платы Arduino будет напряжение высокого уровня (high), то выходная частота устройства будет равна разности частот, отображаемой на ЖК дисплее, и промежуточной частоты.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/* Main code by Richard Visokey AD7C - www.ad7c.com Revision 2.0 - November 6th, 2013 */ // подключаем необходимые библиотеки #include <LiquidCrystal.h> #include <rotary.h> #include <EEPROM.h> //Setup some items #define W_CLK 8 // Pin 8 - connect to AD9850 module word load clock pin (CLK) #define FQ_UD 9 // Pin 9 - connect to freq update pin (FQ) #define DATA 10 // Pin 10 - connect to serial data load pin (DATA) #define RESET 11 // Pin 11 - connect to reset pin (RST) #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses. Must be interrupt pins. (используемые контакты для энкодера, должны быть сконфигурированы как контакты для обработки прерываний) LiquidCrystal lcd(12, 13, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts. int_fast32_t rx=7200000; // Starting frequency of VFO (начальная частота нашего генератора переменной частоты) int_fast32_t rx2=1; // variable to hold the updated frequency int_fast32_t increment = 10; // starting VFO update increment in HZ. (стартовый инкремент частоты для нашего генератора – 10 Гц) int buttonstate = 0; String hertz = "10 Hz"; int hertzPosition = 5; byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Placeholders String freq; // string to hold the frequency (строка для хранения значения частоты) int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup (переменная для хранения времени, прошедшего с момента включения arduino) int memstatus = 1; // value to notify if memory is current or old. 0=old, 1=current. int ForceFreq = 1; // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory. YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET! // измените это значение на 0 после того как вы загрузите и запустите скетч чтобы активировать память EEPROM void setup() { pinMode(A0,INPUT); // Connect to a button that goes to GND on push digitalWrite(A0,HIGH); lcd.begin(16, 2); PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); pinMode(FQ_UD, OUTPUT); pinMode(W_CLK, OUTPUT); pinMode(DATA, OUTPUT); pinMode(RESET, OUTPUT); pulseHigh(RESET); pulseHigh(W_CLK); pulseHigh(FQ_UD); // this pulse enables serial mode on the AD9850 - Datasheet page 12. (этот импульс включает последовательный режим в модуле AD9850) lcd.setCursor(hertzPosition,1); lcd.print(hertz); // Load the stored frequency (загружаем сохраненную частоту) if (ForceFreq == 0) { freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6)); rx = freq.toInt(); } } void loop() { if (rx != rx2){ showFreq(); sendFrequency(rx); rx2 = rx; } buttonstate = digitalRead(A0); if(buttonstate == LOW) { setincrement(); }; // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change. if(memstatus == 0){ if(timepassed+2000 < millis()){ storeMEM(); } } } ISR(PCINT2_vect) { unsigned char result = r.process(); if (result) { if (result == DIR_CW){rx=rx+increment;} else {rx=rx-increment;}; if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT if (rx <=1000000){rx=rx2;}; // LOWER VFO LIMIT } } // frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32 // частота, рассчитанная из даташита void sendFrequency(double frequency) { int32_t freq = frequency * 4294967295/125000000; // note 125 MHz clock on 9850. You can make 'slight' tuning variations here by adjusting the clock frequency. // в это выражение можно вносить небольшие изменения чтобы более точно настроить тактовую частоту for (int b=0; b<4; b++, freq>>=8) { tfr_byte(freq & 0xFF); } tfr_byte(0x000); // Final control byte, all 0 for 9850 chip pulseHigh(FQ_UD); // Done! Should see output } // transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line // передаем весь байт последовательно, сначала младшие биты, модулю 9850 через линию DATA void tfr_byte(byte data) { for (int i=0; i<8; i++, data>>=1) { digitalWrite(DATA, data & 0x01); pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high (после каждого переданного бита устанавливаем на CLK high } } void setincrement(){ if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;} else if (increment == 50){increment = 100; hertz = "100 Hz"; hertzPosition=4;} else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;} else if (increment == 500){increment = 1000; hertz="1 Khz"; hertzPosition=6;} else if (increment == 1000){increment = 2500; hertz="2.5 Khz"; hertzPosition=4;} else if (increment == 2500){increment = 5000; hertz="5 Khz"; hertzPosition=6;} else if (increment == 5000){increment = 10000; hertz="10 Khz"; hertzPosition=5;} else if (increment == 10000){increment = 100000; hertz="100 Khz"; hertzPosition=4;} else if (increment == 100000){increment = 1000000; hertz="1 Mhz"; hertzPosition=6;} else{increment = 10; hertz = "10 Hz"; hertzPosition=5;}; lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(hertzPosition,1); lcd.print(hertz); delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed. // настройте значение этой задержки чтобы увеличить/уменьшить скорость прокрутки меню }; void showFreq(){ millions = int(rx/1000000); hundredthousands = ((rx/100000)%10); tenthousands = ((rx/10000)%10); thousands = ((rx/1000)%10); hundreds = ((rx/100)%10); tens = ((rx/10)%10); ones = ((rx/1)%10); lcd.setCursor(0,0); lcd.print(" "); if (millions > 9){lcd.setCursor(1,0);} else{lcd.setCursor(2,0);} lcd.print(millions); lcd.print("."); lcd.print(hundredthousands); lcd.print(tenthousands); lcd.print(thousands); lcd.print("."); lcd.print(hundreds); lcd.print(tens); lcd.print(ones); lcd.print(" Mhz "); timepassed = millis(); memstatus = 0; // Trigger memory write }; void storeMEM(){ //Write each frequency section to a EPROM slot. Yes, it's cheating but it works! // записываем каждую цифру из значения частоты в слот EPROM EEPROM.write(0,millions); EEPROM.write(1,hundredthousands); EEPROM.write(2,tenthousands); EEPROM.write(3,thousands); EEPROM.write(4,hundreds); EEPROM.write(5,tens); EEPROM.write(6,ones); memstatus = 1; // Let program know memory has been written }; |
Видео, демонстрирующее работу проекта
Также можете посмотреть еще очень подробное обучающее видео (на английском языке) по принципам работы технологии SDR (если кто то хочет разобраться в этих вопросах поглубже).
12 ответов к “SDR радио на Arduino и DDS модуле AD9850”
Да, моя почта актульана
Я написал вам на почту
Здравствуйте. У меня для дипломного проекта это. Как мне сделать это?.
Добрый день. Что вы хотите сделать?
Этот проект я хочу сделать
Ну здесь вроде все описано как его делать, у вас какой то конкретный вопрос?
Можно купить этот проект. Можете ли вы сделать этот проект и прислать его мне?
К сожалению, пока не могу, нет доступа к необходимому железу поскольку сменил место работы.
Возможно с Вами как-то связаться?
Да, я могу написать вам на email, который вы использовали для написания данного комментария, если он корректный
Здравствуйте! А его можно импользовать без пк ?
Добрый день. Ну обычно все подобные простые SDR устройства подключаются к компьютеру для удобства отображения информации. А без компьютера вы что с его помощью хотите делать?