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);
}
Thank you 73 colin vk2jcc
ReplyDeleteMy pleasure Colin.
DeleteThanks Charlie!
ReplyDeleteNo problems Vladimir.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi Charlie,
ReplyDeleteJust sat here listening to my copy of your simple 80m ssb receiver and feeling well chuffed as its working fine.
I am not long retired and don't really have any experience in electronics but I have always wanted to build
my own radio. Finding your blog on you tube was a revelation for me and I have learnt so much from your video's.
Now I am working out how to proceed on a transmitter and if I can get it on the air then i can really call myself
a radio amateur. Please keep up the great work and I just wanted you to know your video's and clear explanation's
are a great asset to all radio amateurs and very much appreciated.
best regards
Alex (G0JZE) Oxford, England.
Thank you Alex for taking the time to drop a comment. I really appreciate the kind words. As you know, the whole aim of the videos and blog is to encourage others to give homebrew a go. I know the radios are simple and lack all of the bells and whistles, but that's the whole point. Start simple and go from there. Thanks again Alex, and keep us posted on how the transmitter progresses.
DeleteHi Charlie,
ReplyDeletethanks for the great work and I just wanted you to know your video's and explanation's exelents!
Today, I tested sketch from this Lesson. All-Ok!
Good Luck ...
That's great to hear Henadz. Really pleased.
DeleteCharlie
ZL2CTM