Signal Generator using Adafruit SI5351 Clock Generator
34,The DDS and related clock generation circuitry has made possible high accuracy, broad-banded programmable VFO functionality for very little money.;Analogue Devices’ AD9850;series offer HF frequencies for about;€5. Higher frequencies can be had for not much more money, with the Silicon Labs SI570 with its near GHz maximum frequency offering the highest. I recently came across;an interesting little device from Adafruit. Again, from Silicon Labs, the SI5351;offers 3 independent clock outputs from a single 25MHz reference, programmable via i2c, a maximum frequency of 160MHz and all for less than;€10 shipped. I had to have one.
\nThe order, along with some of the other wonderful goodies from Adafruit arrived soon enough, and I got to work, first off getting the encoder knob working. The plan was to have a rotary encoder with push button for setting the freqeuncy, an i2c LCD for display, and the clockgen, all hanging off an Arduino… in this case, a Leonardo clone.
\n
\n
\n
\nThe sample code I first tried for the encoder worked ok, but then I found the builtin ‘encoder’ library, and tried that… far better, and no messing with interrupts.
\n
\nNext, I tried to get the display working… no joy using the standard LiquidCrystal_I2C library. I then ran an i2c scanner to find out if the device perhaps had a different address from standard. This gave me a ‘no devices’ error… something was wrong. After a bit more research, I discovered that the pins used for i2c on the Leo’ are not the same as on the Uno.;The Uno uses Analog pins 5 and 6 , whereas the Leo’ uses Digital pins 2 and 3. I reran the scanner, and it immediately detected the display on 0x27 ;and the clock-gen on 0x60. I plugged the address into some display testing code and had my display!
\n
\n
\nI then added in a few lines to include the Adafruit si5351 library and program one of the clocks to output 14Hz. I had my AOR8200 MkIII to hand, tuned to 14MHz AM so I hoped to be able to hear the clock on the AOR receiver. Nothing, however. A bit more reading, and I came across;another library for the SI5351… this one managing to avoid all the divider/multiplier calculations necessary with the Adafruit library. I modified the code once again to include this, and instead of doing any calculations, just wrote the required frequency directly to the clock. This time, I could hear a tone on the receiver. As I turned the encoder, the frequency on the display changed, and I could hear the tone get slightly higher in pitch… success by any measure.
\n
\nIt only remains to case this and use it to align a few projects.
\n
\n;
\n
\n
; | |
; | #include <Wire.h> \n\t\t\t#include <LiquidCrystal_I2C.h> |
; | #include <Encoder.h> |
; | #include si5351.h |
; | ; |
; | Si5351 clockgen; |
; | ; |
; | const int BUTTON = 8; |
; | long oldPosition = -999; |
; | long int step = 1; |
; | long int frequency = 14000000; |
; | ; |
; | Encoder myEnc(5, 6); |
; | LiquidCrystal_I2C lcd(0x27,20,4); //set the LCD address to 0x27 for a 16 chars and 2 line display |
; | ; |
; | void setup () { |
; | lcd.init(); |
; | lcd.backlight(); |
; | lcd.setCursor(0, 0); |
; | lcd.print(Initialising…); |
; | clockgen.init(SI5351_CRYSTAL_LOAD_8PF); |
; | lcd.setCursor(0, 1); |
; | lcd.print(OK!); |
; | delay (2000); |
; | pinMode (BUTTON, INPUT); |
; | digitalWrite (BUTTON, HIGH); // Pull High Restance |
; | lcd.init(); |
; | lcd.backlight(); |
; | lcd.setCursor(0, 0); |
; | lcd.print(Freq: ); |
; | lcd.setCursor(6, 0); |
; | lcd.print(frequency); |
; | lcd.setCursor(0, 1); |
; | lcd.print(Step: ); |
; | lcd.setCursor(6, 1); |
; | lcd.print(step); |
; | // Set CLK0 to output 14 MHz with a fixed PLL frequency |
; | clockgen.set_pll(SI5351_PLL_FIXED, SI5351_PLLA); |
; | clockgen.set_freq(frequency, SI5351_PLL_FIXED, SI5351_CLK0); |
; | } |
; | ; |
; | void loop () { |
; | int delta; |
; | if (!(digitalRead(BUTTON))) { |
; | if (step >= 1000000) |
; | step = 1; |
; | else step = step * 10; |
; | lcd.setCursor(6, 1); |
; | lcd.print(step); |
; | lcd.setCursor(6+(step/10),1); |
; | lcd.print( ); |
; | delay (200); |
; | } |
; | long newPosition = myEnc.read(); |
; | if (newPosition != oldPosition) { |
; | delta = newPosition > oldPosition? 1 : -1; |
; | oldPosition = newPosition; |
; | frequency = frequency + (delta * step); |
; | lcd.setCursor(6, 0); |
; | lcd.print(frequency); |
; | clockgen.set_freq(frequency, SI5351_PLL_FIXED, SI5351_CLK0); |
; | } |
; | } |