Please see the YouTube channel for details: https://www.youtube.com/channel/UCSNPW3_gzuMJcX_ErBZTv2g
AF Amp
IF Amps
Mixers
BPF
AGC/Limiter
RF PA Experiments
1st iteration
****************************************************************
Final Arduino code
#include <LiquidCrystal_I2C.h>
#include <si5351.h>
static const long bandStart = 3500000; // start of VFO range
static const long bandEnd = 3900000; // end of VFO range
static const long bandInit = 3690000; // where to initially set the frequency
volatile long freq = 3690000; // the current freq
volatile long oldfreq = 0; // the previous freq
volatile long rx_LSB_BFO_freq = 8997200; // High side injection thus SB inversion.
volatile long rx_USB_BFO_freq = 8998700; // High side injection thus SB inversion.
volatile long tx_LSB_BFO_freq = 8996300; // High side injection thus SB inversion.
volatile long tx_USB_BFO_freq = 8999800; // High side injection thus SB inversion.
volatile long radix = 1000; // How much to change the frequency by, clicking the Up Down switches
volatile long oldradix = 0; // the previous radix
volatile int mode = 0; // the current mode (0=LSB, 1=USB)
volatile int oldmode = 0; // the previous mode (0=LSB, 1=USB)
volatile int TX = 0; // 0=RX, 1=TX
volatile int oldTX = 1; // the old TX
unsigned int encoderA, encoderB, encoderC = 1; // rotary encoder variables
// Rotary encoder pins and other inputs
static const int rotAPin = 2;
static const int rotBPin = 3;
static const int radixPin = 4;
static const int modePin = 5;
static const int PTTPin = 6;
// Instantiate the Objects
LiquidCrystal_I2C lcd(0x3F, 16, 2); // 3F the address of the LCD
Si5351 si5351;
void setup()
{
// Set up I/O pins
pinMode(rotAPin, INPUT);
digitalWrite(rotAPin, HIGH); // internal pull-up enabled
pinMode(rotBPin, INPUT);
digitalWrite(rotBPin, HIGH); // internal pull-up enabled
pinMode(radixPin, INPUT);
digitalWrite(radixPin, HIGH); // internal pull-up enabled
pinMode(modePin, INPUT);
digitalWrite(modePin, HIGH); // internal pull-up enabled
pinMode(PTTPin, INPUT);
digitalWrite(PTTPin, LOW); // internal pull-up disabled
// Initialize the display
lcd.begin();
lcd.backlight();
lcd.noCursor();
// Initialize the DDS
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 62100); // 62100 is the specific calibration factor for this Si5351 board
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA); // 2 mA for HB mixers
si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_2MA); // 2 mA for HB mixers
}
void loop()
{
CheckEncoder();
CheckRadixSwitch();
CheckModeSwitch();
CheckPTTPin();
}
void CheckEncoder()
{
byte encoderA = digitalRead(rotAPin);
byte encoderB = digitalRead(rotBPin);
if ((encoderA == HIGH) && (encoderC == LOW))
{
if (encoderB == HIGH)
// Decrease frequency
freq = constrain(freq - radix, bandStart, bandEnd);
else
// Increase frequency
freq = constrain(freq + radix, bandStart, bandEnd);
}
encoderC = encoderA;
if (freq != oldfreq)
{
UpdateDisplay();
SendFrequency();
oldfreq = freq;
}
}
void CheckRadixSwitch()
{
if (digitalRead(radixPin) == 0)
{
radix = radix / 10;
if (radix < 1)
radix = 1000;
delay(200);
}
if (radix != oldradix)
{
UpdateRadixDisplay();
oldradix = radix;
}
}
void CheckModeSwitch()
{
if (digitalRead(modePin) == 0)
mode = 0; // 0=LSB
if (digitalRead(modePin) == 1)
mode = 1; // 1=USB
if (mode != oldmode)
{
UpdateDisplay();
SendFrequency();
oldmode = mode;
}
}
void CheckPTTPin()
{
TX = digitalRead(PTTPin);
if (TX != oldTX)
{
UpdateDisplay();
SendFrequency();
oldTX = TX;
}
}
void UpdateDisplay()
{
// freq
lcd.setCursor(0, 0);
lcd.print(freq);
// mode
lcd.setCursor(0, 1);
if (mode == 0)
lcd.print("LSB");
else
lcd.print("USB");
lcd.setCursor(10, 1);
// PTT
lcd.setCursor(4, 1);
if (TX == 1)
lcd.print("TX");
if (TX == 0)
lcd.print("RX");
// callsign
lcd.setCursor(10, 1);
lcd.print("ZL2CTM");
}
void UpdateRadixDisplay()
{
// radix
if (radix == 1000)
{
lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(9, 0);
lcd.print(radix);
lcd.setCursor(14, 0);
lcd.print("Hz");
}
if (radix == 100)
{
lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(10, 0);
lcd.print(radix);
lcd.setCursor(14, 0);
lcd.print("Hz");
}
if (radix == 10)
{
lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(11, 0);
lcd.print(radix);
lcd.setCursor(14, 0);
lcd.print("Hz");
}
if (radix == 1)
{
lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(12, 0);
lcd.print(radix);
lcd.setCursor(14, 0);
lcd.print("Hz");
}
}
void SendFrequency()
{
if (mode == 0) // LSB
{
if (TX == 1) // Transmit
{
si5351.set_freq(((tx_LSB_BFO_freq + freq) * 100ULL), SI5351_CLK2); // VFO
si5351.set_freq((tx_LSB_BFO_freq * 100ULL), SI5351_CLK0); // BFO
}
else // Receive
{
si5351.set_freq(((rx_LSB_BFO_freq + freq) * 100ULL), SI5351_CLK0); // VFO
si5351.set_freq((rx_LSB_BFO_freq * 100ULL), SI5351_CLK2); // BFO
}
}
if (mode == 1) // USB
{
if (TX == 1) // Transmit
{
si5351.set_freq(((tx_USB_BFO_freq + freq) * 100ULL), SI5351_CLK2); // VFO
si5351.set_freq((tx_USB_BFO_freq * 100ULL), SI5351_CLK0); // BFO
}
else // Receive
{
si5351.set_freq(((rx_USB_BFO_freq + freq) * 100ULL), SI5351_CLK0); // VFO
si5351.set_freq((rx_USB_BFO_freq * 100ULL), SI5351_CLK2); // BFO
}
}
}
Hi Charlie, just building the si5351 and nano on a board. Your timing with this vfo/bfo is perfect timing.
ReplyDeleteI will take a look at your coding as thats about where I am up to.
Cheers Colin vk2jcc
That's great Colin. Check out some earlier blogs for other software versions using a standard rotary encoder.
ReplyDeleteHi Charlie,
ReplyDeleteI can't get my arduino loaded.
I am getting an error.
Can you help me.
I don't think I have the right library.
Where can I find the right one?
Arduino: 1.8.5 (Windows 10), Board: "Arduino / Genuino Uno"
C: \ Program Files (x86) \ Arduino \ libraries \ LiquidCrystal_I2C \ I2CIO.cpp: 35: 10: fatal error: ../Wire/Wire.h: No such file or directory
#include <../ Wire / Wire.h>
^ ~~~~~~~~~~~~~~~
compilation terminated.
Found multiple libraries for "LiquidCrystal_I2C.h"
Used: C: \ Program Files (x86) \ Arduino \ libraries \ LiquidCrystal_I2C
Not used: C: \ Program Files (x86) \ Arduino \ libraries \ NewLiquidCrystal_lib
exit status 1
Error compiling for board Arduino / Genuino Uno
This report would contain more information with
"Show verbose output during compilation"
option in File -> Preferences.
greetings Arjan
I won't be able to help sorry Arjan. I suggest you open the example sketch that comes with your display library and look at the syntax. Copy that syntax in this sketch.
DeleteCharlie
Put in 16,2 in the lcd.begin();
DeleteIt worked for me but we may use different displays
DeleteGreat Build there Charlie, Just finished the VFO using exact same parts as you are, I found that when pin 5 us grounded i get a continuous flicker between Rx Tx and USB LSB. I will try add some resistance at the switch hope that helps.
ReplyDeleteNot sure sorry. I don't have that problem here. The internal pull-up resistor is enabled.
ReplyDeleteHello Charlie! Would you be able to take some close up photographs of both the IF Amp and the AF Amp completed boards? As I am very new to the hobby I it would help me greatly help to see the component placement on the board. I tried to zoom-in on the video but it still isn't very clear to me. Thank you in advance!
ReplyDeleteSee above.
DeleteThank you sir!
DeleteThanks for adding the photos! Seeing your construction style up close is very helpful.
ReplyDeleteThanks for the feedback.
DeleteCharlie
ReplyDeleteAny chance of posting final circuit for driver and power amp stages of your transceiver?
Mike ZL1AXG
Sure. I've just added the notes.
ReplyDeleteCharlie
Great, thanks!
ReplyDeleteCharlie - I will be making this rig with one or two mods over the next few months. I am assembling the audio amp at present and see you have an extra capacitor at the input in series with the resistor. I presume this is in the order of 10uF? Also, I am not sure why you use two BPF’s and don’t just use another relay on the antenna side. My thought is to use the arduino to switch four 5v relays (with driver transistor) for IF, BPF, antenna, and 12v RX/TX to make it possible to use on CW as well (pulling off balance one of the double balances mixers). I will also be using a 12 MHz IF requiring a few recalculations - only because I have the xtals.... It is 48 years since I completed a scratch build, but I have built a number of kits and smaller projects! You are an inspiration in this regard.
ReplyDeleteYes, 10uF will be fine. As for the BPF, I have done it both ways. More often I have it directly after the mixer on TX in order to remove all of the unwanted mixer products before amplification. Having a second BPF makes it easy. Either way will work fine.
ReplyDeleteI agree - straight after the mixer on the TX pathway is the best approach. I plan to demonstrate testing of each module in our regular Branch 50 shed workshops.
ReplyDeletehi charlie, how can i contact you?
ReplyDeleteCharlie
ReplyDeleteMy regards.
Will you kindly enlighten me about why in last 8 lines of the code you have switched vfo from clk2 to clk0 and again to clk2 and similarly bfo also was switched
between clk0 and clk2 .
Hi. Please see the 'relays' section above. I am using the two mixers for different purposes depending on if it is RX or TX. I do this now as I don't have any problems with feedback around the IF. The YouTube videos explain why I have changed.
DeleteThanks for your prompt response .
ReplyDeleteMy vfo/bfo with your coding idea is working nicely with my home brewed rig .
That's good to hear.
DeleteAbsolutely brilliant work Charlie! I've been searching for someone with your ability for a very long time. Thank you for sharing with the world.
ReplyDeleteI have a couple questions: on the PA section, can you show how you calcuated the 5:4 transformer (or did I miss it somewhere)?
I am very curious about something else - when you make transmitters, do you spend a lot of time with impedance matching withing stages? If so, can you recommend how you calculate that? Can you recommend any good books on the subject? S and Y parameters for small transistors like the 2N3904 have been notoriously hard to find for me, so I've never been able to do it.
Do you use any good software tools or books to calculate your torroid inductors?
Thank you again,
Josh
KC7KJC
Seattle, WA, USA
Hi charlie, thank you for your detailed design, I am interested in build a VFO of an old 80 mts SSB BLU (modified :) ). My question is regarding the output frequency of the Si5351, if am not wrong is and sqare output instead of a sine wave no? So if that happens you simply add a filter to get a clean carrier for example? O the IF filter leave all the armonics behind?
ReplyDeleteThanks in avdance!
LU7VRI from Argentina!
Regards
Hi. Take a look at:
Deletehttp://soldersmoke.blogspot.com/2016/03/great-video-on-mixers.html
That provides a good rundown on square waves and mixers.
Charlie
Thank you Charlie!! I will take a look on that!
DeleteThanks again..
LU7VRI
Ignacio
Kia Ora. A quick question: On the mixer, can Charlie or anyone else explain the design choices for the transformers? The number of turns, the guage of the wire, and the cores chosen? They are each 10 turns of 28 guage wire on FT 37-43 cores, but I'm not sure why. Charlie, do you have any good reference books or websites you use to determine values like these, whether for transformers or other parts?
ReplyDeleteThanks
-Josh
KC7KJC
Hi Josh. I try and use readily available parts so others can give it a go. The FT37-43 toroid is one of those. As for texts, my main source is Solid State Design for the Radio Amateur. An oldie but a goodie!
DeleteCharlie
Hola. Me sale errores varios al compilar el código. Necesito hacer solamente el generador de frecuencia para adaptarlo a un equipo Kenwood 120 pero no puedo compilar el código. Lo voy a armar con un displey 16*2 Arduino nano, encoder con pulsador y si5351. Pido si me pued n ayudar. Gracias
ReplyDelete
DeleteLe sugiero que use el código de ejemplo que viene con sus módulos, luego transfiera la sintaxis. Eso es todo lo que puedo hacer desde este punto. 73 Charlie ZL2CTM
Me ayudarías? La verdad es q no se nada y no puedo hacer q el código funcione. Sería mucho pedirle si me pasa el código y q librería debería usar? Los elementos que tengo son: Arduino nano, si5153, encoder de 5 pins, LCD 16*2 l2c. Desde ya más que agradecido. Lu1dte Daniel. Argentina.
DeleteNo lo siento. Debe comenzar con las bibliotecas (por ejemplo, la pantalla I2C) y sus ejemplos. Necesita encontrar los que funcionen con sus componentes. Utilice la biblioteca 'Etherkit Si5351' para el Si5351. Lo siento, no puedo ser de más ayuda.
Delete