Arduino Code part 1: /* This code is a modified version of a sketch found at py2ohh.w2c.com.br/ , for use as a quadrature VFO in RF direct conversion phasing receivers. I modified it just a bit, mantaining same functionality. The VFO is based on a Si5351a clock generator IC mounted on a breakout board, controlled by an Arduino Nano via I2C. User interface is just a 16x2 LCD and a rotary encoder with switch. Frequency range should be 3.2Hz to ~110MHz, but I could only verify until about 80MHz, then quadrature and equal amplitude degrade rapidly (could be due to test setup and oscilloscope employed). In order to reach the 3.2MHz lower frequency, a modification in the etherkit Si5351 library is necessary: locate the file "si5351.h" and change the line #define SI5351_PLL_VCO_MIN 600000000 to #define SI5351_PLL_VCO_MIN 400000000 In the si5351 library example folder there is a sketch that makes the frequency calibration process very easy, look for "si5351_calibration.ino" and follow the instructions. I calibrated mine using a receiver tuned to 10.000.500 Hz and a 500Hz reference tone. It is easier than tuning a guitar... The original sketch introduction by py2ohh: This entire program is taken from Jason Mildrum, NT7S and Przemek Sadowski, SQ9NJE. There is not enough original code written by AK2b to make it worth mentioning. nt7s.com/ sq9nje.pl/ ak2b.blogspot.com/ I made some mods ...first updating the sketch to new library from NT7S ..in frequency coverage and the mode for frequency change.. pressing the encoder and turn it at same time ...it will move a underline showing the place where it is OK to change XXXXXXXXXXXXXXXXXXXXXX Now I made other mods ... is OK to use with SDR rigs ... the clock0 and clock1 are in the same frequency, but in 90 degrees phase out.. it is ok from 3.2MHz to 110MHz (teoric) I tested with 30MHz and it was OK (to reach 3.2MHz I changed the NT7S library) I made a new function according Hans Summers, for dont have clicks when change the frequency ...reseting the SI5351 only when the evendivider is changed py2ohh.w2c.com.br/ */ #include // Ben Buxton's rotary encoder library github.com/brianlow/Rotary #include // Etherkit github.com/etherkit/Si5351Arduino #include // native Arduino library, for I2C things #include // native Arduino library, for LCD things const int encApin = 2; // Encoder pin A nano/uno pin D2 const int encBpin = 3; // Encoder pin B nano/uno pin D3 const int encSwPin = 4; // Encoder switch nano/uno pin D4 const int LCD_RS = 5; // LCD pin 4 nano/uno pin D5 const int LCD_E = 6; // LCD pin 6 nano/uno pin D6 const int LCD_D4 = 7; // LCD pin 11 nano/uno pin D7 const int LCD_D5 = 8; // LCD pin 12 nano/uno pin D8 const int LCD_D6 = 9; // LCD pin 13 nano/uno pin D9 const int LCD_D7 = 10; // LCD pin 14 nano/uno pin D10 const int numRows = 2; // LCD number of rows const int numCols = 16; // LCD number of columns LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // LCD pins assignment Si5351 si5351(0x60); // Si5351 I2C Address 0x60 Rotary r = Rotary(encApin, encBpin); // Rotary encoder, pins A, B volatile uint32_t vfo = 700000000ULL / SI5351_FREQ_MULT; //start freq, 7MHz volatile uint32_t radix = 1000; //start step size double vfoMhz; boolean changed_f = false; // freq change flag short und = 3; // underline cursor control short pot = 3; // multiplier int evenmult = 100; // PLL frequency must be an even multiple of clock frequency int oldevenmult = 0; /* ****************************************************** */ /* Interrupt service routine for encoder frequency change */ /* ****************************************************** */ ISR(PCINT2_vect) { unsigned char result = r.process(); if (result == DIR_CW) set_frequency(1); else if (result == DIR_CCW) set_frequency(-1); }
If you are referring to the SDR project, it is (in its current form) here: "SDR circuit experiment update, schematics and Arduino code" ua-cam.com/video/MfK98hA9SaY/v-deo.html Now I am working on transferring the circuit to a larger box, including four more bandpass filters and a second antenna input. You are welcome!
Arduino Code part 3: void loop() { // Update the display if the frequency has been changed if (changed_f) { vfoMhz = vfo / 10000; if (vfoMhz >= 320) { // without lib mod this is 476 display_frequency(); } else { display_frequency(); lcd.setCursor(0, 1); lcd.print("LIMIT >= 3.2MHz"); delay(1000); lcd.clear(); vfo = 3200000; display_frequency(); } if ((vfoMhz > 11000)) { display_frequency(); lcd.setCursor(0, 1); lcd.print("LIMIT
Arduino Code part 1:
/*
This code is a modified version of a sketch found at py2ohh.w2c.com.br/ ,
for use as a quadrature VFO in RF direct conversion phasing receivers.
I modified it just a bit, mantaining same functionality.
The VFO is based on a Si5351a clock generator IC mounted on a breakout board,
controlled by an Arduino Nano via I2C. User interface is just a 16x2 LCD and
a rotary encoder with switch.
Frequency range should be 3.2Hz to ~110MHz, but I could only verify until about
80MHz, then quadrature and equal amplitude degrade rapidly (could be due to test
setup and oscilloscope employed).
In order to reach the 3.2MHz lower frequency, a modification in the etherkit
Si5351 library is necessary: locate the file "si5351.h" and change the line
#define SI5351_PLL_VCO_MIN 600000000
to
#define SI5351_PLL_VCO_MIN 400000000
In the si5351 library example folder there is a sketch that makes
the frequency calibration process very easy, look for "si5351_calibration.ino"
and follow the instructions. I calibrated mine using a receiver tuned to
10.000.500 Hz and a 500Hz reference tone. It is easier than tuning a guitar...
The original sketch introduction by py2ohh:
This entire program is taken from Jason Mildrum, NT7S and Przemek Sadowski, SQ9NJE.
There is not enough original code written by AK2b to make it worth mentioning.
nt7s.com/
sq9nje.pl/
ak2b.blogspot.com/
I made some mods ...first updating the sketch to new library from NT7S
..in frequency coverage and the mode for frequency change..
pressing the encoder and turn it at same time ...it will move a underline showing
the place where it is OK to change
XXXXXXXXXXXXXXXXXXXXXX
Now I made other mods ... is OK to use with SDR rigs ... the clock0 and
clock1 are in the same frequency, but in 90 degrees phase out.. it is ok
from 3.2MHz to 110MHz (teoric) I tested with 30MHz and it was OK
(to reach 3.2MHz I changed the NT7S library)
I made a new function according Hans Summers, for dont have clicks
when change the frequency ...reseting the SI5351 only when the evendivider is changed
py2ohh.w2c.com.br/
*/
#include // Ben Buxton's rotary encoder library github.com/brianlow/Rotary
#include // Etherkit github.com/etherkit/Si5351Arduino
#include // native Arduino library, for I2C things
#include // native Arduino library, for LCD things
const int encApin = 2; // Encoder pin A nano/uno pin D2
const int encBpin = 3; // Encoder pin B nano/uno pin D3
const int encSwPin = 4; // Encoder switch nano/uno pin D4
const int LCD_RS = 5; // LCD pin 4 nano/uno pin D5
const int LCD_E = 6; // LCD pin 6 nano/uno pin D6
const int LCD_D4 = 7; // LCD pin 11 nano/uno pin D7
const int LCD_D5 = 8; // LCD pin 12 nano/uno pin D8
const int LCD_D6 = 9; // LCD pin 13 nano/uno pin D9
const int LCD_D7 = 10; // LCD pin 14 nano/uno pin D10
const int numRows = 2; // LCD number of rows
const int numCols = 16; // LCD number of columns
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // LCD pins assignment
Si5351 si5351(0x60); // Si5351 I2C Address 0x60
Rotary r = Rotary(encApin, encBpin); // Rotary encoder, pins A, B
volatile uint32_t vfo = 700000000ULL / SI5351_FREQ_MULT; //start freq, 7MHz
volatile uint32_t radix = 1000; //start step size
double vfoMhz;
boolean changed_f = false; // freq change flag
short und = 3; // underline cursor control
short pot = 3; // multiplier
int evenmult = 100; // PLL frequency must be an even multiple of clock frequency
int oldevenmult = 0;
/* ****************************************************** */
/* Interrupt service routine for encoder frequency change */
/* ****************************************************** */
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result == DIR_CW) set_frequency(1);
else if (result == DIR_CCW) set_frequency(-1);
}
Could u share the complete modified project?Thx!
If you are referring to the SDR project, it is (in its current form) here: "SDR circuit experiment update, schematics and Arduino code" ua-cam.com/video/MfK98hA9SaY/v-deo.html
Now I am working on transferring the circuit to a larger box, including four more bandpass filters and a second antenna input. You are welcome!
Schematic: ua-cam.com/users/postUgkxFN3pQ9SFDtaa-ssTALJWAV6iQFjHx6WB
Arduino Code part 3:
void loop()
{
// Update the display if the frequency has been changed
if (changed_f)
{
vfoMhz = vfo / 10000;
if (vfoMhz >= 320) { // without lib mod this is 476
display_frequency();
}
else {
display_frequency();
lcd.setCursor(0, 1);
lcd.print("LIMIT >= 3.2MHz");
delay(1000);
lcd.clear();
vfo = 3200000;
display_frequency();
}
if ((vfoMhz > 11000)) {
display_frequency();
lcd.setCursor(0, 1);
lcd.print("LIMIT
Arduino Code part 2:
/* ************************************* */
/* Change the frequency and underline */
/* dir = 1 Increment, dir = -1 Decrement */
/* ************************************* */
void set_frequency(short dir)
{
if (!digitalRead(encSwPin)) { // if encoder switch is pressed, encoder
lcd.setCursor( 12 - und, 0); // rotation controls underline cursor position
if (dir == 1) {
und += 1;
switch (und) {
case 4 : und = 5; break;
case 8 : und = 9; break;
case 12 : und = 11; break;
}
}
if (dir == -1) {
und += -1;
switch (und) {
case 4 : und = 3; break;
case 8 : und = 7; break;
case 0 : und = 1; break;
}
}
pot = und;
if (und > 3) (pot += -1);
if (und > 7) (pot += -1);
lcd.setCursor( 12 - und, 0);
lcd.cursor();
}
else // if encoder switch is not pressed, encoder rotation
{ lcd.noCursor(); // increase or decrease frequency in the selected step
if (dir == 1) vfo += radix;
if (dir == -1) {
if (vfo > radix ) {
vfo -= radix;
}
}
changed_f = true;
}
}
/* **************************************** */
/* Read the encoder switvh and debounce it */
/* **************************************** */
boolean get_button()
{
if (!digitalRead(encSwPin)) // If switch is LOW (pressed)
{
delay(20); // wait 20ms for debouncing,
if (!digitalRead(encSwPin)) // read the pin again, and if still LOW
{
while (!digitalRead(encSwPin)); // return true while it stay LOW, so the step size
return 1; // can be changed by rotating the encoder.
}
}
return 0;
}
/* ************************************ */
/* Displays the frequency */
/* ************************************ */
void display_frequency()
{
uint16_t f;
lcd.setCursor(1, 0);
f = (vfo ) / 1000000; //
if (f < 100) {
lcd.print(' ');
}
if (f < 10) {
lcd.print(' ');
}
lcd.print(f);
lcd.print('.');
f = (vfo % 1000000) / 1000;
if (f < 100) lcd.print('0');
if (f < 10) lcd.print('0');
lcd.print(f);
lcd.print('.');
f = vfo % 1000;
if (f < 100) lcd.print('0');
if (f < 10) lcd.print('0');
lcd.print(f);
lcd.print("Hz");
}
/* ***************************************** */
/* change envenmult for each of the freq */
/* bands bellow to keep things in quadrature */
/* ***************************************** */
void alterevenmult() // change envenmult for each of the freq bands bellow
{ // to keep things in quadrature
if ( vfoMhz < 685) evenmult = 126;
if ((vfoMhz >= 685) && (vfoMhz < 950)) evenmult = 88;
if ((vfoMhz >= 950) && (vfoMhz < 1360)) evenmult = 64;
if ((vfoMhz >= 1360) && (vfoMhz < 1750)) evenmult = 44;
if ((vfoMhz >= 1750) && (vfoMhz < 2500)) evenmult = 34;
if ((vfoMhz >= 2500) && (vfoMhz < 3600)) evenmult = 24;
if ((vfoMhz >= 3600) && (vfoMhz < 4500)) evenmult = 18;
if ((vfoMhz >= 4500) && (vfoMhz < 6000)) evenmult = 14;
if ((vfoMhz >= 6000) && (vfoMhz < 8000)) evenmult = 10;
if ((vfoMhz >= 8000) && (vfoMhz < 11000)) evenmult = 8;
}
void setup()
{
//Serial.begin(115200);
Wire.begin(); // Initialize I2C
lcd.begin(numCols, numRows); // Initialize LCD
lcd.clear(); // clear the LCD
lcd.display();
lcd.setCursor(5, 0);
lcd.print("IQ VFO");
lcd.setCursor(0, 1);
lcd.print("3.2MHz to 110MHz");
delay(3000);
lcd.clear();
r.begin(false); // disables the Arduino's internal weak pull-ups for the given
// pins and configures the rotary for use with external pull-ups
//initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); // 0 is the default crystal frequency of 25Mhz.
si5351.set_correction(10390, SI5351_PLL_INPUT_XO); // correction from calibration sketch
si5351.output_enable(SI5351_CLK0, 1); // 1 - Enable / 0 - Disable CLK
si5351.output_enable(SI5351_CLK1, 1);
si5351.output_enable(SI5351_CLK2, 0);
//2 mA roughly corresponds to 3 dBm output, 8 mA is approximately 10 dBm output:
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // 2MA, 4MA, 6MA or 8MA
si5351.drive_strength(SI5351_CLK1, SI5351_DRIVE_8MA);
// SI5351_FREQ_MULT is 100, second argument is the desired PLL frequency,
si5351.set_freq_manual(vfo * SI5351_FREQ_MULT, evenmult * vfo * SI5351_FREQ_MULT, SI5351_CLK0);
si5351.set_freq_manual(vfo * SI5351_FREQ_MULT, evenmult * vfo * SI5351_FREQ_MULT, SI5351_CLK1);
si5351.set_phase(SI5351_CLK0, 0); // In-phase signal at CLK0
si5351.set_phase(SI5351_CLK1, evenmult); // Quadrature at CLK1
si5351.pll_reset(SI5351_PLLA); // reset the Si5351 to enable changes
pinMode(encSwPin, INPUT_PULLUP);
PCICR |= (1