Last active
November 17, 2019 06:17
-
-
Save la3pna/7f3ef8c9c75e035fce02 to your computer and use it in GitHub Desktop.
Si5351 generic VFO
This file contains hidden or 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
/* | |
Si5351 VFO | |
By LA3PNA 27 March 2015 | |
Modified 14 February 2017 | |
Modified 28 November 2018 | |
This code is licenced with GNU GPL v2. Please read: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
This version uses the new version (v2) of the Si5351 library from NT7S. | |
see: http://arduino.cc/en/Reference/AttachInterrupt for what pins that have interrupts. | |
UNO and 328 boards: Encoder on pin 2 and 3. Center pin to GND. | |
Leonardo: Encoder on pin 0 and 1. Center pin to GND. | |
100nF from each of the encoder pins to gnd is used to debounce | |
The pushbutton goes to pin 4 to set the tuning rate. | |
Pin 5 is the RX/TX pin. Put this pin LOW for RX, open or high for TX. | |
Single transistor switch to +RX will work. | |
VFO will NOT tune in TX. | |
LCD connections: | |
* LCD RS pin to digital pin 12 | |
* LCD Enable pin to digital pin 11 | |
* LCD D4 pin to digital pin 10 | |
* LCD D5 pin to digital pin 9 | |
* LCD D6 pin to digital pin 8 | |
* LCD D7 pin to digital pin 7 | |
* LCD R/W pin to ground | |
* LCD VSS pin to ground | |
* LCD VCC pin to 5V | |
* 10K pot: | |
* ends to +5V and ground | |
* wiper to LCD VO pin (pin 3) | |
IF frequency is positive for sum product (IF = RF + LO) and negative for diff (IF = RF - LO) | |
VFO signal output on CLK0, BFO signal on CLK2 | |
ToDo: | |
* | |
*/ | |
volatile uint64_t frequency = 7100000; // This will be the frequency it always starts on. | |
long iffreq = 0; // set the IF frequency in Hz. | |
long freqstep[] = {50, 100, 500, 1000, 5000, 10000}; // set this to your wanted tuning rate in Hz. | |
int corr = 10; // this is the correction factor for the Si5351, use calibration sketch to find value. | |
unsigned int lastReportedPos = 1; // change management | |
static boolean rotating = false; // debounce management | |
#include <si5351.h> | |
#include "Wire.h" | |
#include <LiquidCrystal.h> | |
Si5351 si5351; | |
// interrupt service routine vars | |
boolean A_set = false; | |
boolean B_set = false; | |
LiquidCrystal lcd(12, 11, 10, 9, 8, 7); | |
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) | |
int encoderPinA = 0; // rigth | |
int encoderPinB = 1; // left | |
#endif | |
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) | |
int encoderPinA = 2; // rigth | |
int encoderPinB = 3; // left | |
#endif | |
int inData; | |
bool tx; | |
int txpin = 5; | |
int freqsteps = 1; | |
int stepbutton = 4; | |
#define arraylength (sizeof(freqstep) / sizeof(freqstep[0])) | |
void setup() { | |
pinMode(encoderPinA, INPUT); | |
pinMode(encoderPinB, INPUT); | |
//pinMode(clearButton, INPUT); | |
pinMode(stepbutton, INPUT); | |
pinMode(txpin, INPUT); | |
digitalWrite(txpin, HIGH); | |
// turn on pullup resistors | |
digitalWrite(encoderPinA, HIGH); | |
digitalWrite(encoderPinB, HIGH); | |
digitalWrite(stepbutton, HIGH); | |
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) | |
//Code in here will only be compiled if an Arduino Leonardo is used. | |
// encoder pin on interrupt 0 (pin 0) | |
attachInterrupt(1, doEncoderA, CHANGE); | |
// encoder pin on interrupt 1 (pin 1) | |
attachInterrupt(0, doEncoderB, CHANGE); | |
#endif | |
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) | |
//Code in here will only be compiled if an Arduino Uno (or older) is used. | |
attachInterrupt(0, doEncoderA, CHANGE); | |
// encoder pin on interrupt 1 (pin 1) | |
attachInterrupt(1, doEncoderB, CHANGE); | |
#endif | |
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, corr); | |
lcd.begin(16, 2); | |
lcd.print("Si5351 VFO"); | |
Serial.begin(9600); | |
delay(2000); | |
si5351.set_freq(iffreq * 100ULL, SI5351_CLK2); | |
} | |
// main loop, work is done by interrupt service routines, this one only prints stuff | |
void loop() { | |
tx = digitalRead(txpin); | |
rotating = true; // reset the debouncer | |
if ( lastReportedPos != frequency) { | |
lastReportedPos = frequency; | |
lcd.setCursor(0, 1); | |
lcd.print(" "); | |
lcd.print((long)frequency); | |
si5351.set_freq((frequency + iffreq) * 100ULL, SI5351_CLK0); | |
} | |
delay(50); | |
if (Serial.available() > 0) // see if incoming serial data: | |
{ | |
inData = Serial.read(); // read oldest byte in serial buffer: | |
} | |
if (inData == 'F') { | |
frequency = Serial.parseInt(); | |
inData = 0; | |
} | |
if (digitalRead(stepbutton) == LOW ) { | |
delay(150); // delay to debounce | |
if (digitalRead(stepbutton) == LOW ) { | |
freqsteps = freqsteps + 1; | |
Serial.print(freqstep[freqsteps - 1]); | |
Serial.print(" "); | |
Serial.print(freqsteps); | |
Serial.print(" "); | |
Serial.println(sizeof(freqstep)); | |
if (freqsteps > arraylength - 1 ) { | |
freqsteps = 0; | |
} | |
delay(1000); //delay to avoid many steps at one | |
} | |
} | |
} | |
// Interrupt on A changing state | |
void doEncoderA() { | |
// debounce | |
if ( rotating ) delay (1); // wait a little until the bouncing is done | |
// Test transition, did things really change? | |
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more | |
A_set = !A_set; | |
// adjust counter + if A leads B | |
if ( A_set && !B_set ) { | |
if (!tx) { | |
frequency += freqstep[freqsteps]; // hehre is the amount to increase the freq | |
} | |
rotating = false; // no more debouncing until loop() hits again | |
} | |
} | |
} | |
// Interrupt on B changing state, same as A above | |
void doEncoderB() { | |
if ( rotating ) delay (1); | |
if ( digitalRead(encoderPinB) != B_set ) { | |
B_set = !B_set; | |
// adjust counter - 1 if B leads A | |
if ( B_set && !A_set ) { | |
if (!tx) { | |
frequency -= freqstep[freqsteps]; // here is the amount to decrease the freq | |
} | |
rotating = false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment