Here is RF generator code for adafruit Si5351 and Si5351 chip.
It is capable to make frequency output from 1MHz to 150MHz with various step from 100Hz to 10MHz.
It can be used as local oscillator for amateur radio. Signal output is square wave so there is lot of harmonics. They must be taken a count if this generator is used for transmitter.
It uses rotary coder and small standard LCD display.
Many parts of SW is borrowed from various other sketches, but frequency calculation part is studied from si5351 AN619 and checked using Clock Builder Pro from Silicon Labs
Im not aware of bugs. Igot code ready last night so it is not extensively tested.
Best Regard:
OH2BTG
/**************************************************************************/
//v.0.0.5 09.09.2017 Frequency generator 1...150MHz with 100Hz steps. OH2BTG
/**************************************************************************/
#include <Wire.h>
#include <Adafruit_SI5351.h>
#include <LiquidCrystal.h>
#include <rotary.h>
#include <si5351.h>
Adafruit_SI5351 clockgen = Adafruit_SI5351();
#define ENCODER_A 3 // Encoder pin A
#define ENCODER_B 2 // Encoder pin B
#define ENCODER_BTN 4 // Encoder c button
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t vfo = 14578750000 ;// initial frequency in Hz Put your favourite frequency here
uint32_t pllFreq; // si5351 internal vco frequency
uint32_t radix = 12500; //start step size 12.5kHz
uint32_t si5351multiCount; // Multicounter
uint32_t si5351multi_int; // Multicounter integer
uint32_t si5351nomi; // Multicounter nominator
uint32_t si5351denomi = 1000000; //Multicounter denominator one million
uint32_t si5351divider; // VCO output divider integer part
boolean changed_f = 1;
String tbfo = "";
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // LCD: RS,E,D4,D5,D6,D7 Erska
/**************************************/
/* Displays the frequency */
/**************************************/
void count_frequency()
{
uint16_t f, g;
lcd.clear();
lcd.setCursor(3,0);
f = vfo / 1000000; //variable is now vfo instead of 'frequency' vfo esim 145787500
si5351divider = 900000000/vfo; // vfo divider integer
pllFreq = si5351divider * vfo; // counts pllFrequency
si5351multiCount = pllFreq / 25; // feedback divider
si5351multi_int = pllFreq / 25000000; // feedback divider integer
si5351nomi = si5351multiCount % 1000000; // feedback divider integer
si5351denomi = 1000000; // feedback divider fraktion
Serial.print(" vfo ");
Serial.println( vfo);
Serial.print(" pllFreq ");
Serial.println( pllFreq);
Serial.print("si5351divider ");
Serial.println(si5351divider);
Serial.print(" si5351multiCount ");
Serial.println(si5351multiCount);
Serial.print(" si5351multi_int ");
Serial.println(si5351multi_int);
Serial.print(" si5351nomi ");
Serial.println(si5351nomi);
Serial.print(" si5351denomi ");
Serial.println(si5351denomi);
// Serial.println(f = vfo / 1000000); // printtaa f 145.XXX.XXX
if (f < 10)
lcd.print("");
lcd.print(f);
lcd.print(",");
f = (vfo % 1000000) / 1000; // printtaa taajuuden 3 viim numeroa XXX.550.XXX
// Serial.println (f = (vfo % 1000000) / 1000);
if (f < 100)
lcd.print("0");
if (f < 10)
lcd.print("0");
lcd.print(f);
lcd.print(".");
// f = vfo % 1000;
f = (vfo % 1000) / 100; // removing 2 last digit from frequency reading
// Serial.println( f = vfo % 1000); // printtaa XXX.XXX.000
// if (f < 100)
// lcd.print("0");
// if (f < 10)
// lcd.print("0");
lcd.print(f); //
lcd.print("MHz");
// lcd.setCursor(0, 0);
// lcd.print(tbfo);
// Serial.println(vfo + bfo);
// Serial.println(tbfo);
}
/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix()
{
lcd.setCursor(0, 1);
switch (radix)
{
case 1:
lcd.print(" 1");
break;
case 10:
lcd.print(" 10");
break;
case 100:
lcd.print(" 100");
break;
case 1000:
lcd.print(" 1k");
break;
case 12500:
lcd.print("12.5k");
break;
case 100000:
lcd.setCursor(0, 1);
lcd.print(" 100k");
break;
case 1000000:
lcd.setCursor(1, 1);
lcd.print(" 1M"); //1MHz increments
break;
case 10000000:
lcd.setCursor(1, 1);
lcd.print(" 10M"); //10MHz increments
break;
}
lcd.print("Hz");
Serial.println("radix");
Serial.println(radix);
}
/**************************************/
/* 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);
}
/**************************************/
/* Change the frequency */
/* dir = 1 Increment */
/* dir = -1 Decrement */
/**************************************/
void set_frequency(short dir)
{
if (dir == 1)
vfo += radix;
if (dir == -1)
vfo -= radix;
if(vfo > 150000000)
vfo = 100000;
if(vfo < 100000)
vfo = 150000000;
if (vfo < 0)
vfo = 100000;
changed_f = 1;
}
/**************************************/
/* Read the button with debouncing */
/**************************************/
boolean get_button()
{
if (!digitalRead(ENCODER_BTN))
{
delay(20);
if (!digitalRead(ENCODER_BTN))
{
while (!digitalRead(ENCODER_BTN));
return 1;
}
}
return 0;
}
void setup(void)
{
Serial.begin(115200);
Serial.println(" Hello Word "); // Put your favourite text here
// lcd.begin(16, 2); // Initialize and clear the LCD
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" OH2BTG ");
lcd.setCursor(0,1);
lcd.print("1-150MHz v.0.0.5");
delay(2000); //2seconds
Wire.begin();
/* Initialise the sensor */
if (clockgen.begin() != ERROR_NONE)
{
while(1);
}
/* Enable the clocks */
clockgen.enableOutputs(true);
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enable pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
count_frequency(); // Count f and update the display
}
void loop(void)
{
// Update the display if the frequency has been changed
if (changed_f)
{
count_frequency();
clockgen.setupPLL(SI5351_PLL_A, (si5351multi_int),(si5351nomi),(si5351denomi)); // write si5351ctl divider word
// clockgen.setupMultisynthInt(0, SI5351_PLL_A, SI5351_MULTISYNTH_DIV_6);
clockgen.setupMultisynth(0, SI5351_PLL_A,(si5351divider),0,1 );
changed_f = 0;
}
// Button press changes the frequency step
if (get_button())
{
switch (radix)
{
// case 1:
// radix = 10;
// break;
// case 10:
// radix = 100;
// break;
case 100:
radix = 1000;
break;
case 1000:
radix = 12500;
break;
case 12500:
radix = 100000;
break;
case 100000:
radix = 1000000;
break;
case 1000000:
radix = 10000000;
break;
case 10000000:
radix = 100;
break;
}
display_radix();
}
}