SPI - Arduino Pro Mini vs. Redboard Turbo

The Bottom Line: Default SPI setup works well on the Arduino Pro Mini, but mysteriously fails on the Redboard Turbo.

And before we start the ‘Yeah, but…’ replies, let’s document the rest of the background to this observation.

The Gory Details - Let’s start with The Facts:

The Arduino Pro Mini is just a smaller form factor of the Arduino Uno. It’s a well known and tested architecture. The default pins for SPI are as follows: MOSI on Pin 11, MISO on Pin 12, SCK on Pin 13, and usually Pin 10 is used as the Chip Select (CS) pin. These same electrical signals are brought out to the ICSP header on the Uno.

However the Pro Mini is a 5 volt device, and the SPI device that is being tested here is a 3.3 volt unit. (Does is really matter what the specific device is? SPI should work the same regardless, if the setup is identical. Well, then…) Therefore a bidirectional level shifter must be used between the Pro Mini and the SPI chip. This is not a problem, and the wiring of such a level shifter is well known and documented for the standard Arduino setup.

The Redboard Turbo, however, has a different architecture, and uses the 32-bit SAMD21 processor rather than the 8-bit Atmel processor of the Uno. The Arduino compatible Redboard Turbo does not use the same pins for its default SPI port. It only has the ICSP header to provide access to the default SPI interface. The pin numbers for the SPI signals on the Redboard Turbo are as follows: MISO on Pin 22, MOSI on Pin 23, SCK on Pin 24, and it is still possible to use Pin 10 as the Chip Select (CS) pin. (The software I’ve written does all the manual toggling of the CS pin, as needed.)

The Redboard Turbo is also a 3.3 volt board, and so no level shifting is required to interface with the SPI sensor. This makes the breadboard setup an easy 6-wire connection.

This knowledge allows us to set up two breadboards, one for each processor. I just manual place the SPI chip in the breadboard of choice for running any particular test. So, the same chip is used in both setups, removing that source of variability.

Connection validation:

  1. I used a voltmeter to measure the voltage at the breadboard for the where SPI chip will go. Both boards measure a voltage of 3.29 volts, which is nearly perfect for our testing.

  2. The individual pin connections are verified with an LED and a modified Blink program on each processor. This validates that the pins for MOSI, MISO, SCK and CS are all controllable from the pin numbers that are documented, and are wired correctly on both breadboards.

  3. The last test is a loopback test, where MISO and MOSI are jumpered together. This results in the same data that is sent out being seen as input data. For both processor breadboard layouts, this test succeeds, and proves that the data sent out is seen coming back in.

  4. And, if the loopback wire is removed, then all the SPI interface reads back is 0xff. That seems reasonable.

The Software:

The SPI sensor under test has no Arduino Library written for it. So, I decided to write my own. It’s more than a trivial task, but I feel it will be well worth it if others can use this library when it’s completed.

So, after researching other SPI implementations, and reading up on the SPI library in the Arduino IDE, I forged ahead and came up with something that works - sort of. And therein lies the rub. The software works perfectly on the Arduino Pro Mini. It’s able to initialize the SPI device, and read sensor values just fine. I get an endless loop of data being printed out.

However, on the Redboard Turbo, I run the exact same software (okay, Serial gets replaced by SerialUSB. Understood) but all I get back now is 0xff - like the SPI device isn’t even there.

Hmm, for a possible clue, I look at the online documentation Sparkfun has for adding SERCOM ports to the SAMD processor boards - particularly SPI. The only difference I see in the posted code is the inclusion of a ‘delay(25)’ statement just after the SPI.transfer() is done, and before the CS line is pulled high. So, I try adding in that line of code. Same result.

I then check the definitions for PIN_SPI_MOSI, PIN_SPI_MISO, and PIN_SPI_SCK. All are as expected.

The fact that the loopback test works leads me to two possibilities:

  1. The default SPI has MOSI and MISO pin definitions reversed.

OR

  1. The SCK pin isn’t really putting out a clock.

So, which is it? Wait, I’m using breadboards, so I can just switch the MISO and MOSI lines on the Redboard Turbo to see if that fixes it, if I don’t let out the magic smoke in the process. Okay, I try that, and get back all 0x00. That didn’t work. Checking again with the Pro Mini verifies that the SPI chip survived though, and is still giving out good readings there.

That leaves a possible issue with the SCK line. I’m defining the SPI port as follows:

SPISettings spiSettings{2000000, MSBFIRST, SPI_MODE0};

I’ve tried to slow down the SPI clock value too, and that has no effect.

So where could the problem be? Is the SCK signal even getting out? Or is there something else that I haven’t even considered looking at here?

I now leave this conundrum in the hands of the gurus at Sparkfun to solve, because I’m at my wits end.

Got it. The critical clue came from looking at the implementation of another SPI device- the BME 280 pressure/temperature/humidity sensor breakout board, also sold by Sparkfun. The breakout board includes a pullup resistor on the Chip Select/Slave Select line. After I added a similar 4.7k ohm pullup resistor, the sketch and library started to function as expected on the Redboard Turbo. Amazingly, the Arduino Pro Mini was able to run its SPI interface without that pullup resistor in place. Go figure.