Components and supplies
1
Toggle Switch, Toggle
1
Arduino Nano R3
1
Breadboard (generic)
2
Capacitor 10 nF
1
SSD1306 128X64 OLED DISPLAY
1
SI5351 CLOCK GEN MODULE
2
Capacitor 100 nF
1
Capacitor 10 µF
1
RCA JACK FOR RF OUTPUT CONECTION
1
Rotary Encoder with Push-Button
Apps and platforms
1
Arduino IDE
Project description
Code
Sketch SI5351_VFO_RF_GEN_OLED_JCR
c_cpp
VFO work. Load it to the Arduino using the IDE.
1/******************************************************************************************************** 2 10kHz to 120MHz VFO / RF Generator with Si5351 and Arduino Nano, with Intermediate Frequency (IF) 3 offset (+ or -). See the schematics for wiring details. By J. CesarSound - ver 1.0 - Dec/2020. 4*********************************************************************************************************/ 5 6//Libraries 7#include <Wire.h> //IDE Standard 8#include <Rotary.h> //Ben Buxton https://github.com/brianlow/Rotary 9#include <si5351.h> //Etherkit https://github.com/etherkit/Si5351Arduino 10#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library 11#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306 12 13//User preferences 14//------------------------------------------------------------------------------------------------------------ 15#define IF 0 //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. 16#define FREQ_INIT 7000000 //Enter your initial frequency at startup, ex: 7000000 = 7MHz, 10000000 = 10MHz, 840000 = 840kHz. 17#define XT_CAL_F 33000 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value will decreases the frequency and vice versa. 18#define tunestep A0 //Change the pin used by encoder push button if you want. 19//------------------------------------------------------------------------------------------------------------ 20 21Rotary r = Rotary(2, 3); 22Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); 23Si5351 si5351; 24 25unsigned long freq = FREQ_INIT; 26unsigned long freqold, fstep; 27long interfreq = IF; 28long cal = XT_CAL_F; 29unsigned long long pll_freq = 90000000000ULL; 30byte encoder = 1; 31byte stp; 32unsigned int period = 100; //millis display active 33unsigned long time_now = 0; //millis display active 34 35ISR(PCINT2_vect) { 36 char result = r.process(); 37 if (result == DIR_CW) set_frequency(1); 38 else if (result == DIR_CCW) set_frequency(-1); 39} 40 41void set_frequency(short dir) { 42 if (encoder == 1) { //Up/Down frequency 43 if (dir == 1) freq = freq + fstep; 44 if (freq >= 120000000) freq = 120000000; 45 if (dir == -1) freq = freq - fstep; 46 if (fstep == 1000000 && freq <= 1000000) freq = 1000000; 47 else if (freq < 10000) freq = 10000; 48 } 49} 50 51void setup() { 52 Wire.begin(); 53 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 54 display.clearDisplay(); 55 display.setTextColor(WHITE); 56 display.display(); 57 58 pinMode(2, INPUT_PULLUP); 59 pinMode(3, INPUT_PULLUP); 60 pinMode(tunestep, INPUT_PULLUP); 61 62 statup_text(); 63 64 si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, cal); 65 si5351.output_enable(SI5351_CLK0, 1); //1 - Enable / 0 - Disable CLK 66 si5351.output_enable(SI5351_CLK1, 0); 67 si5351.output_enable(SI5351_CLK2, 0); 68 si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA); //Output current 2MA, 4MA, 6MA or 8MA 69 70 PCICR |= (1 << PCIE2); 71 PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); 72 sei(); 73 74 stp = 3; 75 setstep(); 76 layout(); 77 displayfreq(); 78} 79 80void loop() { 81 if (freqold != freq) { 82 time_now = millis(); 83 tunegen(); 84 freqold = freq; 85 } 86 87 if (digitalRead(tunestep) == LOW) { 88 time_now = (millis() + 300); 89 setstep(); 90 delay(300); 91 } 92 93 if ((time_now + period) > millis()) { 94 displayfreq(); 95 layout(); 96 } 97} 98 99void tunegen() { 100 si5351.set_freq_manual((freq + (interfreq * 1000ULL)) * 100ULL, pll_freq, SI5351_CLK0); 101} 102 103void displayfreq() { 104 unsigned int m = freq / 1000000; 105 unsigned int k = (freq % 1000000) / 1000; 106 unsigned int h = (freq % 1000) / 1; 107 108 display.clearDisplay(); 109 display.setTextSize(2); 110 111 char buffer[15] = ""; 112 if (m < 1) { 113 display.setCursor(41, 1); sprintf(buffer, "%003d.%003d", k, h); 114 } 115 else if (m < 100) { 116 display.setCursor(5, 1); sprintf(buffer, "%2d.%003d.%003d", m, k, h); 117 } 118 else if (m >= 100) { 119 unsigned int h = (freq % 1000) / 10; 120 display.setCursor(5, 1); sprintf(buffer, "%2d.%003d.%02d", m, k, h); 121 } 122 display.print(buffer); 123} 124 125void setstep() { 126 switch (stp) { 127 case 1: 128 stp = 2; 129 fstep = 1; 130 break; 131 case 2: 132 stp = 3; 133 fstep = 10; 134 break; 135 case 3: 136 stp = 4; 137 fstep = 1000; 138 break; 139 case 4: 140 stp = 5; 141 fstep = 5000; 142 break; 143 case 5: 144 stp = 6; 145 fstep = 10000; 146 break; 147 case 6: 148 stp = 1; 149 fstep = 1000000; 150 break; 151 } 152} 153 154void layout() { 155 display.setTextColor(WHITE); 156 display.drawLine(0, 20, 127, 20, WHITE); 157 display.drawLine(0, 43, 127, 43, WHITE); 158 display.drawLine(105, 24, 105, 39, WHITE); 159 display.setTextSize(2); 160 display.setCursor(2, 25); 161 display.print("TS:"); 162 if (stp == 2) display.print("1Hz"); if (stp == 3) display.print("10Hz"); if (stp == 4) display.print("1k"); 163 if (stp == 5) display.print("5k"); if (stp == 6) display.print("10k"); if (stp == 1) display.print("1M"); 164 display.setCursor(2, 48); 165 display.print("IF:"); 166 display.print(interfreq); 167 display.print("k"); 168 display.setTextSize(1); 169 display.setCursor(110, 23); 170 if (freq < 1000000) display.print("kHz"); 171 if (freq >= 1000000) display.print("MHz"); 172 display.setCursor(110, 33); 173 if (interfreq == 0) display.print("VFO"); 174 if (interfreq != 0) display.print("L O"); 175 display.display(); 176} 177 178void statup_text() { 179 display.setTextSize(1); 180 display.setCursor(4, 5); 181 display.print("Si5351"); 182 display.setCursor(4, 20); 183 display.print("VFO / RF Generator"); 184 display.setCursor(4, 35); 185 display.print("Version 1.0"); 186 display.setCursor(4, 50); 187 display.print(">> JCR RADIO <<"); 188 display.display(); 189 delay(3000); 190 display.clearDisplay(); 191}
Sketch SI5351_VFO_RF_GEN_OLED_JCR
c_cpp
VFO work. Load it to the Arduino using the IDE.
1/******************************************************************************************************** 2 3 10kHz to 120MHz VFO / RF Generator with Si5351 and Arduino Nano, with Intermediate 4 Frequency (IF) 5 offset (+ or -). See the schematics for wiring details. By J. 6 CesarSound - ver 1.0 - Dec/2020. 7*********************************************************************************************************/ 8 9//Libraries 10#include 11 <Wire.h> //IDE Standard 12#include <Rotary.h> //Ben 13 Buxton https://github.com/brianlow/Rotary 14#include <si5351.h> //Etherkit 15 https://github.com/etherkit/Si5351Arduino 16#include <Adafruit_GFX.h> //Adafruit 17 GFX https://github.com/adafruit/Adafruit-GFX-Library 18#include <Adafruit_SSD1306.h> 19 //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306 20 21//User 22 preferences 23//------------------------------------------------------------------------------------------------------------ 24#define 25 IF 0 //Enter your IF frequency, ex: 455 = 455kHz, 10700 = 10.7MHz, 26 0 = to direct convert receiver or RF generator, + will add and - will subtract IF 27 offfset. 28#define FREQ_INIT 7000000 //Enter your initial frequency at startup, 29 ex: 7000000 = 7MHz, 10000000 = 10MHz, 840000 = 840kHz. 30#define XT_CAL_F 33000 31 //Si5351 calibration factor, adjust to get exatcly 10MHz. Increasing this value 32 will decreases the frequency and vice versa. 33#define tunestep A0 //Change 34 the pin used by encoder push button if you want. 35//------------------------------------------------------------------------------------------------------------ 36 37Rotary 38 r = Rotary(2, 3); 39Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); 40Si5351 41 si5351; 42 43unsigned long freq = FREQ_INIT; 44unsigned long freqold, fstep; 45long 46 interfreq = IF; 47long cal = XT_CAL_F; 48unsigned long long pll_freq = 90000000000ULL; 49byte 50 encoder = 1; 51byte stp; 52unsigned int period = 100; //millis display active 53unsigned 54 long time_now = 0; //millis display active 55 56ISR(PCINT2_vect) { 57 char 58 result = r.process(); 59 if (result == DIR_CW) set_frequency(1); 60 else if 61 (result == DIR_CCW) set_frequency(-1); 62} 63 64void set_frequency(short dir) 65 { 66 if (encoder == 1) { //Up/Down frequency 67 if 68 (dir == 1) freq = freq + fstep; 69 if (freq >= 120000000) freq = 120000000; 70 71 if (dir == -1) freq = freq - fstep; 72 if (fstep == 1000000 && freq <= 1000000) 73 freq = 1000000; 74 else if (freq < 10000) freq = 10000; 75 } 76} 77 78void 79 setup() { 80 Wire.begin(); 81 display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 82 83 display.clearDisplay(); 84 display.setTextColor(WHITE); 85 display.display(); 86 87 88 pinMode(2, INPUT_PULLUP); 89 pinMode(3, INPUT_PULLUP); 90 pinMode(tunestep, 91 INPUT_PULLUP); 92 93 statup_text(); 94 95 si5351.init(SI5351_CRYSTAL_LOAD_8PF, 96 0, cal); 97 si5351.output_enable(SI5351_CLK0, 1); //1 - Enable 98 / 0 - Disable CLK 99 si5351.output_enable(SI5351_CLK1, 0); 100 si5351.output_enable(SI5351_CLK2, 101 0); 102 si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA); //Output current 103 2MA, 4MA, 6MA or 8MA 104 105 PCICR |= (1 << PCIE2); 106 PCMSK2 |= (1 << PCINT18) 107 | (1 << PCINT19); 108 sei(); 109 110 stp = 3; 111 setstep(); 112 layout(); 113 114 displayfreq(); 115} 116 117void loop() { 118 if (freqold != freq) { 119 time_now 120 = millis(); 121 tunegen(); 122 freqold = freq; 123 } 124 125 if (digitalRead(tunestep) 126 == LOW) { 127 time_now = (millis() + 300); 128 setstep(); 129 delay(300); 130 131 } 132 133 if ((time_now + period) > millis()) { 134 displayfreq(); 135 layout(); 136 137 } 138} 139 140void tunegen() { 141 si5351.set_freq_manual((freq + (interfreq 142 * 1000ULL)) * 100ULL, pll_freq, SI5351_CLK0); 143} 144 145void displayfreq() { 146 147 unsigned int m = freq / 1000000; 148 unsigned int k = (freq % 1000000) / 1000; 149 150 unsigned int h = (freq % 1000) / 1; 151 152 display.clearDisplay(); 153 display.setTextSize(2); 154 155 156 char buffer[15] = ""; 157 if (m < 1) { 158 display.setCursor(41, 1); sprintf(buffer, 159 "%003d.%003d", k, h); 160 } 161 else if (m < 100) { 162 display.setCursor(5, 163 1); sprintf(buffer, "%2d.%003d.%003d", m, k, h); 164 } 165 else if (m >= 100) 166 { 167 unsigned int h = (freq % 1000) / 10; 168 display.setCursor(5, 1); sprintf(buffer, 169 "%2d.%003d.%02d", m, k, h); 170 } 171 display.print(buffer); 172} 173 174void 175 setstep() { 176 switch (stp) { 177 case 1: 178 stp = 2; 179 fstep 180 = 1; 181 break; 182 case 2: 183 stp = 3; 184 fstep = 10; 185 break; 186 187 case 3: 188 stp = 4; 189 fstep = 1000; 190 break; 191 case 192 4: 193 stp = 5; 194 fstep = 5000; 195 break; 196 case 5: 197 stp 198 = 6; 199 fstep = 10000; 200 break; 201 case 6: 202 stp = 1; 203 204 fstep = 1000000; 205 break; 206 } 207} 208 209void layout() { 210 display.setTextColor(WHITE); 211 212 display.drawLine(0, 20, 127, 20, WHITE); 213 display.drawLine(0, 43, 127, 43, 214 WHITE); 215 display.drawLine(105, 24, 105, 39, WHITE); 216 display.setTextSize(2); 217 218 display.setCursor(2, 25); 219 display.print("TS:"); 220 if (stp == 2) display.print("1Hz"); 221 if (stp == 3) display.print("10Hz"); if (stp == 4) display.print("1k"); 222 223 if (stp == 5) display.print("5k"); if (stp == 6) display.print("10k"); if 224 (stp == 1) display.print("1M"); 225 display.setCursor(2, 48); 226 display.print("IF:"); 227 228 display.print(interfreq); 229 display.print("k"); 230 display.setTextSize(1); 231 232 display.setCursor(110, 23); 233 if (freq < 1000000) display.print("kHz"); 234 235 if (freq >= 1000000) display.print("MHz"); 236 display.setCursor(110, 33); 237 238 if (interfreq == 0) display.print("VFO"); 239 if (interfreq != 0) display.print("L 240 O"); 241 display.display(); 242} 243 244void statup_text() { 245 display.setTextSize(1); 246 247 display.setCursor(4, 5); 248 display.print("Si5351"); 249 display.setCursor(4, 250 20); 251 display.print("VFO / RF Generator"); 252 display.setCursor(4, 35); 253 254 display.print("Version 1.0"); 255 display.setCursor(4, 50); 256 display.print(">> 257 JCR RADIO <<"); 258 display.display(); 259 delay(3000); 260 display.clearDisplay(); 261}
Downloadable files
Wiring diagram (schematics)
To interconnect the parts.
Wiring diagram (schematics)
Comments
Only logged in users can leave comments