Tuesday, September 26, 2017

A Two Channel SI5351 Signal Generator Update 9/28 9/30/17

After getting the sketches written for the SI5351 board written to support multiple display types, I decided I need to write one more. Now that Pete is moving the Simpleceiver to a single conversion super-het, I will have to worry about the BFO as well as VFO frequency.  Since I will probably use a different crystal frequency than Pete for the IF filter, I need to have a way to find the correct BFO frequency for both upper and lower side band. The easiest way to do that is to write a sketch that uses the 5351 as a two channel signal generator,with independent control of both frequencies.  
Using what I had already written as a starting point, it did not take too long to get a usable sketch working.   One thing that I did different in my sketch, from the one that Pete sent me was the way I handle the rotary encoder.  In Pete's sketch, he has the frequency setting code in the encoder Interrupt Service Routine.
For a while now I have been using an ISR that just changes the value of a global variable I call encoder. So in my sketch I declare the variable and write the ISR so the only thing it does is change that variable.

int encoder = 0;

ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result) {
    if (result == DIR_CW)
      encoder ++;
    else encoder --;

This allows me to use the encoder ISR to control multiple items, such as menu selection, in this case two frequency values. Since in any non zero value is treated as truea simple
  if (encoder) is the only thing needed to test for an encoder event.   The only thing you have to remember to do is reset the variable back to zero when you leave the function that was checking for an encoder event.
After playing with the sketch on the 5351 board I had been using to test the other sketches, I decided that I would use another board and
make a dedicated two channel signal generator.  The 5351 provides up to three channels of fairly high level square wave output, so it would not be ideal for some uses.  But, for testing double balanced mixer circuits it would be nearly ideal. With an external step attenuator it could be used for many other quick bench tests that would normally require a larger signal generator.  Checking size, it looks like it could be built just about the same size as an Altoids tin, possibly a little deeper to contain a 9V battery.

Bottom parts placement
With that in mind I built up another board, and added some documents as to parts layout.  I have all of the passive components mounted on the bottom of the board.  To keep the size down, I used 1206 size SMD components, but leaded components could also be used 'Muppet' style if you lay them flat to the board.  Since I plan on having this battery operated, I added the optional voltage divider resistors for the battery monitoring software.

When I did the board layout, I tried to think of several ways that components can be stacked on the main board.  One of them was the external rotary encoder module.  You can put a right angle female header on the board and just plug it in, or you can bend the module header pins straight up and mount it to the board from the bottom.  This makes it a little smaller, and provides a stronger assembly.  The Nano and SI5351 board can be mounted several ways to provide a small assembly if needed. 

 For this project I mounted them on the top of the board to make a unit that is less than 1" thick excluding the encoder shaft. 
After I had the assembly put together I loaded the latest sketch and gave it a try.  Everything seems to work, except for an inconsistent issue with turning a channel off if only one is in use.  I will have to check and see if it is something with the way I am setting up the 5351 or something with the library I am using.  But so far it looks like it will be a handy little addition to the bench.  Now to design and print a 3D case for it.

Update 9/28/17
I spent quite a bit of time today designing a case for the 5351 signal generator.  I tried three designs before I finally came up with something I really liked.  Overall size turned out to be about 9x9x3 cm. and that include the height of the feet I designed in the bottom plate of the case.  The more I work with designing and printing cases and parts for my projects, the more I wonder how I got along with out this ability.  In the past I have spent many hours down in my workshop cutting, drilling, and filing assorted project boxes trying to make everything fit correctly.  Quite often I was not happy with the results, or for one reason or another had to start over.  Now with the 3D printer and some 3D design software, I can mostly make anything I desire in way of cases for my project.  The ability to design in mounting posts for boards and components, along with cutouts and bezels makes the process much more enjoyable.  Some times things don't turnout the way you think they should, but it is usually fairly easy to make any correction and print another part.  Overall material cost for most cases is well under $1.00, so even if it takes a few tries it is probably less than it would have cost to buy a project box that I would have to modify.  And the nice thing is if I want to make more than one, it just takes a few minutes to start a new print job.  Then just a matter of waiting for the new part to be printed on the little printer setting next to my desk.

After changing my mind about the design I wanted I came up with this.  It included mounting posts for the board, and a bezel for the display.  Since I would have to change batteries I designed it for brass threaded inserts that I will hot press in place with a soldering iron. This will last longer than just threading screws into the plastic standoffs, like I do for the board.  Now all I have to do is finish installing everything and take a final look at the software.

After finishing printing the top of the case, there was a something I wanted to add to the software.  Since this was to be a battery operated device, I added the software to utilize the voltage divider I designed into the board.  I have used this for most of my battery operated devices, and have a small software building block I can easily add to a sketch.  First, I add definitions for the ADC pin used to read the Battery voltage,  and the resistor values used in the voltage divider. And the variable that represents battery voltage x 100.  

#define vin_BAT     A7      //ADC pin used to read battery voltage
// voltage divider values
#define R1         (1000)  // from GND to vin_BAT, 
#define R2         (4700)  // from + power supply to vin_BAT

float   SupplyVoltage;     // supply voltage x 100

Then a I have a simple function that reads the voltage and scales by the voltage divider values to give the supply voltage.  The resulting value is the battery voltage times 100 to give a resolution of 10mV.
I display the battery voltage at the bottom of the screen.  I also test the value, and if it is below 6.5 volts I change  the text color to warn the battery voltage is getting low.

void measuresupplyvolt() {
  SupplyVoltage = analogRead(vin_BAT);   // Read  supply voltage
// compute battery voltage using voltage divider values
  SupplyVoltage = map(SupplyVoltage, 0, 1023, 0, (500 * (  float R2 +  float R1) / float R1)); 
  // SupplyVoltage = SupplyVoltage + 70;   // add in voltage drop of diode  if installed
  display.fillRect(12, 114, 100, 8, BLUE);  // clear last reading
  display.setCursor(22, 114);
// change color if below 6.5v to warn of battery getting low
  else  display.setTextColor(YELLOW);
  display.print("Battery = ");
  display.print(" V.");


To provide continuous battery voltage monitoring, I use a simple decrementing loop counter that forces a reading around every two minutes.  I start by initializing a variable that I will use as a counter that is decremented each time through the main loop. From experience with other programs a value of 5000 gives a reading about every two minutes.  Just scale up or down for different reading periods.  
int battery_delay = 5000;
Near the end of the loop this variable is decremented each time the loop is completed.  I test to see if the counter has made it to zero, if so I measure and display the battery voltage, and reset the counter for the next two minute delay.

  if ( battery_delay <= 0) {
    battery_delay = 5000;


With the software finished, I assembled the components in the case top, and was ready for the bottom panel.  I had originally planned on a simple flat piece, with some rubber feet glued on the bottom.  I decided I wanted to try to add a way to have the unit sit up at an angle.  Looking around on thingiverse, I checked out some of the keyboard feet designs I found there.   Modifying them a little bit, I added 4 molded in feet, two of which had holes that would hold pins on the ends of a small foot that could be laid down flat or rotated up to hold the unit at an angle. Now that the little signal generator is finished I am very happy with the way it turned out.  It should fit the bill when I want to do some quick testing on the bench. and should work really well for finding correct the BFO frequencies for the Simpleceiver and probably for the unused BITX40 board I still have sitting around.


  1. just ordered some boards, now to gather the rest of the bits. looking forward to building something again

  2. What display did you use in the signal generator?

    1. it is the 1.8" 160x128 TFT display with the STS735 controller chip

  3. Can you share your case? Or is it at thingverse? Thanks DuWayne...

    1. .STL files for case is in main project folder

  4. DuWayne, I hate to bother you but I finally got things together and I can't compile the code. I tried the latest IDE and 1.6.1. I've tried several different Si5351 libraries (found all the other required libraries). I got the furthest with the 1.8.5 IDE but started having longer errors. I admit I'm not a programmer but have usually gotten Arduino code to work in the past...

  5. If you have the libraries installed in the fefault Arduinoi folders try changing the #include "si5351.h" to #include If that does not work then try Pete's libraries at http://www.n6qw.com/Simpleceiver_Plus.html. Put them in your working folder instead of the default and use #include "si5351.h". That will tell it to look for the files there.
    There are several versions of libraries with the same name around that have been causing propblems.

  6. DuWayne, good news. Just used Pete's libraries, put them in the folder where the .INO file was and it compiled and loaded fine. I'm just running it off the USB from the computer. I see the battery voltage 4.37V. The encoder push button works but the encoder doesn't work. I notice when I do a long push, to change channels the 2nd channel "pre-fills" with 10 MHz (same as channel 1). I tested on my counter, both channels are putting out 10 MHz.
    Do you think the encoder problem is low voltage or the encoder itself? I did clean up the solder joints on the encoder board before I soldered it to your board. I want to print your case so I built mine like your pictures.
    Display is small but very sharp. Thanks for the help.

  7. Voltage monitor only measures voltage from a battery. Usually do not see anything when powered off of USB. Default startup frequency is 10MHz for both channels. Ohm out connections from the encoder pins to the Arduino to make sure the encder is not wired different than the one I used. If you have a scope make sure you get pulses when you turn the encoder

  8. DuWayne, I printed the case (still haven't looked into the encoder problem...). Case fits beautifully. I was printing knobs for my uBitx from Thingverse and so many of those files are off - too big or small. Your case was PERFECT!
    I have an older PrinterBot Simple Maker Edition printer that I've modded a few times for a bigger print volume. Still works, not the prettiest prints but functional.

  9. DuWayne, are you willing to share the gerbers for the pc board?

    Thank you.


    1. Check the link in this post A SI5351 VFO-BFO UPDATE 9/15 9/16 9/21 11/15/17

  10. Had lots of trouble finding correct libraries, but finally compiled and uploaded. Now display just white screen, after trying several possibilities found needed series resistor 1K ohm on all control lines. Now to make new PCB!