Minimal VFO using Si5351
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Simple VFO for a direct conversion receiver. | |
Si5351 controlled by a rotary encoder. | |
Based on code from Paul, VK3HN | |
https://github.com/prt459/Arduino_si5351_VFO_Controller_Keyer | |
*/ | |
const unsigned long int FREQ_DEFAULT = 7100000ULL; | |
#define ENCODER_A 3 // DT | |
#define ENCODER_B 2 // CLK | |
#include <RotaryEncoder.h> // by Maattias Hertel http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspx | |
#include <si5351.h> // Etherkit Si3531 library Jason Mildrum, V2.1.4 | |
// https://github.com/etherkit/Si5351Arduino | |
#include <Wire.h> // built in | |
Si5351 si5351; // I2C address defaults to x60 in the NT7S lib | |
RotaryEncoder gEncoder = RotaryEncoder(ENCODER_A, ENCODER_B, RotaryEncoder::LatchMode::FOUR3); | |
long gEncoderPosition = 0; | |
unsigned long int gFrequency = FREQ_DEFAULT; | |
unsigned long int gStep = 100; | |
void setup() { | |
Serial.begin(115200); | |
Wire.begin(); | |
gFrequency = FREQ_DEFAULT; | |
setupOscillator(); | |
setupRotaryEncoder(); | |
delay(500); | |
si5351.set_freq(FREQ_DEFAULT * SI5351_FREQ_MULT, SI5351_CLK0); | |
si5351.output_enable(SI5351_CLK0, 1); | |
} | |
void loop() { | |
// check for change in the rotary encoder | |
gEncoder.tick(); | |
long newEncoderPosition = gEncoder.getPosition(); | |
if(newEncoderPosition != gEncoderPosition) { | |
long encoderDifference = newEncoderPosition - gEncoderPosition; | |
gEncoderPosition = newEncoderPosition; | |
Serial.println(encoderDifference); | |
frequencyAdjust(encoderDifference); | |
} | |
} | |
void setupRotaryEncoder() { | |
attachInterrupt(digitalPinToInterrupt(ENCODER_A), checkPosition, CHANGE); | |
attachInterrupt(digitalPinToInterrupt(ENCODER_B), checkPosition, CHANGE); | |
} | |
// This interrupt routine will be called on any change of one of the input signals | |
void checkPosition() { | |
gEncoder.tick(); // just call tick() to check the state. | |
} | |
void frequencyAdjust(int delta) { | |
Serial.print("Adjust: "); | |
Serial.println(delta); | |
gFrequency += (delta * gStep); | |
setVfoFrequency(gFrequency); | |
} | |
void setVfoFrequency(unsigned long int frequency) { | |
si5351.set_freq(frequency * SI5351_FREQ_MULT, SI5351_CLK0); // | |
Serial.print("set frequency: "); | |
Serial.println(frequency); | |
} | |
void setupOscillator() { | |
bool i2c_found = si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); | |
Serial.print("si5351: "); | |
Serial.println(i2c_found ? "Found" : "Missing"); | |
si5351.set_correction(135000, SI5351_PLL_INPUT_XO); // Library update 26/4/2020: requires destination register address ... si5351.set_correction(19100, SI5351_PLL_INPUT_XO); | |
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); | |
si5351.set_freq(500000000ULL, SI5351_CLK0); | |
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA); | |
si5351.output_enable(SI5351_CLK0, 1); // turn VFO on | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment