• 10 kHz to 225 MHz VFO/RF Generator with Si5351 – Version 2

QC

10 kHz to 225 MHz VFO/RF Generator with Si5351 – Version 2

For use in DIY homebrew radio equipment such as single/dual conversion superheterodyne receivers, SDR, HAM QRP transceivers or RF generators.

Devices and components

Arduino-Nano

10 µF capacitor

100 uH inductor

Toggle switch, SPDT

RCA JACK FOR RF OUTPUT CONNECTION

100nF capacitor

Adafruit SSD1306 128X64 OLED SCREEN

10nF capacitor

Breadboard (generic)

Adafruit SI5351 CLOCK GENERATION MODULE

Resistance 1k ohm

Rotary encoder with push button

Software and tools

Arduino IDE

Project description

Operating range from 10 kHz to 225 MHz.

Step adjustments of 1 Hz, 10 Hz, 1 kHz, 5 kHz, 10 kHz and 1 MHz.

Adjustable intermediate frequency (IF) offset (+ or -).

20 band presets (shortcuts) to BCB and HAM frequencies.

Generator function mode.

RX/TX mode selector for use in QRP Homebrew transceivers.

For use as a local oscillator on Homebrew radio receivers such as Superheterodyne, SDR, Direct Conversion and Homebrew QRP transceivers.

For use in double conversion/airband Superhet receivers in conjunction with the Si4735 or Si4732 DSP radio chip.

Use as a simple RF/clock generator for calibration reference or clock generation.

Works with Arduino Uno, Nano and Pro Mini.

Uses common 128x64 I2C OLED SSD1306 display and Si5351 module.

I2C data transfer, only 2 wires to connect display/Si5351 and arduino.

High stability and precision for frequency generation.

Simple but very effective and free.

June 2022 Update: Added alternate version with support for larger 1.3" SH1106 OLED display and CW input input, see more details on text.

Open the sketch on Arduino IDE, install all required libraries.

Choose the preferences (see note) and compile the sketch, then upload it to the Arduino Nano, Uno or Pro Mini.

Follow the diagrams to wire the Arduino, display, Si5351 module, rotary encoder, etc.

Power on the Arduino.

Rotate the rotary encoder to increase or decrease the frequency.

Press push button 1 to change the frequency step setting. The available steps are 1 Hz, 10 Hz, 1 kHz, 5 kHz, 10 kHz and 1 MHz.

Press push button 2 to cycle through (select) the 20 band presets or enter generator mode.

Turn SW switch 2 on/off to switch from RX mode to TX mode. RX mode = SW 2 open and TX mode = SW 2 closed to GND. In TX mode, the IF value is not added/sub from the RF output. This is ideal for use in QRP Homebrew transceivers.

Connect the S-Meter output signal from your radio to connector X2 (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 hangs in the initialization text, comment out (put a //) on line 77 statup_text();

The author of this project takes no responsibility for (clone) products marketed 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 make corrections to the hardware and/or software at any time without notice or obligation to the people who have already assembled it.

Don't expect this project to work as well or better than professional and commercial equipment, this is an amateur DIY project that aims for the personal satisfaction of setting up at home and seeing it work beyond the learning this activity provides.

Sketch SI5351_VFO_RF_GEN_OLED_JCR_V2

Load it onto Arduino.

1/**********************************************************************************************************
2
3 10kHz to 225MHz VFO / RF Generator with Si5351 and Arduino Nano, with Intermediate
4 Frequency (IF) offset
5 (+ or -), RX/TX Selector for QRP Transceivers, Band Presets
6 and Bargraph S-Meter. See the schematics for
7 wiring and README.txt for details.
8 By J. CesarSound - ver 2.0 - Feb/2021.
9***********************************************************************************************************/
10
11//Libraries
12#include
13 <Wire.h> //IDE Standard
14#include <Rotary.h> //Ben
15 Buxton https://github.com/brianlow/Rotary
16#include <si5351.h> //Etherkit
17 https://github.com/etherkit/Si5351Arduino
18#include <Adafruit_GFX.h> //Adafruit
19 GFX https://github.com/adafruit/Adafruit-GFX-Library
20#include <Adafruit_SSD1306.h>
21 //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
22
23//User
24 preferences
25//------------------------------------------------------------------------------------------------------------
26#define
27 IF 455 //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz,
28 0 = to direct convert receiver or RF generator, + will add and - will subtract IF
29 offfset.
30#define BAND_INIT 7 //Enter your initial Band (1-21) at startup,
31 ex: 1 = Freq Generator, 2 = 800kHz (MW), 7 = 7.2MHz (40m), 11 = 14.1MHz (20m).
32#define
33 XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing
34 this value will decreases the frequency and vice versa.
35#define S_GAIN 303
36 //Adjust the sensitivity of Signal Meter A/D input: 101 = 500mv; 202 = 1v;
37 303 = 1.5v; 404 = 2v; 505 = 2.5v; 1010 = 5v (max).
38#define tunestep A0 //The
39 pin used by tune step push button.
40#define band A1 //The pin used
41 by band selector push button.
42#define rx_tx A2 //The pin used by
43 RX / TX selector switch, RX = switch open, TX = switch closed to GND. When in TX,
44 the IF value is not considered.
45#define adc A3 //The pin used by
46 Signal Meter A/D input.
47//------------------------------------------------------------------------------------------------------------
48
49Rotary
50 r = Rotary(2, 3);
51Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
52Si5351
53 si5351(0x60); //Si5351 I2C Address 0x60
54
55unsigned long freq, freqold, fstep;
56long
57 interfreq = IF, interfreqold = 0;
58long cal = XT_CAL_F;
59unsigned int smval;
60byte
61 encoder = 1;
62byte stp, n = 1;
63byte count, x, xo;
64bool sts = 0;
65unsigned
66 int period = 100;
67unsigned long time_now = 0;
68
69ISR(PCINT2_vect) {
70 char
71 result = r.process();
72 if (result == DIR_CW) set_frequency(1);
73 else if
74 (result == DIR_CCW) set_frequency(-1);
75}
76
77void set_frequency(short dir)
78 {
79 if (encoder == 1) { //Up/Down frequency
80 if
81 (dir == 1) freq = freq + fstep;
82 if (freq >= 225000000) freq = 225000000;
83
84 if (dir == -1) freq = freq - fstep;
85 if (fstep == 1000000 && freq <= 1000000)
86 freq = 1000000;
87 else if (freq < 10000) freq = 10000;
88 }
89 if (encoder
90 == 1) { //Up/Down graph tune pointer
91 if (dir == 1)
92 n = n + 1;
93 if (n > 42) n = 1;
94 if (dir == -1) n = n - 1;
95 if
96 (n < 1) n = 42;
97 }
98}
99
100void setup() {
101 Wire.begin();
102 display.begin(SSD1306_SWITCHCAPVCC,
103 0x3C);
104 display.clearDisplay();
105 display.setTextColor(WHITE);
106 display.display();
107
108
109 pinMode(2, INPUT_PULLUP);
110 pinMode(3, INPUT_PULLUP);
111 pinMode(tunestep,
112 INPUT_PULLUP);
113 pinMode(band, INPUT_PULLUP);
114 pinMode(rx_tx, INPUT_PULLUP);
115
116
117 //statup_text(); //If you hang on startup, comment
118
119 si5351.init(SI5351_CRYSTAL_LOAD_8PF,
120 0, 0);
121 si5351.set_correction(cal, SI5351_PLL_INPUT_XO);
122 si5351.drive_strength(SI5351_CLK0,
123 SI5351_DRIVE_8MA);
124 si5351.output_enable(SI5351_CLK0, 1); //1
125 - Enable / 0 - Disable CLK
126 si5351.output_enable(SI5351_CLK1, 0);
127 si5351.output_enable(SI5351_CLK2,
128 0);
129
130 PCICR |= (1 << PCIE2);
131 PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
132
133 sei();
134
135 count = BAND_INIT;
136 bandpresets();
137 stp = 4;
138 setstep();
139}
140
141void
142 loop() {
143 if (freqold != freq) {
144 time_now = millis();
145 tunegen();
146
147 freqold = freq;
148 }
149
150 if (interfreqold != interfreq) {
151 time_now
152 = millis();
153 tunegen();
154 interfreqold = interfreq;
155 }
156
157 if
158 (xo != x) {
159 time_now = millis();
160 xo = x;
161 }
162
163 if (digitalRead(tunestep)
164 == LOW) {
165 time_now = (millis() + 300);
166 setstep();
167 delay(300);
168
169 }
170
171 if (digitalRead(band) == LOW) {
172 time_now = (millis() + 300);
173
174 inc_preset();
175 delay(300);
176 }
177
178 if (digitalRead(rx_tx) == LOW)
179 {
180 time_now = (millis() + 300);
181 sts = 1;
182 } else sts = 0;
183
184
185 if ((time_now + period) > millis()) {
186 displayfreq();
187 layout();
188
189 }
190 sgnalread();
191}
192
193void tunegen() {
194 si5351.set_freq((freq +
195 (interfreq * 1000ULL)) * 100ULL, SI5351_CLK0);
196}
197
198void displayfreq() {
199
200 unsigned int m = freq / 1000000;
201 unsigned int k = (freq % 1000000) / 1000;
202
203 unsigned int h = (freq % 1000) / 1;
204
205 display.clearDisplay();
206 display.setTextSize(2);
207
208
209 char buffer[15] = "";
210 if (m < 1) {
211 display.setCursor(41, 1); sprintf(buffer,
212 "%003d.%003d", k, h);
213 }
214 else if (m < 100) {
215 display.setCursor(5,
216 1); sprintf(buffer, "%2d.%003d.%003d", m, k, h);
217 }
218 else if (m >= 100)
219 {
220 unsigned int h = (freq % 1000) / 10;
221 display.setCursor(5, 1); sprintf(buffer,
222 "%2d.%003d.%02d", m, k, h);
223 }
224 display.print(buffer);
225}
226
227void
228 setstep() {
229 switch (stp) {
230 case 1: stp = 2; fstep = 1; break;
231 case
232 2: stp = 3; fstep = 10; break;
233 case 3: stp = 4; fstep = 1000; break;
234
235 case 4: stp = 5; fstep = 5000; break;
236 case 5: stp = 6; fstep = 10000;
237 break;
238 case 6: stp = 1; fstep = 1000000; break;
239 }
240}
241
242void inc_preset()
243 {
244 count++;
245 if (count > 21) count = 1;
246 bandpresets();
247 delay(50);
248}
249
250void
251 bandpresets() {
252 switch (count) {
253 case 1: freq = 100000; tunegen();
254 break;
255 case 2: freq = 800000; break;
256 case 3: freq = 1800000; break;
257
258 case 4: freq = 3650000; break;
259 case 5: freq = 4985000; break;
260 case
261 6: freq = 6180000; break;
262 case 7: freq = 7200000; break;
263 case 8: freq
264 = 10000000; break;
265 case 9: freq = 11780000; break;
266 case 10: freq =
267 13630000; break;
268 case 11: freq = 14100000; break;
269 case 12: freq =
270 15000000; break;
271 case 13: freq = 17655000; break;
272 case 14: freq =
273 21525000; break;
274 case 15: freq = 27015000; break;
275 case 16: freq =
276 28400000; break;
277 case 17: freq = 50000000; break;
278 case 18: freq =
279 100000000; break;
280 case 19: freq = 130000000; break;
281 case 20: freq
282 = 144000000; break;
283 case 21: freq = 220000000; break;
284 }
285 si5351.pll_reset(SI5351_PLLA);
286
287 stp = 4; setstep();
288}
289
290void layout() {
291 display.setTextColor(WHITE);
292
293 display.drawLine(0, 20, 127, 20, WHITE);
294 display.drawLine(0, 43, 127, 43,
295 WHITE);
296 display.drawLine(105, 24, 105, 39, WHITE);
297 display.drawLine(87,
298 24, 87, 39, WHITE);
299 display.drawLine(87, 48, 87, 63, WHITE);
300 display.drawLine(15,
301 55, 82, 55, WHITE);
302 display.setTextSize(1);
303 display.setCursor(59, 23);
304
305 display.print("STEP");
306 display.setCursor(54, 33);
307 if (stp == 2) display.print("
308 1Hz"); if (stp == 3) display.print(" 10Hz"); if (stp == 4) display.print("
309 1kHz");
310 if (stp == 5) display.print(" 5kHz"); if (stp == 6) display.print("10kHz");
311 if (stp == 1) display.print(" 1MHz");
312 display.setTextSize(1);
313 display.setCursor(92,
314 48);
315 display.print("IF:");
316 display.setCursor(92, 57);
317 display.print(interfreq);
318
319 display.print("k");
320 display.setTextSize(1);
321 display.setCursor(110,
322 23);
323 if (freq < 1000000) display.print("kHz");
324 if (freq >= 1000000)
325 display.print("MHz");
326 display.setCursor(110, 33);
327 if (interfreq == 0)
328 display.print("VFO");
329 if (interfreq != 0) display.print("L O");
330 display.setCursor(91,
331 28);
332 if (!sts) display.print("RX"); if (!sts) interfreq = IF;
333 if (sts)
334 display.print("TX"); if (sts) interfreq = 0;
335 bandlist(); drawbargraph();
336
337 display.display();
338}
339
340void bandlist() {
341 display.setTextSize(2);
342
343 display.setCursor(0, 25);
344 if (count == 1) display.print("GEN"); if (count
345 == 2) display.print("MW"); if (count == 3) display.print("160m"); if (count
346 == 4) display.print("80m");
347 if (count == 5) display.print("60m"); if (count
348 == 6) display.print("49m"); if (count == 7) display.print("40m"); if (count
349 == 8) display.print("31m");
350 if (count == 9) display.print("25m"); if (count
351 == 10) display.print("22m"); if (count == 11) display.print("20m"); if (count
352 == 12) display.print("19m");
353 if (count == 13) display.print("16m"); if
354 (count == 14) display.print("13m"); if (count == 15) display.print("11m"); if
355 (count == 16) display.print("10m");
356 if (count == 17) display.print("6m");
357 if (count == 18) display.print("WFM"); if (count == 19) display.print("AIR");
358 if (count == 20) display.print("2m");
359 if (count == 21) display.print("1m");
360
361 if (count == 1) interfreq = 0; else if (!sts) interfreq = IF;
362}
363
364void
365 sgnalread() {
366 smval = analogRead(adc); x = map(smval, 0, S_GAIN, 1, 14); if
367 (x > 14) x = 14;
368}
369
370void drawbargraph() {
371 byte y = map(n, 1, 42, 1,
372 14);
373 display.setTextSize(1);
374
375 //Pointer
376 display.setCursor(0, 48);
377 display.print("TU");
378 switch (y) {
379 case 1: display.fillRect(15, 48,
380 2, 6, WHITE); break;
381 case 2: display.fillRect(20, 48, 2, 6, WHITE); break;
382
383 case 3: display.fillRect(25, 48, 2, 6, WHITE); break;
384 case 4: display.fillRect(30,
385 48, 2, 6, WHITE); break;
386 case 5: display.fillRect(35, 48, 2, 6, WHITE); break;
387
388 case 6: display.fillRect(40, 48, 2, 6, WHITE); break;
389 case 7: display.fillRect(45,
390 48, 2, 6, WHITE); break;
391 case 8: display.fillRect(50, 48, 2, 6, WHITE); break;
392
393 case 9: display.fillRect(55, 48, 2, 6, WHITE); break;
394 case 10: display.fillRect(60,
395 48, 2, 6, WHITE); break;
396 case 11: display.fillRect(65, 48, 2, 6, WHITE);
397 break;
398 case 12: display.fillRect(70, 48, 2, 6, WHITE); break;
399 case
400 13: display.fillRect(75, 48, 2, 6, WHITE); break;
401 case 14: display.fillRect(80,
402 48, 2, 6, WHITE); break;
403 }
404
405 //Bargraph
406 display.setCursor(0, 57);
407 display.print("SM");
408 switch (x) {
409 case 14: display.fillRect(80, 58,
410 2, 6, WHITE);
411 case 13: display.fillRect(75, 58, 2, 6, WHITE);
412 case
413 12: display.fillRect(70, 58, 2, 6, WHITE);
414 case 11: display.fillRect(65,
415 58, 2, 6, WHITE);
416 case 10: display.fillRect(60, 58, 2, 6, WHITE);
417 case
418 9: display.fillRect(55, 58, 2, 6, WHITE);
419 case 8: display.fillRect(50, 58,
420 2, 6, WHITE);
421 case 7: display.fillRect(45, 58, 2, 6, WHITE);
422 case
423 6: display.fillRect(40, 58, 2, 6, WHITE);
424 case 5: display.fillRect(35, 58,
425 2, 6, WHITE);
426 case 4: display.fillRect(30, 58, 2, 6, WHITE);
427 case
428 3: display.fillRect(25, 58, 2, 6, WHITE);
429 case 2: display.fillRect(20, 58,
430 2, 6, WHITE);
431 case 1: display.fillRect(15, 58, 2, 6, WHITE);
432 }
433}
434
435void
436 statup_text() {
437 display.setTextSize(1); display.setCursor(13, 18);
438 display.print("Si5351
439 VFO/RF GEN");
440 display.setCursor(6, 40);
441 display.print("JCR RADIO - Ver
442 2.0");
443 display.display(); delay(2000);
444}

Sketch SI5351_VFO_RF_GEN_OLED_JCR_V2

Load it onto Arduino.

1/**********************************************************************************************************
2 10kHz to 225MHz VFO / RF Generator with Si5351 and Arduino Nano, with Intermediate Frequency (IF) offset
3 (+ or -), RX/TX Selector for QRP Transceivers, Band Presets and Bargraph S-Meter. See the schematics for
4 wiring and README.txt for details. By J. CesarSound - ver 2.0 - Feb/2021.
5***********************************************************************************************************/
6
7//Libraries
8#include <Wire.h> //IDE Standard
9#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary
10#include <si5351.h> //Etherkit https://github.com/etherkit/Si5351Arduino
11#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
12#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
13
14//User preferences
15//------------------------------------------------------------------------------------------------------------
16#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.
17#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).
18#define XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value will decreases the frequency and vice versa.
19#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).
20#define tunestep A0 //The pin used by tune step push button.
21#define band A1 //The pin used by band selector push button.
22#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.
23#define adc A3 //The pin used by Signal Meter A/D input.
24//------------------------------------------------------------------------------------------------------------
25
26Rotary r = Rotary(2, 3);
27Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
28Si5351 si5351(0x60); //Si5351 I2C Address 0x60
29
30unsigned long freq, freqold, fstep;
31long interfreq = IF, interfreqold = 0;
32long cal = XT_CAL_F;
33unsigned int smval;
34byte encoder = 1;
35byte stp, n = 1;
36byte count, x, xo;
37bool sts = 0;
38unsigned int period = 100;
39unsigned long time_now = 0;
40
41ISR(PCINT2_vect) {
42 char result = r.process();
43 if (result == DIR_CW) set_frequency(1);
44 else if (result == DIR_CCW) set_frequency(-1);
45}
46
47void set_frequency(short dir) {
48 if (encoder == 1) { //Up/Down frequency
49 if (dir == 1) freq = freq + fstep;
50 if (freq >= 225000000) freq = 225000000;
51 if (dir == -1) freq = freq - fstep;
52 if (fstep == 1000000 && freq <= 1000000) freq = 1000000;
53 else if (freq < 10000) freq = 10000;
54 }
55 if (encoder == 1) { //Up/Down graph tune pointer
56 if (dir == 1) n = n + 1;
57 if (n > 42) n = 1;
58 if (dir == -1) n = n - 1;
59 if (n < 1) n = 42;
60 }
61}
62
63void setup() {
64 Wire.begin();
65 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
66 display.clearDisplay();
67 display.setTextColor(WHITE);
68 display.display();
69
70 pinMode(2, INPUT_PULLUP);
71 pinMode(3, INPUT_PULLUP);
72 pinMode(tunestep, INPUT_PULLUP);
73 pinMode(band, INPUT_PULLUP);
74 pinMode(rx_tx, INPUT_PULLUP);
75
76 //statup_text(); //If you hang on startup, comment
77
78 si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
79 si5351.set_correction(cal, SI5351_PLL_INPUT_XO);
80 si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
81 si5351.output_enable(SI5351_CLK0, 1); //1 - Enable / 0 - Disable CLK
82 si5351.output_enable(SI5351_CLK1, 0);
83 si5351.output_enable(SI5351_CLK2, 0);
84
85 PCICR |= (1 << PCIE2);
86 PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
87 sei();
88
89 count = BAND_INIT;
90 bandpresets();
91 stp = 4;
92 setstep();
93}
94
95void loop() {
96 if (freqold != freq) {
97 time_now = millis();
98 tunegen();
99 freqold = freq;
100 }
101
102 if (interfreqold != interfreq) {
103 time_now = millis();
104 tunegen();
105 interfreqold = interfreq;
106 }
107
108 if (xo != x) {
109 time_now = millis();
110 xo = x;
111 }
112
113 if (digitalRead(tunestep) == LOW) {
114 time_now = (millis() + 300);
115 setstep();
116 delay(300);
117 }
118
119 if (digitalRead(band) == LOW) {
120 time_now = (millis() + 300);
121 inc_preset();
122 delay(300);
123 }
124
125 if (digitalRead(rx_tx) == LOW) {
126 time_now = (millis() + 300);
127 sts = 1;
128 } else sts = 0;
129
130 if ((time_now + period) > millis()) {
131 displayfreq();
132 layout();
133 }
134 sgnalread();
135}
136
137void tunegen() {
138 si5351.set_freq((freq + (interfreq * 1000ULL)) * 100ULL, SI5351_CLK0);
139}
140
141void displayfreq() {
142 unsigned int m = freq / 1000000;
143 unsigned int k = (freq % 1000000) / 1000;
144 unsigned int h = (freq % 1000) / 1;
145
146 display.clearDisplay();
147 display.setTextSize(2);
148
149 char buffer[15] = "";
150 if (m < 1) {
151 display.setCursor(41, 1); sprintf(buffer, "%003d.%003d", k, h);
152 }
153 else if (m < 100) {
154 display.setCursor(5, 1); sprintf(buffer, "%2d.%003d.%003d", m, k, h);
155 }
156 else if (m >= 100) {
157 unsigned int h = (freq % 1000) / 10;
158 display.setCursor(5, 1); sprintf(buffer, "%2d.%003d.%02d", m, k, h);
159 }
160 display.print(buffer);
161}
162
163void setstep() {
164 switch (stp) {
165 case 1: stp = 2; fstep = 1; break;
166 case 2: stp = 3; fstep = 10; break;
167 case 3: stp = 4; fstep = 1000; break;
168 case 4: stp = 5; fstep = 5000; break;
169 case 5: stp = 6; fstep = 10000; break;
170 case 6: stp = 1; fstep = 1000000; break;
171 }
172}
173
174void inc_preset() {
175 count++;
176 if (count > 21) count = 1;
177 bandpresets();
178 delay(50);
179}
180
181void bandpresets() {
182 switch (count) {
183 case 1: freq = 100000; tunegen(); break;
184 case 2: freq = 800000; break;
185 case 3: freq = 1800000; break;
186 case 4: freq = 3650000; break;
187 case 5: freq = 4985000; break;
188 case 6: freq = 6180000; break;
189 case 7: freq = 7200000; break;
190 case 8: freq = 10000000; break;
191 case 9: freq = 11780000; break;
192 case 10: freq = 13630000; break;
193 case 11: freq = 14100000; break;
194 case 12: freq = 15000000; break;
195 case 13: freq = 17655000; break;
196 case 14: freq = 21525000; break;
197 case 15: freq = 27015000; break;
198 case 16: freq = 28400000; break;
199 case 17: freq = 50000000; break;
200 case 18: freq = 100000000; break;
201 case 19: freq = 130000000; break;
202 case 20: freq = 144000000; break;
203 case 21: freq = 220000000; break;
204 }
205 si5351.pll_reset(SI5351_PLLA);
206 stp = 4; setstep();
207}
208
209void layout() {
210 display.setTextColor(WHITE);
211 display.drawLine(0, 20, 127, 20, WHITE);
212 display.drawLine(0, 43, 127, 43, WHITE);
213 display.drawLine(105, 24, 105, 39, WHITE);
214 display.drawLine(87, 24, 87, 39, WHITE);
215 display.drawLine(87, 48, 87, 63, WHITE);
216 display.drawLine(15, 55, 82, 55, WHITE);
217 display.setTextSize(1);
218 display.setCursor(59, 23);
219 display.print("STEP");
220 display.setCursor(54, 33);
221 if (stp == 2) display.print(" 1Hz"); if (stp == 3) display.print(" 10Hz"); if (stp == 4) display.print(" 1kHz");
222 if (stp == 5) display.print(" 5kHz"); if (stp == 6) display.print("10kHz"); if (stp == 1) display.print(" 1MHz");
223 display.setTextSize(1);
224 display.setCursor(92, 48);
225 display.print("IF:");
226 display.setCursor(92, 57);
227 display.print(interfreq);
228 display.print("k");
229 display.setTextSize(1);
230 display.setCursor(110, 23);
231 if (freq < 1000000) display.print("kHz");
232 if (freq >= 1000000) display.print("MHz");
233 display.setCursor(110, 33);
234 if (interfreq == 0) display.print("VFO");
235 if (interfreq != 0) display.print("L O");
236 display.setCursor(91, 28);
237 if (!sts) display.print("RX"); if (!sts) interfreq = IF;
238 if (sts) display.print("TX"); if (sts) interfreq = 0;
239 bandlist(); drawbargraph();
240 display.display();
241}
242
243void bandlist() {
244 display.setTextSize(2);
245 display.setCursor(0, 25);
246 if (count == 1) display.print("GEN"); if (count == 2) display.print("MW"); if (count == 3) display.print("160m"); if (count == 4) display.print("80m");
247 if (count == 5) display.print("60m"); if (count == 6) display.print("49m"); if (count == 7) display.print("40m"); if (count == 8) display.print("31m");
248 if (count == 9) display.print("25m"); if (count == 10) display.print("22m"); if (count == 11) display.print("20m"); if (count == 12) display.print("19m");
249 if (count == 13) display.print("16m"); if (count == 14) display.print("13m"); if (count == 15) display.print("11m"); if (count == 16) display.print("10m");
250 if (count == 17) display.print("6m"); if (count == 18) display.print("WFM"); if (count == 19) display.print("AIR"); if (count == 20) display.print("2m");
251 if (count == 21) display.print("1m");
252 if (count == 1) interfreq = 0; else if (!sts) interfreq = IF;
253}
254
255void sgnalread() {
256 smval = analogRead(adc); x = map(smval, 0, S_GAIN, 1, 14); if (x > 14) x = 14;
257}
258
259void drawbargraph() {
260 byte y = map(n, 1, 42, 1, 14);
261 display.setTextSize(1);
262
263 //Pointer
264 display.setCursor(0, 48); display.print("TU");
265 switch (y) {
266 case 1: display.fillRect(15, 48, 2, 6, WHITE); break;
267 case 2: display.fillRect(20, 48, 2, 6, WHITE); break;
268 case 3: display.fillRect(25, 48, 2, 6, WHITE); break;
269 case 4: display.fillRect(30, 48, 2, 6, WHITE); break;
270 case 5: display.fillRect(35, 48, 2, 6, WHITE); break;
271 case 6: display.fillRect(40, 48, 2, 6, WHITE); break;
272 case 7: display.fillRect(45, 48, 2, 6, WHITE); break;
273 case 8: display.fillRect(50, 48, 2, 6, WHITE); break;
274 case 9: display.fillRect(55, 48, 2, 6, WHITE); break;
275 case 10: display.fillRect(60, 48, 2, 6, WHITE); break;
276 case 11: display.fillRect(65, 48, 2, 6, WHITE); break;
277 case 12: display.fillRect(70, 48, 2, 6, WHITE); break;
278 case 13: display.fillRect(75, 48, 2, 6, WHITE); break;
279 case 14: display.fillRect(80, 48, 2, 6, WHITE); break;
280 }
281
282 //Bargraph
283 display.setCursor(0, 57); display.print("SM");
284 switch (x) {
285 case 14: display.fillRect(80, 58, 2, 6, WHITE);
286 case 13: display.fillRect(75, 58, 2, 6, WHITE);
287 case 12: display.fillRect(70, 58, 2, 6, WHITE);
288 case 11: display.fillRect(65, 58, 2, 6, WHITE);
289 case 10: display.fillRect(60, 58, 2, 6, WHITE);
290 case 9: display.fillRect(55, 58, 2, 6, WHITE);
291 case 8: display.fillRect(50, 58, 2, 6, WHITE);
292 case 7: display.fillRect(45, 58, 2, 6, WHITE);
293 case 6: display.fillRect(40, 58, 2, 6, WHITE);
294 case 5: display.fillRect(35, 58, 2, 6, WHITE);
295 case 4: display.fillRect(30, 58, 2, 6, WHITE);
296 case 3: display.fillRect(25, 58, 2, 6, WHITE);
297 case 2: display.fillRect(20, 58, 2, 6, WHITE);
298 case 1: display.fillRect(15, 58, 2, 6, WHITE);
299 }
300}
301
302void statup_text() {
303 display.setTextSize(1); display.setCursor(13, 18);
304 display.print("Si5351 VFO/RF GEN");
305 display.setCursor(6, 40);
306 display.print("JCR RADIO - Ver 2.0");
307 display.display(); delay(2000);
308}

Downloadable files

Schematic wiring

Circuit Wiring

Schematic wiring




Note: Content and images are from: https://projecthub.arduino.cc/, with some modifications.
If you want it removed due to copyright reasons, please leave a comment. Thank you.
I want to share this article more widely so that everyone knows about Arduino and your project.

SendData

Điều khiển trạng thái qua Firebase Trạng thái hiện tại: Đang tải... ĐỔI TRẠNG THÁI