The AF amp now has a pi filter on the input made up of 100nF - 1mH - 100nF
That removes the high freq noise.
Ant RF Amp
Mic Amp
Test Low Power RF Amplifier
Out of the junk box hence the 13.8VDC VCC.
Initial code for the radio. Please see the YouTube video for an explanation:
#include <LiquidCrystal_I2C.h>
#include <si5351.h>
const long band80mStart = 3500000; // start of 80m
const long band80mEnd = 3900000; // end of 80m
const long band40mStart = 7000000; // start of 40m
const long band40mEnd = 7300000; // end of 40m
volatile long freq = 3700000; // this is a variable (changes) - set it to the beginning of the band
volatile long radix = 1000; // how much to change the frequency by, clicking the rotary encoder will change this.
volatile long oldfreq = 0;
volatile long old80mfreq = 3700000;
volatile long old40mfreq = 7100000;
volatile long currentfreq = 0;
volatile int updatedisplay = 0;
volatile int band = 0; // 0=80m, 1=40m
volatile int oldband = 0;
// Rotary encoder pins and other inputs
static const int rotAPin = 2;
static const int rotBPin = 3;
static const int pushSwPin = 4;
// Band switch
static const int BandSwPin = 5;
// Rotary encoder variables, used by interrupt routines
volatile int rotState = 0;
volatile int rotAval = 1;
volatile int rotBval = 1;
// Instantiate the Objects
LiquidCrystal_I2C lcd(0x27, 16, 2);
Si5351 si5351;
void setup()
{
// Set up frequency and radix switches
pinMode(rotAPin, INPUT_PULLUP);
pinMode(rotBPin, INPUT_PULLUP);
pinMode(pushSwPin, INPUT_PULLUP);
pinMode(BandSwPin, INPUT_PULLUP);
// Set up interrupt pins
attachInterrupt(digitalPinToInterrupt(rotAPin), ISRrotAChange, CHANGE);
attachInterrupt(digitalPinToInterrupt(rotBPin), ISRrotBChange, CHANGE);
// Initialize the display
lcd.begin();
lcd.backlight();
lcd.cursor();
// Initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
si5351.set_correction(191, SI5351_PLL_INPUT_XO);
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
// Update display and send start frequency
UpdateDisplay();
SendFrequency();
}
void loop()
{
// Check to see if the freq has changed
currentfreq = getfreq(); // Interrupt safe method to get the current frequency
if (currentfreq != oldfreq)
{
UpdateDisplay();
SendFrequency();
oldfreq = currentfreq;
}
// Check the rotary encoder (radix) swith
if (digitalRead(pushSwPin) == LOW) // Read the rotary encoder switch
{
delay(10);
while (digitalRead(pushSwPin) == LOW)
{
if (updatedisplay == 1)
{
UpdateDisplay();
updatedisplay = 0;
}
}
delay(50);
}
// Check the band swith
if (digitalRead(BandSwPin) == LOW)
band = 1; // 1=40m
else
band = 0; // 0=80m
if (band != oldband) // Only update the display on band change
{
if (band == 0) // Now 80m was 40m
{
old40mfreq = freq; // Store old 40m freq
freq = old80mfreq; // Recall old 40m freq
}
if (band == 1) // Now 40m was 80m
{
old80mfreq = freq; // Store old 80m freq
freq = old40mfreq; // Recall old 40m freq
}
UpdateDisplay();
oldband = band;
}
}
long getfreq()
{
long temp_freq;
cli();
temp_freq = freq;
sei();
return temp_freq;
}
// Interrupt routines
void ISRrotAChange()
{
if (digitalRead(rotAPin))
{
rotAval = 1;
UpdateRot();
}
else
{
rotAval = 0;
UpdateRot();
}
}
void ISRrotBChange()
{
if (digitalRead(rotBPin))
{
rotBval = 1;
UpdateRot();
}
else
{
rotBval = 0;
UpdateRot();
}
}
// Determine which way the rotary encoder is rotating and action as required
void UpdateRot()
{
switch (rotState)
{
case 0: // Idle state, look for direction
if (!rotBval)
rotState = 1; // CW 1
if (!rotAval)
rotState = 11; // CCW 1
break;
case 1: // CW, wait for A low while B is low
if (!rotBval)
{
if (!rotAval)
{
// either increment the radix or freq
if (digitalRead(pushSwPin) == LOW)
{
updatedisplay = 1;
if (radix == 1000000)
radix = 100000;
else if (radix == 100000)
radix = 10000;
else if (radix == 10000)
radix = 1000;
else if (radix == 1000)
radix = 100;
else if (radix == 100)
radix = 10;
else if (radix == 10)
radix = 1;
else
radix = 1000000;
}
else
{
freq = (freq + radix);
if (band == 0) // 80m
if (freq > band80mEnd)
freq = band80mEnd;
if (band == 1) // 40m
if (freq > band40mEnd)
freq = band40mEnd;
}
rotState = 2; // CW 2
}
}
else if (rotAval)
rotState = 0; // It was just a glitch on B, go back to start
break;
case 2: // CW, wait for B high
if (rotBval)
rotState = 3; // CW 3
break;
case 3: // CW, wait for A high
if (rotAval)
rotState = 0; // back to idle (detent) state
break;
case 11: // CCW, wait for B low while A is low
if (!rotAval)
{
if (!rotBval)
{
// either decrement the radix or freq
if (digitalRead(pushSwPin) == LOW)
{
updatedisplay = 1;
if (radix == 1)
radix = 10;
else if (radix == 10)
radix = 100;
else if (radix == 100)
radix = 1000;
else if (radix == 1000)
radix = 10000;
else if (radix == 10000)
radix = 100000;
else if (radix == 100000)
radix = 1000000;
else
radix = 1;
}
else
{
freq = (freq - radix);
if (band == 0) // 80m
if (freq < band80mStart)
freq = band80mStart;
if (band == 1) // 40m
if (freq < band40mStart)
freq = band40mStart;
}
rotState = 12; // CCW 2
}
}
else if (rotBval)
rotState = 0; // It was just a glitch on A, go back to start
break;
case 12: // CCW, wait for A high
if (rotAval)
rotState = 13; // CCW 3
break;
case 13: // CCW, wait for B high
if (rotBval)
rotState = 0; // back to idle (detent) state
break;
}
}
void UpdateDisplay()
{
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(freq);
lcd.setCursor(10, 0);
lcd.print("ZL2CTM");
if (radix == 1)
lcd.setCursor(6, 0);
if (radix == 10)
lcd.setCursor(5, 0);
if (radix == 100)
lcd.setCursor(4, 0);
if (radix == 1000)
lcd.setCursor(3, 0);
if (radix == 10000)
lcd.setCursor(2, 0);
if (radix == 100000)
lcd.setCursor(1, 0);
if (radix == 1000000)
lcd.setCursor(0, 0);
}
void SendFrequency()
{
si5351.set_freq((freq * 100ULL), SI5351_CLK0);
}