Jason's library has a very good calibration procedure found by clicking on 'File\Examples\Etherkit-si535\si5351_calibration'
You will need some way of measuring frequency. Once done you will end up with a number that will replace the 0 in this statement:
si5351.set_correction(0);
Initialization now takes two arguments in the new library. Instead of just the crystal load capacitance - it now takes the crystal frequency as well.
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);
A zero as the second parameter defaults to 25Mhz, as above.
If you're using a 27Mhz crystal you could change it in the header file (si5351.h) or just put in 27000000.
Any and all comments are appreciated.
Tuesday, February 24, 2015
Tuesday, February 10, 2015
KD1JV PFR-3 TX spectral plot with 40M LPF
Sunday, February 8, 2015
KD1JV PFR-3 transmitter
I always wanted to try making making a cw transmitter like the one in KD1JV's PFR-3. It looks so simple. Steve uses the square wave comparator output of the AD9834 into an *74HC02 quad nand gate to buffer the output into 3 paralled BS170's. Since the Si5351 already puts out a square wave - why not? A quick test gave me 4 watts into a dummy load. I added a 40M LPF because I plan to lash this up with an already built CRX1 since it has some nice built-in conveniences, like TX/RX switching, muting and a nice twin-T sidetone oscillator.
Spectral plot of output.
Below is the finished product.
Spectral plot of output.
Below is the finished product.
Sunday, February 1, 2015
Codebender Arduino IDE
Recently I came across this video from the Open Source Hardware group which describes a cloud based IDE (Integrated Development Environment) for Arduino. This may simplify things for some people who have had problems with setting up an Arduino Environment on their home computers. For me, it means keeping the code all in one place and the fact that I simply like it better than the Arduino IDE.
To add a new library in Codebender click on the codebender gear in the upper left corner of the page (if you are on the code page) or "Upload library" on the upper right if you are at the home page. The library must be zipped. If it is downloaded from NT7S Si5351 or Rotary it is already zipped for you. In that case, just drag them from your download folder onto the Codebender "Upload a personal library" pop up that occurs when you press the green button.
Codebender allows me to embed my sketch into my blog where you can have your way with it. If you have Codebender installed on your browser, you can compile and download to your Arduino from here. If you want just the LCD_VFO_Si5351_IF.ino file for the Arduino IDE click here.
To add a new library in Codebender click on the codebender gear in the upper left corner of the page (if you are on the code page) or "Upload library" on the upper right if you are at the home page. The library must be zipped. If it is downloaded from NT7S Si5351 or Rotary it is already zipped for you. In that case, just drag them from your download folder onto the Codebender "Upload a personal library" pop up that occurs when you press the green button.
Codebender allows me to embed my sketch into my blog where you can have your way with it. If you have Codebender installed on your browser, you can compile and download to your Arduino from here. If you want just the LCD_VFO_Si5351_IF.ino file for the Arduino IDE click here.
Saturday, January 31, 2015
IF offset added to Si5351 VFO sketch
4/10/15***This sketch will no longer work go to this page and download the new library and sketch.
This new listing will allow an IF offset to be added to the VFO sketch.
This new listing will allow an IF offset to be added to the VFO sketch.
*These new lines, among others, have been added:
volatile uint32_t vfo = 14200000L; // this is the start frequency
volatile uint32_t LSB = 8999500L; // change this ...
volatile uint32_t USB = 9001500L; // ... and this to reflect your IF frequency
volatile uint32_t bfo = 9001500L; // inital start bfo is set to USB
The bfo will change from USB to LSB when the vfo is below 10 MHz and will be noted on the LCD.
By all means, experiment with this code. If you mess up just download it again.
I will from time to time update this code and will try to keep it simple, readable and distinctive as to things like different types of displays. The whole idea to learning something about programming is that you will not be stuck with things the way I do them or anyone else. Come to think of it, that is also one of the best things about home brewing!
*just changing these few lines will not work. You need to click "new listing" to download the new sketch.By all means, experiment with this code. If you mess up just download it again.
I will from time to time update this code and will try to keep it simple, readable and distinctive as to things like different types of displays. The whole idea to learning something about programming is that you will not be stuck with things the way I do them or anyone else. Come to think of it, that is also one of the best things about home brewing!
Monday, January 26, 2015
Installing Libraries and running code for Si5351 Arduino VFO
**as of 4/11/15 Jason's library has changed and this program will not work if you just downloaded the library. Use the new library and sketch from this posting. With newer versions of the Arduino IDE, downloading and installing libraries is a little easier - see this posting. The main thing is, remove the old library before installing a new one.
***Also, it is much easier now to add a new library. See this page.
We are going to use the NT7S Si5351 library from Github along with a sketch from SQ9NJE.
To quote the Adafruit Arduino Libraries tutorial, "User installed libraries should be installed in your sketchbook libraries folder so they can be used with all versions of the IDE. This way, if a new version of the IDE is released, you don't have to re-install all your favorite libraries! It would be a good idea to go through the tutorial if you are confused on this point.
Download and install the NT7S Si5351 library by clicking "Download Zip" on the right side of the page.
You will get a file called "Si5351Arduino-master.zip" Click on the file name and from the menu above and click on extract. Now you will have a file folder called "Si5351Arduino-master". This is not an acceptable file name as far as the Arduino IDE is concerned. Arduino doesn't like hypens. So right click on the folder name and change it to "Si5351".
Where you put this library folder is very important. Open the Arduino program and under "File" on the top left menu, click on "Preferences". This will show you where the IDE expects to see user sketches and user libraries ( Sketchbook location: ). The folder "Arduino" will list all your sketches and contains another folder called "libraries" This is where you will put the folder called Si5351 and Rotary.
The Si5351 folder contains two files which are most important, the one ending in ".cpp" and the one ending in ".h". The .h or header file describes the functions and variables for the cpp file that does all the work. If you are using another board like the one from Hans Summers QRP Labs, it uses a crystal of 27MHz instead of the 25Mhz crystal used in the Adafruit or NT7S board. In which case you will need to edit the line in the si5351.h file that says:
#define SI5351_XTAL_FREQ 25000000
to
#define SI5351_XTAL_FREQ 27000000
*In the new version of Jason's library, it is no longer necessary to do this. You can put the crystal frequency in as the second initialization parameter i.e.
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000);
You could edit this with Notepad but it might be difficult. A much easier approach for editing files that contain code is to use a program called Notepad++. It's free and very easy to use. In our case just go to the Si5351 folder, open it and right click on si5351.h and click "edit with Notepad++", make the change as above and click on File, Save.
**DO NOT edit with a word processor program like Word.
Download the *Rotary library from SQ9NJE's website by clicking on "Rotary Library" or "Biblioteka Rotary" (if you haven't right clicked on the page and clicked "Translate to English").
Follow the instructions as above.
Download sketch from LCD_VFO_Si5351.ino
(if you're using the latest NT7S library, use the sketch mentioned at the top of the post)
/*
This entire program is taken from Jason Mildrum, NT7S and Przemek Sadowski, SQ9NJE and Ben Buxton.
There is not enough original code written by me to make it worth mentioning.
http://nt7s.com/
http://sq9nje.pl/
Rotary library by Ben Buxton
*/
#include <Rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define F_MIN 1000000L // Lower frequency limit
#define F_MAX 30000000L // change to suit your needs for upper limit
#define ENCODER_A 3 // Encoder pin A
#define ENCODER_B 2 // Encoder pin B
#define ENCODER_BTN 11 //increments tuning step size
#define LCD_RS 5
#define LCD_E 6
#define LCD_D4 7
#define LCD_D5 8
#define LCD_D6 9
#define LCD_D7 10
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // LCD - pins
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t frequency0 = 14000000L; //You change these to your own frequencies
volatile uint32_t frequency1 = 9000000L;
volatile uint32_t frequency2 = 10000000L;
volatile uint32_t radix = 100; //100Hz steps to start with
boolean changed_f = 0; // frequency has changed flag
/**************************************/
/* 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)
frequency0 += radix;
if(dir == -1)
frequency0 -= radix;
if(frequency0 > F_MAX) //if you comment out these four lines
frequency0 = F_MAX; //then you can avoid checking
if(frequency0 < F_MIN) //upper and lower limits
frequency0 = F_MIN; //do the math, though, and set the limits for F_MAX
//and F_MIN for the vfo you are using
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;
}
/**************************************/
/* Displays the frequency */
/**************************************/
void display_frequency()
{
uint16_t f, g;
lcd.setCursor(4, 0);
f = frequency0 / 1000000;
if(f<10)
lcd.print(' ');
lcd.print(f);
lcd.print('.');
f = (frequency0 % 1000000)/1000;
if(f<100)
lcd.print('0');
if(f<10)
lcd.print('0');
lcd.print(f);
lcd.print('.');
f = frequency0 % 1000;
if(f<100)
lcd.print('0');
if(f<10)
lcd.print('0');
lcd.print(f);
lcd.print("Hz");
}
/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix()
{
lcd.setCursor(10, 1);
switch(radix)
{
case 10:
lcd.print(" 10");
break;
case 100:
lcd.print(" 100");
break;
case 1000:
lcd.print(" 1k");
break;
case 10000:
lcd.print(" 10k");
break;
case 100000:
lcd.print("100k");
break;
case 1000000: //change these lines to tune in 1MHz increments
lcd.print("1M");
break;
}
lcd.print("Hz");
}
void setup()
{
lcd.begin(16, 2); // Initialize and clear the LCD
lcd.clear();
Wire.begin();
// Start serial and initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF);
//Comment out the si5351.set_freq lines of the outputs you don't want to use
// same for si5351.drive_strength
// Set CLK0 to output to 14 MHz ( frequency0) with a fixed PLL frequency
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);
// Set CLK1 to output 9 MHz (frequency1)
si5351.set_freq(frequency1, 0, SI5351_CLK1);
// Set CLK2 to output 10 MHz (frequency2)
si5351.set_freq(frequency2, 0, SI5351_CLK2);
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA); //change the 2 to a 4, 6, or 8
si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA); //for more power output
si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA);
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enable pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
display_frequency(); // Update the display
display_radix();
}
void loop()
{
// Update the display if the frequency has been changed
if(changed_f) //changed_f = 1 because encoder was moved
{
display_frequency();
si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);
changed_f = 0; // set back to 0 after updating si5351 with new freq.
}
// Button press changes the frequency change step
if(get_button()) //default radix was 100
{ //so the next time the button is pressed ...
switch(radix)
{
case 10:
radix = 100;
break;
case 100: //case will be 100
radix = 1000; //so step is increased to 10000
break;
case 1000:
radix = 10000;
break;
case 10000:
radix = 100000;
break;
case 100000: //change these lines to tune in 1MHz increments
radix = 1000000;
break;
case 1000000:
radix = 10;
break;
}
display_radix();
}
}
***Also, it is much easier now to add a new library. See this page.
We are going to use the NT7S Si5351 library from Github along with a sketch from SQ9NJE.
To quote the Adafruit Arduino Libraries tutorial, "User installed libraries should be installed in your sketchbook libraries folder so they can be used with all versions of the IDE. This way, if a new version of the IDE is released, you don't have to re-install all your favorite libraries! It would be a good idea to go through the tutorial if you are confused on this point.
Download and install the NT7S Si5351 library by clicking "Download Zip" on the right side of the page.
You will get a file called "Si5351Arduino-master.zip" Click on the file name and from the menu above and click on extract. Now you will have a file folder called "Si5351Arduino-master". This is not an acceptable file name as far as the Arduino IDE is concerned. Arduino doesn't like hypens. So right click on the folder name and change it to "Si5351".
Where you put this library folder is very important. Open the Arduino program and under "File" on the top left menu, click on "Preferences". This will show you where the IDE expects to see user sketches and user libraries ( Sketchbook location: ). The folder "Arduino" will list all your sketches and contains another folder called "libraries" This is where you will put the folder called Si5351 and Rotary.
The Si5351 folder contains two files which are most important, the one ending in ".cpp" and the one ending in ".h". The .h or header file describes the functions and variables for the cpp file that does all the work. If you are using another board like the one from Hans Summers QRP Labs, it uses a crystal of 27MHz instead of the 25Mhz crystal used in the Adafruit or NT7S board. In which case you will need to edit the line in the si5351.h file that says:
#define SI5351_XTAL_FREQ 25000000
to
#define SI5351_XTAL_FREQ 27000000
*In the new version of Jason's library, it is no longer necessary to do this. You can put the crystal frequency in as the second initialization parameter i.e.
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 27000000);
You could edit this with Notepad but it might be difficult. A much easier approach for editing files that contain code is to use a program called Notepad++. It's free and very easy to use. In our case just go to the Si5351 folder, open it and right click on si5351.h and click "edit with Notepad++", make the change as above and click on File, Save.
**DO NOT edit with a word processor program like Word.
Download the *Rotary library from SQ9NJE's website by clicking on "Rotary Library" or "Biblioteka Rotary" (if you haven't right clicked on the page and clicked "Translate to English").
Follow the instructions as above.
Download sketch from LCD_VFO_Si5351.ino
(if you're using the latest NT7S library, use the sketch mentioned at the top of the post)
/*
This entire program is taken from Jason Mildrum, NT7S and Przemek Sadowski, SQ9NJE and Ben Buxton.
There is not enough original code written by me to make it worth mentioning.
http://nt7s.com/
http://sq9nje.pl/
Rotary library by Ben Buxton
*/
#include <Rotary.h>
#include <si5351.h>
#include <Wire.h>
#include <LiquidCrystal.h>
#define F_MIN 1000000L // Lower frequency limit
#define F_MAX 30000000L // change to suit your needs for upper limit
#define ENCODER_A 3 // Encoder pin A
#define ENCODER_B 2 // Encoder pin B
#define ENCODER_BTN 11 //increments tuning step size
#define LCD_RS 5
#define LCD_E 6
#define LCD_D4 7
#define LCD_D5 8
#define LCD_D6 9
#define LCD_D7 10
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); // LCD - pins
Si5351 si5351;
Rotary r = Rotary(ENCODER_A, ENCODER_B);
volatile uint32_t frequency0 = 14000000L; //You change these to your own frequencies
volatile uint32_t frequency1 = 9000000L;
volatile uint32_t frequency2 = 10000000L;
volatile uint32_t radix = 100; //100Hz steps to start with
boolean changed_f = 0; // frequency has changed flag
/**************************************/
/* 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)
frequency0 += radix;
if(dir == -1)
frequency0 -= radix;
if(frequency0 > F_MAX) //if you comment out these four lines
frequency0 = F_MAX; //then you can avoid checking
if(frequency0 < F_MIN) //upper and lower limits
frequency0 = F_MIN; //do the math, though, and set the limits for F_MAX
//and F_MIN for the vfo you are using
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;
}
/**************************************/
/* Displays the frequency */
/**************************************/
void display_frequency()
{
uint16_t f, g;
lcd.setCursor(4, 0);
f = frequency0 / 1000000;
if(f<10)
lcd.print(' ');
lcd.print(f);
lcd.print('.');
f = (frequency0 % 1000000)/1000;
if(f<100)
lcd.print('0');
if(f<10)
lcd.print('0');
lcd.print(f);
lcd.print('.');
f = frequency0 % 1000;
if(f<100)
lcd.print('0');
if(f<10)
lcd.print('0');
lcd.print(f);
lcd.print("Hz");
}
/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix()
{
lcd.setCursor(10, 1);
switch(radix)
{
case 10:
lcd.print(" 10");
break;
case 100:
lcd.print(" 100");
break;
case 1000:
lcd.print(" 1k");
break;
case 10000:
lcd.print(" 10k");
break;
case 100000:
lcd.print("100k");
break;
case 1000000: //change these lines to tune in 1MHz increments
lcd.print("1M");
break;
}
lcd.print("Hz");
}
void setup()
{
lcd.begin(16, 2); // Initialize and clear the LCD
lcd.clear();
Wire.begin();
// Start serial and initialize the Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF);
//Comment out the si5351.set_freq lines of the outputs you don't want to use
// same for si5351.drive_strength
// Set CLK0 to output to 14 MHz ( frequency0) with a fixed PLL frequency
si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);
// Set CLK1 to output 9 MHz (frequency1)
si5351.set_freq(frequency1, 0, SI5351_CLK1);
// Set CLK2 to output 10 MHz (frequency2)
si5351.set_freq(frequency2, 0, SI5351_CLK2);
si5351.drive_strength(SI5351_CLK0,SI5351_DRIVE_2MA); //change the 2 to a 4, 6, or 8
si5351.drive_strength(SI5351_CLK1,SI5351_DRIVE_2MA); //for more power output
si5351.drive_strength(SI5351_CLK2,SI5351_DRIVE_2MA);
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enable pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
display_frequency(); // Update the display
display_radix();
}
void loop()
{
// Update the display if the frequency has been changed
if(changed_f) //changed_f = 1 because encoder was moved
{
display_frequency();
si5351.set_freq(frequency0, SI5351_PLL_FIXED, SI5351_CLK0);
changed_f = 0; // set back to 0 after updating si5351 with new freq.
}
// Button press changes the frequency change step
if(get_button()) //default radix was 100
{ //so the next time the button is pressed ...
switch(radix)
{
case 10:
radix = 100;
break;
case 100: //case will be 100
radix = 1000; //so step is increased to 10000
break;
case 1000:
radix = 10000;
break;
case 10000:
radix = 100000;
break;
case 100000: //change these lines to tune in 1MHz increments
radix = 1000000;
break;
case 1000000:
radix = 10;
break;
}
display_radix();
}
}
Location:
New York, NY, USA
Sunday, January 25, 2015
Si5351 Arduino VFO breadboarded
This is the project bread boarded with an Arduino Duemilanove. On the left is the encoder with switch. In the center is the Adafruit si5351 breakout board and of course, the LCD on the right.
scope input taken directly from output 0 of Adafruit board.
I should be able to post the sketch by tomorrow.
scope input taken directly from output 0 of Adafruit board.
I should be able to post the sketch by tomorrow.
Subscribe to:
Comments (Atom)




