Skip to content

Instantly share code, notes, and snippets.

@NT7S
Created April 25, 2015 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NT7S/fe5224bf440b0e7fc4be to your computer and use it in GitHub Desktop.
Save NT7S/fe5224bf440b0e7fc4be to your computer and use it in GitHub Desktop.
Basic Si5351 VFO for LCD
/*
Si5351 VFO
By LA3PNA 27 March 2015
This version uses the new version 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 unsigned long 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);
si5351.set_correction(corr);
lcd.begin(16, 2);
lcd.print("Si5351 VFO");
Serial.begin(9600);
delay(2000);
si5351.set_freq(iffreq * 100ULL, 0, 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(frequency);
si5351.set_freq((frequency + iffreq) * 100ULL, 0, 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