10kHz To 225MHz VFO
10kHz To 225MHz VFO
10kHz To 225MHz VFO
Version 2
For use in DIY homebrew radio equipment such superheterodyne single/double conversion receiver, SDR, HAM QRP
transceivers or RF generator.
IntermediateWork in progress82,651
Hardware components
Breadboard (generic)
× 1
Arduino Nano R3
× 1
Rotary Encoder with Push-Button
× 1
Capacitor 100 nF × 3
Capacitor 10 µF × 1
Capacitor 10 nF × 2
Resistor 1k ohm × 1
Inductor 100 uH × 1
Arduino IDE
Story
This is a project of a VFO (variable frequency oscillator) for use in DIY homebrew radio equipement such as
Superheterodyne Single / Double Conversion Receivers, DCR, SDR or Ham QRP Transceivers. It has a Bargraph
indicator for Signal Strenght (S-Meter) and 20 Band presets. Can be used as RF/Clock generator too. This is the new
version (V.2), I updated the previous project and it includes new features.
Features:
Operation range from 10kHz to 225MHz.
Tuning steps of 1Hz, 10Hz, 1kHz, 5kHz, 10kHz and 1MHz.
Intermediate Frequency (IF) offset (+ or -) adjustable.
20 Band Presets (shortcuts) to the BCB and HAM frequencies.
Generator funcion mode.
RX / TX Mode Selector for use in Homebrew QRP Transceivers.
Bargraph for Signal Meter through the analog input (ADC).
For use as Local Oscillator on Homebrew radio receivers such as Superheterodyne, SDR, Direct
Conversion and Homebrew QRP Transceivers.
For use in Double Conversion / Air Band Superhet Receivers in conjunction with Si4735 or Si4732 DSP
radio chip.
For use as a simple RF/Clock generator for calibration reference or clock generation.
Works with Arduino Uno, Nano and Pro Mini.
Uses a common 128x64 I2C OLED SSD1306 display and Si5351 module.
I2C data transfer, only 2 wires to connect the display / Si5351 and arduino.
High stability and precision for frequency generation.
Simple yet very efficient and free.
Update Jun, 2022: added an Alternative Version with support to bigger OLED SH1106 1.3" display and CW
Keying input, see more details on text.
Setup:
1/4
Schematics / wiring:
An old VFO from the 1960s. The Great-Grandfather of the VFO DDS:
An old VFO from the 1960s
In operation video:
For anyone interested in making a double conversion receiver with the SI5351 and SI4735(32), this is the block
diagram of the receiver blocks that I built and it works great. Using JCR 10kHz-225MHz VFO. The mixer is the
popular NE602 / SA612 IC.
Alternative Version (SH1106 - bigger display 1.3"):
Mr. Pablo Woiz (LU1AGP) did some adaptations in my code so that the original project now support the OLED 1.3"
display SH1106, CW keying input, has less steps, and CLK1 / CLK2 outputs activated for 2 intermediate frequencies
of USB/LSB. Mr. Woiz kindly sent me his version and asked to share it here. To download this alternative version
click here.
Notes: in this version the PIN A6 of Nano is used for CW Keying input (on/off the RF carrier) and it is a PULLUP
input, so it is activated when conected to the GND. Also, the CLK1 and CLK2 outputs a fixed IF frequency (BFO) for
SSB applications. The folder contains the main sketch, the hex file firmware and the SH1106 library.
Instructions:
Open the scketch on Arduino IDE, install all the required libraries.
Choose the preferences (see note) and compile the sketch and then load it to the Arduino Nano, Uno or Pro
Mini.
Follow the schematics to wire the Arduino, Display, Si5351 module, rotary encoder, etc.
Power up the Arduino.
Rotate the rotary encoder to tune up or down the frequency.
Push the push button 1 to change the frequency step tuning. The steps available are 1Hz, 10Hz, 1kHz,
5kHz, 10kHz and 1MHz.
Push the push button 2 to browse (select) the 20 band presets or enter the generator mode.
Turn on/off the switch SW 2 to change from RX to TX mode. RX mode = SW 2 Open and TX mode = SW 2
Closed to GND. When in TX mode, the IF value is not added/sub from the RF out. This is ideal for use in Homebrew
QRP Transceivers.
Connect the S-Meter output signal from your radio to the X2 connector (S-Meter input). This input has
adjustable sensitivity, the gain must be adjusted in Sketch, accepting signals from 500mV to 5V (max).
Known Issue: if it freezes in the initialization text, comment (put a //) at the line 77 statup_text ();
#define IF 455 //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz, 0 = to direct convert receiver or RF
generator, + will add and - will subtract IF offfset.
#define BAND_INIT 7 //Enter your initial Band (1-21) at startup, ex: 1 = Freq Generator, 2 = 800kHz (MW), 7 =
7.2MHz (40m), 11 = 14.1MHz (20m).
#define XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value will
decreases the frequency and vice versa.
#define S_GAIN 303 //Adjust the sensitivity of Signal Meter A/D input: 101 = 500mv; 202 = 1v; 303 = 1.5v; 404 = 2v;
505 = 2.5v; 1010 = 5v (max).
#define rx_tx A2 //The pin used by RX / TX selector switch, RX = switch open, TX = switch closed to GND. When in
TX, the IF is not considered.
This project is being sold on eBay and Aliexpress as a CLONE, already assembled including internal rechargeable
battery. In case anyone is interested, this is the picture of it.
Disclaimer: The author of this project has no connection or any responsability with the sale of this assembled product.
This product is not a complete radio transceiver, as described in the sales ad, it works only as a VFO / Continuous
RF Generator.
Important Notes:
The author of this project has no responsibility for the products (clones) being traded via China, as the
manufacture and sale of these products has no connection with the author. This project is open source and is not
intended for commercial profit.
The author of this project reserves the right to change, modify or do corrections to the hardware and/or
software at any time without notice or obligation to persons who already assembled it.
Don't expect this project to perform as well or better than professional and commercial equipments, this is
an amateur DIY home project that aims at the personal satisfaction of setting up at home and seeing it work beyond
the learning that this activity provides.
//Libraries
#include <Wire.h> //IDE Standard
#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
#include <si5351.h> //Etherkit https://github.com/etherkit/Si5351Arduino
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
//User preferences
//------------------------------------------------------------------------------------------------------------
#define IF 455 //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz, 0 = to direct convert receiver or RF
generator, + will add and - will subtract IF offfset.
#define BAND_INIT 7 //Enter your initial Band (1-21) at startup, ex: 1 = Freq Generator, 2 = 800kHz (MW), 7 = 7.2MHz
(40m), 11 = 14.1MHz (20m).
#define XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value will decreases the
frequency and vice versa.
#define S_GAIN 303 //Adjust the sensitivity of Signal Meter A/D input: 101 = 500mv; 202 = 1v; 303 = 1.5v; 404 = 2v; 505
= 2.5v; 1010 = 5v (max).
#define tunestep A0 //The pin used by tune step push button.
#define band A1 //The pin used by band selector push button.
#define rx_tx A2 //The pin used by RX / TX selector switch, RX = switch open, TX = switch closed to GND. When in TX,
the IF value is not considered.
#define adc A3 //The pin used by Signal Meter A/D input.
//------------------------------------------------------------------------------------------------------------
ISR(PCINT2_vect) {
char result = r.process();
if (result == DIR_CW) set_frequency(1);
else if (result == DIR_CCW) set_frequency(-1);
}
void setup() {
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.display();
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(tunestep, INPUT_PULLUP);
pinMode(band, INPUT_PULLUP);
pinMode(rx_tx, INPUT_PULLUP);
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_correction(cal, SI5351_PLL_INPUT_XO);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.output_enable(SI5351_CLK0, 1); //1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 0);
count = BAND_INIT;
bandpresets();
stp = 4;
setstep();
}
void loop() {
if (freqold != freq) {
time_now = millis();
tunegen();
freqold = freq;
}
if (interfreqold != interfreq) {
time_now = millis();
tunegen();
interfreqold = interfreq;
}
if (xo != x) {
time_now = millis();
xo = x;
}
if (digitalRead(tunestep) == LOW) {
time_now = (millis() + 300);
setstep();
delay(300);
}
if (digitalRead(band) == LOW) {
time_now = (millis() + 300);
inc_preset();
delay(300);
}
if (digitalRead(rx_tx) == LOW) {
time_now = (millis() + 300);
sts = 1;
} else sts = 0;
void tunegen() {
si5351.set_freq((freq + (interfreq * 1000ULL)) * 100ULL, SI5351_CLK0);
}
void displayfreq() {
unsigned int m = freq / 1000000;
unsigned int k = (freq % 1000000) / 1000;
unsigned int h = (freq % 1000) / 1;
display.clearDisplay();
display.setTextSize(2);
void setstep() {
switch (stp) {
case 1: stp = 2; fstep = 1; break;
case 2: stp = 3; fstep = 10; break;
case 3: stp = 4; fstep = 1000; break;
case 4: stp = 5; fstep = 5000; break;
case 5: stp = 6; fstep = 10000; break;
case 6: stp = 1; fstep = 1000000; break;
}
}
void inc_preset() {
count++;
if (count > 21) count = 1;
bandpresets();
delay(50);
}
void bandpresets() {
switch (count) {
case 1: freq = 100000; tunegen(); break;
case 2: freq = 800000; break;
case 3: freq = 1800000; break;
case 4: freq = 3650000; break;
case 5: freq = 4985000; break;
case 6: freq = 6180000; break;
case 7: freq = 7200000; break;
case 8: freq = 10000000; break;
case 9: freq = 11780000; break;
case 10: freq = 13630000; break;
case 11: freq = 14100000; break;
case 12: freq = 15000000; break;
case 13: freq = 17655000; break;
case 14: freq = 21525000; break;
case 15: freq = 27015000; break;
case 16: freq = 28400000; break;
case 17: freq = 50000000; break;
case 18: freq = 100000000; break;
case 19: freq = 130000000; break;
case 20: freq = 144000000; break;
case 21: freq = 220000000; break;
}
si5351.pll_reset(SI5351_PLLA);
stp = 4; setstep();
}
void layout() {
display.setTextColor(WHITE);
display.drawLine(0, 20, 127, 20, WHITE);
display.drawLine(0, 43, 127, 43, WHITE);
display.drawLine(105, 24, 105, 39, WHITE);
display.drawLine(87, 24, 87, 39, WHITE);
display.drawLine(87, 48, 87, 63, WHITE);
display.drawLine(15, 55, 82, 55, WHITE);
display.setTextSize(1);
display.setCursor(59, 23);
display.print("STEP");
display.setCursor(54, 33);
if (stp == 2) display.print(" 1Hz"); if (stp == 3) display.print(" 10Hz"); if (stp == 4) display.print(" 1kHz");
if (stp == 5) display.print(" 5kHz"); if (stp == 6) display.print("10kHz"); if (stp == 1) display.print(" 1MHz");
display.setTextSize(1);
display.setCursor(92, 48);
display.print("IF:");
display.setCursor(92, 57);
display.print(interfreq);
display.print("k");
display.setTextSize(1);
display.setCursor(110, 23);
if (freq < 1000000) display.print("kHz");
if (freq >= 1000000) display.print("MHz");
display.setCursor(110, 33);
if (interfreq == 0) display.print("VFO");
if (interfreq != 0) display.print("L O");
display.setCursor(91, 28);
if (!sts) display.print("RX"); if (!sts) interfreq = IF;
if (sts) display.print("TX"); if (sts) interfreq = 0;
bandlist(); drawbargraph();
display.display();
}
void bandlist() {
display.setTextSize(2);
display.setCursor(0, 25);
if (count == 1) display.print("GEN"); if (count == 2) display.print("MW"); if (count == 3) display.print("160m"); if (count ==
4) display.print("80m");
if (count == 5) display.print("60m"); if (count == 6) display.print("49m"); if (count == 7) display.print("40m"); if (count ==
8) display.print("31m");
if (count == 9) display.print("25m"); if (count == 10) display.print("22m"); if (count == 11) display.print("20m"); if (count ==
12) display.print("19m");
if (count == 13) display.print("16m"); if (count == 14) display.print("13m"); if (count == 15) display.print("11m"); if (count
== 16) display.print("10m");
if (count == 17) display.print("6m"); if (count == 18) display.print("WFM"); if (count == 19) display.print("AIR"); if (count ==
20) display.print("2m");
if (count == 21) display.print("1m");
if (count == 1) interfreq = 0; else if (!sts) interfreq = IF;
}
void sgnalread() {
smval = analogRead(adc); x = map(smval, 0, S_GAIN, 1, 14); if (x > 14) x = 14;
}
void drawbargraph() {
byte y = map(n, 1, 42, 1, 14);
display.setTextSize(1);
//Pointer
display.setCursor(0, 48); display.print("TU");
switch (y) {
case 1: display.fillRect(15, 48, 2, 6, WHITE); break;
case 2: display.fillRect(20, 48, 2, 6, WHITE); break;
case 3: display.fillRect(25, 48, 2, 6, WHITE); break;
case 4: display.fillRect(30, 48, 2, 6, WHITE); break;
case 5: display.fillRect(35, 48, 2, 6, WHITE); break;
case 6: display.fillRect(40, 48, 2, 6, WHITE); break;
case 7: display.fillRect(45, 48, 2, 6, WHITE); break;
case 8: display.fillRect(50, 48, 2, 6, WHITE); break;
case 9: display.fillRect(55, 48, 2, 6, WHITE); break;
case 10: display.fillRect(60, 48, 2, 6, WHITE); break;
case 11: display.fillRect(65, 48, 2, 6, WHITE); break;
case 12: display.fillRect(70, 48, 2, 6, WHITE); break;
case 13: display.fillRect(75, 48, 2, 6, WHITE); break;
case 14: display.fillRect(80, 48, 2, 6, WHITE); break;
}
//Bargraph
display.setCursor(0, 57); display.print("SM");
switch (x) {
case 14: display.fillRect(80, 58, 2, 6, WHITE);
case 13: display.fillRect(75, 58, 2, 6, WHITE);
case 12: display.fillRect(70, 58, 2, 6, WHITE);
case 11: display.fillRect(65, 58, 2, 6, WHITE);
case 10: display.fillRect(60, 58, 2, 6, WHITE);
case 9: display.fillRect(55, 58, 2, 6, WHITE);
case 8: display.fillRect(50, 58, 2, 6, WHITE);
case 7: display.fillRect(45, 58, 2, 6, WHITE);
case 6: display.fillRect(40, 58, 2, 6, WHITE);
case 5: display.fillRect(35, 58, 2, 6, WHITE);
case 4: display.fillRect(30, 58, 2, 6, WHITE);
case 3: display.fillRect(25, 58, 2, 6, WHITE);
case 2: display.fillRect(20, 58, 2, 6, WHITE);
case 1: display.fillRect(15, 58, 2, 6, WHITE);
}
}
void statup_text() {
display.setTextSize(1); display.setCursor(13, 18);
display.print("Si5351 VFO/RF GEN");
display.setCursor(6, 40);
display.print("JCR RADIO - Ver 2.0");
display.display(); delay(2000);
}
Credits
CesarSound
6 projects • 142 followers
FollowContact
Хардверске компоненте
Ардуино Нано Р3
× 1
Прекидач, СПДТ
× 2
Кондензатор 100 нФ × 3
Кондензатор 10 µФ × 1
Кондензатор 10 нФ × 2
Отпорник 1к ома × 1
Индуктор 100 уХ × 1
Прича
Ово је пројекат ВФО (осцилатора променљиве фреквенције) за употребу у кућној радио опреми као што су
суперхетеродински пријемници са једном/двоструком конверзијом, ДЦР, СДР или Хам КРП
примопредајници. Има барграф индикатор за јачину сигнала (С-метар) и 20 унапред подешених опсега. Може
се користити и као РФ/Цлоцк генератор. Ово је нова верзија (В.2), ажурирао сам претходни пројекат и
укључује нове функције.
Карактеристике:
Радни опсег од 10кХз до 225МХз.
Кораци подешавања од 1Хз, 10Хз, 1кХз, 5кХз, 10кХз и 1МХз.
Померање средње фреквенције (ИФ) (+ или -) подесиво.
20 унапред подешених опсега (пречица) за БЦБ и ХАМ фреквенције.
Режим рада генератора.
Бирач РКС / ТКС режима за употребу у Хомебрев КРП примопредајницима.
Барграф за мерач сигнала преко аналогног улаза (АДЦ).
За употребу као локални осцилатор на Хомебрев радио пријемницима као што су Суперхетеродине,
СДР, Дирецт Цонверсион и Хомебрев КРП примопредајници.
За употребу у Суперхет пријемницима са двоструком конверзијом / Аир Банд у комбинацији са
Си4735 или Си4732 ДСП радио чипом.
За употребу као једноставан РФ/Цлоцк генератор за референцу калибрације или генерисање такта.
Ради са Ардуино Уно, Нано и Про Мини.
Користи уобичајени 128к64 И2Ц ОЛЕД ССД1306 екран и Си5351 модул.
И2Ц пренос података, само 2 жице за повезивање екрана / Си5351 и ардуино.
Висока стабилност и прецизност за генерисање фреквенције.
Једноставно, али веома ефикасно и бесплатно.
Ажурирање јуна 2022.: додата је алтернативна верзија са подршком за већи ОЛЕД СХ1106 екран од
1,3 инча и ЦВ Кеиинг унос, погледајте више детаља о тексту.
Подесити:
1/4
Шеме / ожичење:
Стари ВФО из 1960-их. Прадеда ВФО ДДС:
Стари ВФО из 1960-их
Видео у раду:
За све заинтересоване да направе пријемник са двоструком конверзијом са СИ5351 и СИ4735(32), ово је блок
дијаграм блокова пријемника који сам направио и одлично ради. Коришћење ЈЦР 10кХз-225МХз ВФО. Миксер
је популарни НЕ602 / СА612 ИЦ.
Алтернативна верзија (СХ1106 - већи екран од 1,3"):
Г. Пабло Воиз (ЛУ1АГП) је урадио неке адаптације у мом коду тако да оригинални пројекат сада подржава
ОЛЕД 1,3" екран СХ1106, ЦВ улаз, има мање корака и ЦЛК1 / ЦЛК2 излази активирани за 2 средње
фреквенције УСБ/ЛСБ. Господин Воиз ми је љубазно послао своју верзију и замолио да је поделим овде. Да
преузмете ову алтернативну верзију кликните овде.
Упутства:
Отворите скеч на Ардуино ИДЕ, инсталирајте све потребне библиотеке.
Одаберите жељене поставке (погледајте напомену) и компајлирајте скицу, а затим је учитајте у
Ардуино Нано, Уно или Про Мини.
Пратите шеме да повежете Ардуино, екран, Си5351 модул, ротациони енкодер итд.
Укључите Ардуино.
Ротирајте ротациони енкодер да бисте подесили фреквенцију навише или на ниже.
Притисните дугме 1 да промените подешавање корака фреквенције. Доступни кораци су 1Хз, 10Хз,
1кХз, 5кХз, 10кХз и 1МХз.
Притисните дугме 2 да бисте претражили (изабрали) 20 унапред подешених опсега или ушли у режим
генератора.
Укључите/искључите прекидач СВ 2 да бисте променили режим РКС у ТКС. РКС режим = СВ 2
Отворен и ТКС режим = СВ 2 Затворен на ГНД. Када је у ТКС режиму, ИФ вредност се не додаје/подизводи
са РФ излаза. Ово је идеално за употребу у Хомебрев КРП примопредајницима.
Повежите излазни сигнал С-метра са вашег радија на Кс2 конектор (улаз за С-метар). Овај улаз има
подесиву осетљивост, појачање се мора подесити у Скетцх-у, прихватајући сигнале од 500мВ до 5В (мак).
Познати проблем: ако се замрзне у тексту иницијализације, коментаришите (ставите //) у ред 77
статуп_тект ();
#дефине ИФ 455 //Унесите своју ИФ фреквенцију, на пример: 455 = 455кХз, 10700 = 10,7МХз, 0 = за директно
претварање пријемника или РФ генератора, + ће додати и - одузети ИФ офсет.
#дефине БАНД_ИНИТ 7 //Унесите свој почетни опсег (1-21) при покретању, на пример: 1 = Фреквентни
генератор, 2 = 800 кХз (МВ), 7 = 7,2 МХз (40 м), 11 = 14,1 МХз (20 м).
#дефине КСТ_ЦАЛ_Ф 33000 //Си5351 фактор калибрације, подесите да добијете тачно 10МХз. Повећање ове
вредности ће смањити фреквенцију и обрнуто.
#дефине С_ГАИН 303 //Подесите осетљивост А/Д улаза мерача сигнала: 101 = 500мв; 202 = 1в; 303 =
1.5в; 404 = 2в; 505 = 2.5в; 1010 = 5В (макс.).
#дефине рк_тк А2 //Пин који користи РКС / ТКС селекторски прекидач, РКС = прекидач отворен, ТКС =
прекидач затворен на ГНД. Када сте у ТКС, ИФ се не узима у обзир.
Овај пројекат се продаје на еБаи-у и Алиекпресс-у као КЛОН, већ састављен укључујући интерну пуњиву
батерију. Ако је неко заинтересован, ово је слика.
Одрицање од одговорности: Аутор овог пројекта нема никакве везе или било какву одговорност са продајом
овог састављеног производа. Овај производ није комплетан радио примопредајник, као што је описано у
продајном огласу, он ради само као ВФО / Континуални РФ генератор.
Важне напомене:
Аутор овог пројекта не сноси одговорност за производе (клонове) којима се тргује преко Кине, јер
производња и продаја ових производа нема везе са аутором. Овај пројекат је отвореног кода и није намењен
комерцијалном профиту.
Аутор овог пројекта задржава право да промени, модификује или изврши корекције хардвера и/или
софтвера у било ком тренутку без обавештења или обавезе према особама које су га већ монтирале.
Не очекујте да ће овај пројекат бити добар или бољи од професионалне и комерцијалне опреме, ово
је аматерски „уради сам“ кућни пројекат који има за циљ лично задовољство постављања код куће и
гледања како функционише изван учења које ова активност пружа.
//Libraries
#include <Wire.h> //IDE Standard
#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
#include <si5351.h> //Etherkit https://github.com/etherkit/Si5351Arduino
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
//User preferences
//------------------------------------------------------------------------------------------------------------
#define IF 455 //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz, 0 = to direct convert receiver or RF
generator, + will add and - will subtract IF offfset.
#define BAND_INIT 7 //Enter your initial Band (1-21) at startup, ex: 1 = Freq Generator, 2 = 800kHz (MW), 7 = 7.2MHz
(40m), 11 = 14.1MHz (20m).
#define XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value will decreases the
frequency and vice versa.
#define S_GAIN 303 //Adjust the sensitivity of Signal Meter A/D input: 101 = 500mv; 202 = 1v; 303 = 1.5v; 404 = 2v; 505
= 2.5v; 1010 = 5v (max).
#define tunestep A0 //The pin used by tune step push button.
#define band A1 //The pin used by band selector push button.
#define rx_tx A2 //The pin used by RX / TX selector switch, RX = switch open, TX = switch closed to GND. When in TX,
the IF value is not considered.
#define adc A3 //The pin used by Signal Meter A/D input.
//------------------------------------------------------------------------------------------------------------
ИСР ( ПЦИНТ2_вецт ) {
цхар резултат = р . процес ();
иф ( резултат == ДИР_ЦВ ) сет_фрекуенци ( 1 );
елсе иф ( резултат == ДИР_ЦЦВ ) сет_фрекуенци ( - 1 );
}
void setup() {
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.display();
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(tunestep, INPUT_PULLUP);
pinMode(band, INPUT_PULLUP);
pinMode(rx_tx, INPUT_PULLUP);
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_correction(cal, SI5351_PLL_INPUT_XO);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
si5351.output_enable(SI5351_CLK0, 1); //1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 0);
si5351.output_enable(SI5351_CLK2, 0);
count = BAND_INIT;
bandpresets();
stp = 4;
setstep();
}
void loop() {
if (freqold != freq) {
time_now = millis();
tunegen();
freqold = freq;
}
if (interfreqold != interfreq) {
time_now = millis();
tunegen();
interfreqold = interfreq;
}
if (xo != x) {
time_now = millis();
xo = x;
}
if (digitalRead(tunestep) == LOW) {
time_now = (millis() + 300);
setstep();
delay(300);
}
if (digitalRead(band) == LOW) {
time_now = (millis() + 300);
inc_preset();
delay(300);
}
if (digitalRead(rx_tx) == LOW) {
time_now = (millis() + 300);
sts = 1;
} else sts = 0;
void tunegen() {
si5351.set_freq((freq + (interfreq * 1000ULL)) * 100ULL, SI5351_CLK0);
}
void displayfreq() {
unsigned int m = freq / 1000000;
unsigned int k = (freq % 1000000) / 1000;
unsigned int h = (freq % 1000) / 1;
display.clearDisplay();
display.setTextSize(2);
void setstep() {
switch (stp) {
case 1: stp = 2; fstep = 1; break;
case 2: stp = 3; fstep = 10; break;
case 3: stp = 4; fstep = 1000; break;
case 4: stp = 5; fstep = 5000; break;
case 5: stp = 6; fstep = 10000; break;
case 6: stp = 1; fstep = 1000000; break;
}
}
void inc_preset() {
count++;
if (count > 21) count = 1;
bandpresets();
delay(50);
}
void bandpresets() {
switch (count) {
case 1: freq = 100000; tunegen(); break;
case 2: freq = 800000; break;
case 3: freq = 1800000; break;
case 4: freq = 3650000; break;
case 5: freq = 4985000; break;
case 6: freq = 6180000; break;
case 7: freq = 7200000; break;
case 8: freq = 10000000; break;
case 9: freq = 11780000; break;
case 10: freq = 13630000; break;
case 11: freq = 14100000; break;
case 12: freq = 15000000; break;
case 13: freq = 17655000; break;
case 14: freq = 21525000; break;
case 15: freq = 27015000; break;
case 16: freq = 28400000; break;
case 17: freq = 50000000; break;
case 18: freq = 100000000; break;
case 19: freq = 130000000; break;
case 20: freq = 144000000; break;
case 21: freq = 220000000; break;
}
si5351.pll_reset(SI5351_PLLA);
stp = 4; setstep();
}
void layout() {
display.setTextColor(WHITE);
display.drawLine(0, 20, 127, 20, WHITE);
display.drawLine(0, 43, 127, 43, WHITE);
display.drawLine(105, 24, 105, 39, WHITE);
display.drawLine(87, 24, 87, 39, WHITE);
display.drawLine(87, 48, 87, 63, WHITE);
display.drawLine(15, 55, 82, 55, WHITE);
display.setTextSize(1);
display.setCursor(59, 23);
display.print("STEP");
display.setCursor(54, 33);
if (stp == 2) display.print(" 1Hz"); if (stp == 3) display.print(" 10Hz"); if (stp == 4) display.print(" 1kHz");
if (stp == 5) display.print(" 5kHz"); if (stp == 6) display.print("10kHz"); if (stp == 1) display.print(" 1MHz");
display.setTextSize(1);
display.setCursor(92, 48);
display.print("IF:");
display.setCursor(92, 57);
display.print(interfreq);
display.print("k");
display.setTextSize(1);
display.setCursor(110, 23);
if (freq < 1000000) display.print("kHz");
if (freq >= 1000000) display.print("MHz");
display.setCursor(110, 33);
if (interfreq == 0) display.print("VFO");
if (interfreq != 0) display.print("L O");
display.setCursor(91, 28);
if (!sts) display.print("RX"); if (!sts) interfreq = IF;
if (sts) display.print("TX"); if (sts) interfreq = 0;
bandlist(); drawbargraph();
display.display();
}
void bandlist() {
display.setTextSize(2);
display.setCursor(0, 25);
if (count == 1) display.print("GEN"); if (count == 2) display.print("MW"); if (count == 3) display.print("160m"); if (count ==
4) display.print("80m");
if (count == 5) display.print("60m"); if (count == 6) display.print("49m"); if (count == 7) display.print("40m"); if (count ==
8) display.print("31m");
if (count == 9) display.print("25m"); if (count == 10) display.print("22m"); if (count == 11) display.print("20m"); if (count ==
12) display.print("19m");
if (count == 13) display.print("16m"); if (count == 14) display.print("13m"); if (count == 15) display.print("11m"); if (count
== 16) display.print("10m");
if (count == 17) display.print("6m"); if (count == 18) display.print("WFM"); if (count == 19) display.print("AIR"); if (count ==
20) display.print("2m");
if (count == 21) display.print("1m");
if (count == 1) interfreq = 0; else if (!sts) interfreq = IF;
}
void sgnalread() {
smval = analogRead(adc); x = map(smval, 0, S_GAIN, 1, 14); if (x > 14) x = 14;
}
void drawbargraph() {
byte y = map(n, 1, 42, 1, 14);
display.setTextSize(1);
//Pointer
display.setCursor(0, 48); display.print("TU");
switch (y) {
case 1: display.fillRect(15, 48, 2, 6, WHITE); break;
case 2: display.fillRect(20, 48, 2, 6, WHITE); break;
case 3: display.fillRect(25, 48, 2, 6, WHITE); break;
case 4: display.fillRect(30, 48, 2, 6, WHITE); break;
case 5: display.fillRect(35, 48, 2, 6, WHITE); break;
case 6: display.fillRect(40, 48, 2, 6, WHITE); break;
case 7: display.fillRect(45, 48, 2, 6, WHITE); break;
case 8: display.fillRect(50, 48, 2, 6, WHITE); break;
case 9: display.fillRect(55, 48, 2, 6, WHITE); break;
case 10: display.fillRect(60, 48, 2, 6, WHITE); break;
case 11: display.fillRect(65, 48, 2, 6, WHITE); break;
case 12: display.fillRect(70, 48, 2, 6, WHITE); break;
case 13: display.fillRect(75, 48, 2, 6, WHITE); break;
case 14: display.fillRect(80, 48, 2, 6, WHITE); break;
}
//Bargraph
display.setCursor(0, 57); display.print("SM");
switch (x) {
case 14: display.fillRect(80, 58, 2, 6, WHITE);
case 13: display.fillRect(75, 58, 2, 6, WHITE);
case 12: display.fillRect(70, 58, 2, 6, WHITE);
case 11: display.fillRect(65, 58, 2, 6, WHITE);
case 10: display.fillRect(60, 58, 2, 6, WHITE);
case 9: display.fillRect(55, 58, 2, 6, WHITE);
case 8: display.fillRect(50, 58, 2, 6, WHITE);
case 7: display.fillRect(45, 58, 2, 6, WHITE);
case 6: display.fillRect(40, 58, 2, 6, WHITE);
case 5: display.fillRect(35, 58, 2, 6, WHITE);
case 4: display.fillRect(30, 58, 2, 6, WHITE);
case 3: display.fillRect(25, 58, 2, 6, WHITE);
case 2: display.fillRect(20, 58, 2, 6, WHITE);
case 1: display.fillRect(15, 58, 2, 6, WHITE);
}
}
void statup_text() {
дисплеј . сетТектСизе ( 1 ); дисплеј . сетЦурсор ( 13 , 18 );
дисплеј . принт ( "Си5351 ВФО/РФ ГЕН" );
дисплеј . сетЦурсор ( 6 , 40 );
дисплеј . принт ( "ЈЦР РАДИО - Вер 2.0" );
дисплеј . дисплаи (); кашњење ( 2000 );
}
Цредитс
ЦесарСоунд
6 пројеката • 142 пратиоца
ПратитиКонтакт