Saturday, July 18, 2015

Si570 revisited - flexible Arduino controller

Back in 2009, I did a blog post about my then new Si570 synthesizer board being controlled by my then new Arduino MCU board.  I got a surprising number of requests for my source code, which was a little embarrassing because my programs mainly sent pre-calculated register values to the Si570 to program discrete frequencies.  At best, one program used the "ratio" method to tune plus or minus 30 kHz or so from the programmed center frequency, as is allowed by the chip design.

I wanted to do an "any frequency, right now" control scheme, but doing that on the Si570 is much more difficult than it is on the AD9850 family of DDS synthesizers.  The Si570 uses one 3-bit divider register, one 7-bit divider register  and one 38-bit divider register plus the crystal frequency to program its output.  And it's not deterministic -- multiple sets of register values will work and many others will not work, in accordance with rules defined in the data sheet.  Whew!  It's fairly simple to crank out a set of registers for a given frequency "off line" and send them to the chip.  It's quite another thing do to it in real time as fast as you normally turn a rotary encoder knob.

A new Arduino Si570 control program

The best way to approach a programming problem is to find someone who has solved it before.  Craig Johnson AA0ZZ did a very nice Si570 control program for the PIC16F88 MCU and described it in a July/August 2011 QEX article. His is all done in assembly language. The methodology is very important to the solution.  Craig found sets of two of the three registers that would work in each of 24 "bands" from 10 MHz to 157 MHz and saved them in tables.  The actual crystal reference frequency (see "Calibration") was used with those register values to  create another band table of pre-calculated constants.  Now, much of the heavy number crunching needed for a frequency change is already done, although there is plenty of 64 bit integer math left that must be done efficiently for each frequency change.

Anyway, using Craig's article, the data sheet, and my HP48G calculator, I was able to eventually grasp all the nuances and program an Arduino Nano to do essentially the same task: Take a frequency as input, generate the six registers required and send them to the Si570 board via the I2C bus.

My program right now

I decided to put on the brakes at the point where I have all the Si570 control routines working, but before I began to "personalize" the program with menus, LCD display, rotary encoder control and so on.  I'll add those things and publish the source shortly (?), but I want to put out the basic "kernel" of functions right now for readers who are programmers and want to add their own bells and whistles and user interface schemes.

Right now the program is functioning in a "demo mode".  It does a calibration, then goes to 14.025 MHz and tunes up and down in ten 10 Hz steps forever.  That's so a user can hear that it is working (changing frequency) without having to tune the receiver to follow it.

Routines in place are the all important one that accepts a frequency to 1 Hz resolution, calculates the registers, and send them to the Si570.  Also included are step size functions and step-up and step-down functions.

Invisible to the user but important are functions to detect band change (so the correct values will be selected from the band data tables) and to detect movement more than 3500 PPM plus or minus the last center frequency.  When this happens, the Si570 requires a "freeze" operation to load a new "center" frequency.  This is all automated in the software.

Also in the program are some serial routines to allow it to talk to the PC via the Serial Monitor in the Arduino IDE.  That's mostly for troubleshooting and development so you could delete all the serial stuff and save some memory.

Currently, the calibrate() routine sends a bunch of information to the user over the serial link.  After uploading the program, press control-shift-M to open the serial monitor and see start-up registers, crystal frequency and so on.


This is not like the calibration you are accustomed to with AD98xx synthesizers where you calibrate to an external standard. Silicon Labs custom calibrated your Si570 at the factory and stored values in all the registers to cause it to start up on the frequency specified at purchase time.  This is to correct for expected small variations in the 114.285 MHz internal crystal reference.

So when the Arduino does its calibration, it is expected to "know" the specified start-up frequency.  Then it downloads the register values programmed into non-volatile memory by Silicon Labs and uses those to "back calculate" the actual value of the reference crystal, which is then used to generate the constants in the band tables.

My software currently calibrates every time it starts up.  Craig's software does it if you hold in a button when powering the PIC up. I can see why you might want it to be "dealer's choice" so I will make it an option in my full featured version.

Some hardware notes

Connection between the Arduino and Si570 is pretty simple - two wires plus ground.  But it can't be quite that simple if you have a 3.3 V Si570 and 5 V Arduino.  You need bi-directional logic level shifters between the two. I used two BS170 MOSFETs plus two resistors as Craig showed in his article.  You can get the same on a tiny board from eBay if you want to go that way.

Another hardware issue I encountered was unexpected - RFI.  When I first tried the program with the hardware, I got a lot of errors in I2C transmissions.  When I plugged the RF output from the Si570 into a power meter with 50 ohm input, most of it went away.  So it seems that reflections from the output can cause problems - terminate your RF output!  I also added a 4.7 uF tantalum capacitor from my 3.3 volt reference on the MOSFET shifters to ground. That may have helped a bit.

I'm getting out about +14 dBm, BTW.  That's a lot of RF and I'm glad to have it.

Speaking of hardware issues, the Si570 is a pretty clean RF source with low phase noise.  Generally better than most AD98xx units and better than the new Si5351 part, although I have and use both of those.

Another hardware caveat:  I've been burned a couple of times by inaccurate Arduino Nano documentation.  This time I spent half a day troubleshooting I2C communications before finding that SDA and SCL are actually on pins A4 and A5, not D4 and D5 as shown on some drawings.

What about that startup frequency?  That's important to the calibration.  I lot of Si570 boards out there were bought with the Sotfrock project in mind.  In those circuits, the VFO operates at 4x the operating frequency and a lot of Si570s were purchased with a startup frequency of 14.080 MHz in mind, meaning they start up at 56.320 MHz.  Mine is one of those.  Others, possibly taking the default start-up frequency, may start up at 10.000 MHz.  If you don't know, power up your Si570 and check it with a frequency counter.  If it's other than 56.320 (or thereabouts), change this line in the source code to suit:

  #define STARTUP_FREQ 56320000UL

Finally, where do you get those Si570s mounted on a plug-in board?  I see several people (mostly hams) on the web offering them.  Mine was made by WA6UFQ. You might start your search from a Softrock site.

Regarding power the Si570 ... It uses more than 100 mA so don't use a 78L05 regulator and I wouldn't try to have the Arduino supply the power either. I used a 78M05 with a small heat sink.  it's rated at 500 mA. Why am I talking about 5 V regulators? My Si570 board has a 3.3 V regulator on it and wants 5 V to the board.

Let's wrap it up

Where's the source code?

Right here:

I won't be revising this file except to fix any errors that may be lurking in it.  Later I hope to add a link to a version with LCD, rotary encoder and so forth.

Here's a link to Craig Johnson's page, which includes the QEX article:

If you don't want to fight through creating an Arduino based controller, Craig's PIC based card works very well and allows LCD, rotary controller and so forth.  (I have one.)


Nick, WA5BDU