Lately I have been having lots of fun working on a variety of different bench projects, all involving very different technologies, switching between them as parts arrive and time allows. I have been experimenting with space charge tubes, with the goal of building a low voltage regen receiver. Also in progress is a classic VXO controlled CW transmitter, using standard through-hole components. I have had a copy of W1FB’s “QRP Notebook” for two decades, but it is only in the last year or so that I have felt capable enough of trying some of these classic projects. It would be really cool to build a CW transmitter capable of operating on more than one crystal controlled frequency. This might evolve into an actual transceiver some day, who knows?
But very recently I became intrigued when I heard of NT7S, Jason Milldrum`s Indiegogo campaign to crowd fund a breakout board for the SI5351 clock generator chip. This chip has been getting a lot of ham radio press lately. It is capable of generating up to three simultaneous, high precision RF signals, in a range of 1 – 160 MHz. It is easily controlled by any microcontroller or computer which can communicate using the I2C bus standard.
I2C is widely supported, and in particular by the Arduino family of microcontroller boards, and the Raspberry Pi among others. This makes building a DDS VFO totally a snap, and the range of other projects possible is pretty vast.
I jumped in with a contribution for a kit. The campaign exceeded its goals by a wide margin, and soon (beginning of March I think) my board kit arrived. At the time, I was working on some of those other projects, and my only Arduino board was permanently embedded in a completed project (The DFR), so I put the kit aside until I could get my hands on another Arduino to start experimenting.
I decided to commit this new Arduino to permanent, breadboard duty. I will use it for development, and then transfer any code and hardware to a permanent installation with another Arduino, preferably the smallest, cheapest board that will run the code. So, for my breadboard I went all out and bought a Mega 2560. This bad boy has 256kb flash memory, and 4kb SRAM, not likely I will run out of room in my sketches like I did with DFR on the Uno. However, for the SI5351 project I am definitely going to stay to the small-resource end of the line;
hopefully the code I wind up with will run on an inexpensive Nano.
(Update: now that the code is done, I got it small enough to run on any Arduino with 32kb flash memory. This includes most of the ATmega328 based boards, but regrettably not the Nano.)
My breadboard is built on an eco-sensitive, sustainable, bamboo cutting board that cost about $5 at our local supermarket. I didn’t know it at the time, but it turns out that bamboo drills very nicely, and is very rigid for its thickness. It makes a very stable platform for the Arduino and surrounding lash-up. On of the things that was a bit annoying working on the DFR project was having the Uno with a tangle of wires going to a separate breadboard – the slightest jostling caused jumpers to fall off, and I dragged the whole thing off the desk more than once by snagging a wire. No, having all the bits anchored to one solid platform makes things much easier.
I recently came across, quite by accident, an article in the December 2013 QST, “Modern Breadboarding Tools and Techniques” by Richard Barnett, N9NP, where he talks about various breadboarding techniques. I have always thought those plug-in plastic breadboard blocks were basically unusable at RF frequencies, because of all the stray capacitances, but Richard suggests mounting the blocks on copper clad PCB board to provide a good ground plane, and ground the dickens out of it. Also, keep the components connections separated by two or three rows to minimize capacitance from the connectors.
Sounded good to me, so my bamboo breadboard sports two breadboard blocks mounted on PCB. The two sections are well grounded and interconnected by a bridge of PCB which runs under the Arduino. At the time of this writing, I haven’t tried any RF circuits on the breadboard blocks yet, so all the returns are not in. It looks cool, though.
My goal for the SI5351 was to set up a 3-band VFO, with a user interface that would allow selecting the band, and using an encoder to adjust the frequency. This would give a kind of 3 register “memory” effect – each channel on the SI5351 would retain the last frequency setting and jumping between frequencies would just be a matter of pressing a button to select the channel.
One of the really cool things about software defined radio, is that you can write the software without actually having the hardware for the radio. So, even though I hadn’t built the SI5351 breakout board yet, I started right in on the UI with the Arduino breadboard. The user interface would consist of one button to cycle through the three channels, a rotary encoder to adjust the frequency of the current channel up or down, and using the built-in switch on the rotary encoder, a selection of how fast the frequency changes per pulse on the encoder. This would allow easy large excursions, and precise small ones. Nothing is more tedious than moving from 7.0 MHz to 7.2 MHz in at 24 Hz per revolution.
The UI would also have to include some kind of display. I found two inexpensive candidates on Amazon – a 2 line x 20 character LCD, and a tiny but very legible, graphics-capable OLED display (128×64 pixels), which also uses the I2C bus. I wound up going with the OLED display – it only takes 4 wires to interconnect, as compared to 10 for the LCD (a parallel rather than serial interface.) Here you can see the entire lash-up including the SI5351 board:
Code for the UI came from several sources. I decided to manage the switches by polling them in the Arduino code loop. There is not too much going on in the Arduino in this application, so the code loop doesn’t have to operate too fast. A 50 millisecond loop time was more than sufficiently responsive for the button presses. An additional reason for polling the buttons is that I have some library code developed for the DFR that wraps all the debouncing and polling logic. This code can also distinguish between a short press and a long press on each button – initially I did not plan to make use of this feature, but later decided to add two functions – classic feature creep.
Rather than poll the encoder, I decided to use hardware interrupts to read it. This gives much better resolution and allows handling the encoder at a faster rate than the main code loop. The code I wrote for it was a distillation of several example sketches I found online – it seems to work well in this context with no dropped counts. The encoder I used came from Mouser; it cost less than $2 per piece, and seems to work well. I found a reference to it in another project: N6QW Pete Juliano’s “Belthorn III QRP SSB Transceiver”, (video here) and decided to give it a try. It works very well.
Code for driving the ssd1306 OLED display comes from two Adafruit open source libraries. These libraries also support a wide variety of graphical effects, which I did not take advantage of in this sketch. The only caveat using these libraries is that the code initializes the display with the Adafruit logo – you have to explicitly clear the device before writing anything to display. It was easy to figure out the display calls, looking at the example sketch which pretty much exercises everything in the library.
A note for you programmers out there: interestingly the Adafruit library code does not include the guard macros commonly found at the beginning of the .h include files. These macros prevent redefinition errors if the include file is included in the source code more than once. If you inadvertently do include the Adafruit headers more than once, you will get compile errors that look something like this:
The simple fix is to find and remove all but one set of Adafruit includes.
One other note on the Arduino sketch: I structured this code to make it easy to replace the libraries for driving the display and the SI5351, if you wish to try something else. Reference to all of the third-party code is accomplished via an abstract base class, and an implementation class. For example, the main sketch points to a class called VFODisplay, which defines all of the display functions, but the actual calls to the Adafruit library are in a class derived from VFODisplay called ssd1306_VFODisplay. So, if you if you wanted to use a different display library, or a different type of display altogether, all you need to do is derive a new class from VFODisplay with the appropriate code for your setup defined for each display function.
Okay, if you are not an Arduino programmer, and that last paragraph didn’t make any sense, just ignore it. If you use the same hardware and libraries I used, all will be well.
You can purchase the SI5351 breakout board kit from Jason’s company, etherkit.com. Documentation, and links to the library code for the board kit can be found on this page. Code for the SI5351 chip comes from Jason. It is well documented and it is clear how to drive the chip. Integration into my UI was easy, and the entire set up is working nicely as breadboarded.
Here is a Youtube video with a short demonstration of the “rig”
The code for my sketch hosted on github You can download it here. The easiest way to install it is to download the zip file. Extract the zip file on your computer, and copy the sketch and library folders to your Arduino sketchbook. My code is released under a GPL 2.0 license, you are free to use it and modify it as you like, but anything you do with it must remain open source.
My github repository does not include the other libraries you will need to run the sketch. You can find the device libraries at their respective download locations:
This really is amazing technology. The path from parts to a very sophisticated VFO has never been shorter.