2011
08.01

About a month ago, Sparkfun Electronics released a SI4735 AM & FM Receiver Shield for the Arduino.  Based on the Silicon Labs SI4735 receiver on a chip, it looked to be a very promising board.  One small problem, they evidently never tested it on a 5V Arduino, or their Arduino’s inputs were tolerant of being driven from a 3V source.

si4735 Shield

The commenters on Sparkfun’s product page quickly discovered the problem and offered several solutions, however, over on the Arduino forum, another poster found the real culprit and offered an incorrect, albeit working, solution.  I decided I wanted to do this right, and reliably, so I decided on a proper level shifter.

I had a couple of Sparkfun BOB-08745 Logic Level Converter boards kicking around from an iPod interfacing project that never happened so I pressed one of them into service.  I’ll eventually replace the BOB-08745 with a single FET as soon as I find a proper one in a TO-92 case.

Once again… I have to wonder about Sparkfun’s quality control and engineering checks, there were several complaints about the efficacy of the 5V to 3V (RX) section, read the comments on the product page but I don’t need that functionality.

I added header pins to the board, so I can later use it elsewhere and on a breadboard and only soldered the pins needed to the SI4735 board.  I cut the trace to the D12 line and soldered to a convenient via in this trace.

Some commenters on the Sparkfun product page also noted there is a missing delay() in the getResponse function, so change the following in si4735.cpp from…

void Si4735::getResponse(char * response)
{
digitalWrite(SS, LOW);
delay(1);
spiTransfer(0xE0);  //Set up to read the long response
for(int i=0; i<16; i++)*response++ = spiTransfer(0×00);  //Assign the response to the string.
digitalWrite(SS, HIGH);
}

To…

void Si4735::getResponse(char * response)
{
digitalWrite(SS, LOW);
delay(1);
spiTransfer(0xE0);  //Set up to read the long response
delay(1);
for(int i=0; i<16; i++)*response++ = spiTransfer(0×00);  //Assign the response to the string.
digitalWrite(SS, HIGH);
}

After installation and the change above I was still getting responses I didn’t expect and I found yet another problem.  The source code of the Si4735_SerialExample states in the comments;

The command must be terminated with either a newline or carriage* return character. To enable this in the Arduino Serial Terminal, make sure the drop down menu located in the bottom right hand side of the * terminal window (not the baud rate one, but right next to that) reads ‘Newline,’ ‘Carriage Return,’ or ‘Both NL and CR.’

If you set the line end to CR/LF, this has the effect of sending the command, then a null command, resulting in missing the response.  Once I set that to either CR or LF, responses began to come in.

Now I am getting responses but they are still nonsensical!  After spending several hours trying this and that, I found even yet another problem, the SPI interface was running too fast, missing bits.  I found the following line in the si4735.cpp library

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);

This runs the SPI interface at its fastest, 4MHz, resulting in missing bits.  I set it to its slowest, 250KHz via the following code and now responses make sense!!!

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);

I’ll play a little further with SPI speed, but it’s not really an issue, as long as the data is transfered in a few mS, as long as it happens.  With that done, the board is 100% functional.  I can tune it and read back important parameters.  It’s quite late now, I will continue with this tomorrow as something else concerns me, I am getting two different RSSI and SNR readings depending on where I read them.

  1. Good blog post, very well documented. The bit of information you provided concerning SPCR will most likely save me a few hours of headaches as well when I get further into my project =P