06 April 2013

Using the SPI bus with Ethernet, SD-card and NRF24L01 and other slave devices together

I currently work on an project using the popular NRF24L01 module where I came across the question how to avoid conflicts of new designs and existing Arduino boards.
The problem when using the W5100 based Ethernet shield including the  SD Card adapter and the NRF24L01 Modules together with a Arduino UNO board is that all of them are using the same SPI bus for the data transfer to the chips. Here is an overview of how to make them work all together.
Here the master is always the same ATMEGA328 chip on the Arduino board and the 3 chips are slave devices.

The SPI bus concept

A brief explanation of the SPI bus can be found on wikipedia. See http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
The SPI bus needs 4 signals to work:
SCK or SCLK (serial clock) The clock signal that sets the tempo for any data transfer. This signal is generated by the master chip.
On the Arduino Uno this signal is available on pin 13 and ICSP 3.
MISO (master input, slave output) This signal line transfers the data from a slave device to the master chip.
On the Arduino Uno this signal is available on pin 12 and ICSP 1.
MOSI (master output, slave input) This signal line transfers the data from the master to the slave devices.
On the Arduino Uno this signal is available on pin 11 and ICSP 4.
SS or CSN (Slave Select) This signal makes a slave active by selecting it with a low signal.
On the Arduino Uno this signal has to be discussed…
Remark: The signal lines SCK, MOSI and MISO are also available on the ICSP header, see below.
The signal lines SCK, MOSI and MISO can permanently remain connected to all participating chips. However the Slave Select signal has to be different for every device.

Advantages in using the ICSP header

The SPI signals on an Arduino Mega board are not available on the pins 10, 11, 12 and 13 because this board uses another processor. But because programming an ATMEGA chip through the ICSP is internally also using the SPI interface, the signals are available on the ICSP header too. With the Arduino Ethernet Shield Version 06 the design has changed so that the SPI signals are not taken from the pins 11, 12 and 13 but from the pins ISP 4, 1 and 3. If you use an Arduino UNO or 2009 however these pins are connected on the main board.  When designing new shields for Standard and MEGA boards with SPI usage I recommended using the ICSP header like the Ethernet Shield does.

Pin 10

The Arduino pin 10, also labeled SS, also known as PB2 for ATMEGA328, is used by ATMEL to indicate whether the processor is used as an SPI master or slaver device. That pin 10 must remain an output or the SPI hardware will go into 'slave' mode.
Using this pin 10 for example on the Ethernet Shield is fine, but if you use other SPI slave devices, keep in mind to no use this pin for input purpose – better don’t use it to avoid conflicts.

Using multiple SPI bus slave devices

When using multiple slave devices on the same SPI bus there is no principle problem with the lines SCK, MOSI and MISO. Because every slave device needs its own slave select signal there are conflicts using the available Arduino pins. When you stack multiple ARDUINO shields on a single Arduino board you may also have conflicts with other pins the shield uses so you have to take care of other conflicts too. Here are some common pin usages:

Arduino Shield Salve device Arduino Pin
Ethernet version 01 W5100 chip Slave Select 10
Ethernet version 06 W5100 chip Slave Select 10
Ethernet version 06 SD card Slave Select 4

Using a NRF24L01 radio module

In different samples where the NRF24L01 radio is using the Arduino pin 9 for SS and using pin 8 for the Chip Enable signal but also 8 and 7 is used in same samples. There is no standard definition right now and therefore you have to tell the NRF24L01 library what signals to use for Slave Select and Chip Enable.
I personally recommend using 7 for Chip Enable and 8 for Slave Select because the pin 9 is one of the possible PWM output pins. When designing new Shields these pins assignments should be changeable in any way, just to be friendly to other shields… and having the chance to settle conflicts.

More Readings:

Design of the Arduino Ethernet Shield: http://arduino.cc/en/Main/ArduinoEthernetShield

Using the SD-Slot on the EthernetShield with Hardware SPI: http://playground.arduino.cc//Main/EthernetShieldSDHardwareSPIMod General tutorial: http://tronixstuff.wordpress.com/  About the NRF24L01: http://playground.arduino.cc/InterfacingWithHardware/Nrf24L01