How to Connect Multiple SPI devices to an Arduino Microcontroller


Multiple SPI devices


In this project, we are going to show how to connect multiple SPI devices to an arduino microcontroller.

SPI stands for serial peripheral interface and it's one of the ways in which devices and microcontrollers can communicate with each other.

If a device is an SPI device, this means that the device is made or hardwired to be communicate via SPI.

SPI is a digital communication method available on the arduino microcontroller.

Other digital communication methods include the I2C bus and the serial UART bus.

Unlike the I2C, the SPI bus uses separate lines for sending and receiving data, and it employs an additonal line for selecting which slave device you are talking to. This adds additonal wires, but also eliminates needing different slave device addressses. So what this means is instead of specifying the address of the slave device, we simply address that slave device by turning on its CS pin. It's a lot more simplistic.

Arduino has a built-in SPI library and hardware to communicate with SPI devices.

In this circuit, we will connect 2 SPI devices to an arduino microcontroller. We will show how this is actually hardwared together. The 2 SPI devices will be 2 4131 digital potentiometers. We will wire these 2 SPI potentiometers to the arduino and show how the arduino can control them.

Components Needed

  • 2 MCP4231 Digital Potentiometer
  • 2 220Ω resistor
  • Red LED
  • Green LED
  • Arduino microcontroller


The SPI bus was originally created by Motorola. It is a serial communication standard that enables simultaneous bidirectional communication between a master device and one or more slave devices.

SPI devices are referred to as slave devices. This is because they are seen as slaves in comparison the the microcontroller which normally would function as the master.

SPI devices are synchronous, meaning that data is transmitted clock signal with the master device. This means that the clock from the master device is connected to the clock on the slave device, and they operate in synchrony with the clock signal.

In the connection between a SPI master device and a slave device, a minimum of four data lines are necessary for communication.

These are the shared/serial clock (SCLK), the Master Out Slave In (MOSI), and the Master In Slave Out (MISO)., and the SS or CS pin.

All of this will be explained in detail below.

Below is a diagram of the configuration of an SPI master to the SPI slave devices.

SPI hardware configuration

As explained before, the clocks of the master and slave devices need to work in synchrony. So we connect the master clock to all the clock pins (SCLK) of the slave devices. Therefore, all the slave devices are in synchrony with the master's clock.

Next is the MOSI pin, which is the Master Out Slave In. This is how the master device sends data out to the slave devices. All slave devices have the MISO lines connected together. This MOSI pin may be also be referred to as the SDI (Serial Data In) pin.

Next is the MISO pin, which is the Master In Slave Out device. This is how the master device receives data from the slave devices. All slave devices have the MISO lines connected together. The MISO pin may also be referred to as the sDO (Serial Data Out) pin.

Next is the SS pin which is the Slave Select Pin. This may also be called the Chip Select pin. Each slave device has its own SS pin. This is how the master SPI device, which many times is a microcontroller, knows which slave device to communicate with. If the SS pin is LOW for a certain slave device, this means that the master device is communicating with this device. The master device can only communicate with one slave device at a time. So at any given time, only one slave device can have its SS pin LOW.

Because all devices share the MOSI, MISO, and SCLK lines, all commands sent from the master arrive at each slave device. The SS pin tells the slave whether it should ignore this data or respond to it. Importantly, this means that you must make sure to only have one SS pin LOW.

So you can see now how it's a minimum of four data lines that must be present in any SPI system. The MISO, MOSI, and SCLK signals are shared common with all slave devices. However, the SS chip cannot; it must be separate, because each slave device needs its own unique connection so that it alone can be addressed when the master device wants to communicate with it. So for each additional slave device that you add, you must have an additional line available on the master device for that slave device. So, using the above diagram as an example, if we have added a third slave device, we would have to add another SS3 data line to the master device and then connect to the SS pin of that third slave device.

So the number of I/O pins required on the master device will always be 3+n, where n is the number of slave devices.

Now that we have the hardware connections situated, we will explain how transmission of data works.

The process of communicating with an SPI device is as follows.

First, the SPI pin is set LOW for the slave device which you want the master to communicate with.

Secondly, we toggle the clock line up and down at a speed less than or equal to the transmission speed supported by the slave device.

Thirdly, for each clock cycle, we send 1 bit of data on the MOSI line and receive 1 bit of data on the MISO line.

Fourthly, we continue transmitting data until we are finished, in which case we stop toggling the clock signal.

Fifthly, we then draw the SS pin HIGH in order to stop communication.

If all of this isn't making sense now, it will when we build an actual multiple-SPI device.


Circuit Connecting Multiple SPI Devices to an Arduino Microcontroller

The multiple MCP4231 SPI digital potentiometer circuit that we will build and connect to an Arduino microcontroller is shown below.

Multiple SPI devices to an arduino microcontroller

This above circuit built on a breadboard is shown below.

Multiple SPI devices to an arduino microcontroller

In this circuit, we connect pin 1, the CS pin, to digital pin 10 on the arduino. We connect the CS pin of the second digital potentiometer to arduino pin 9.

We connect pin 2, SCK, to digital pin 13 on the arduino. And then we connect the SCK pin to the SCK pin of the first digital potentiometer, so that the SCKs are both connected common.

We connect pin 3, SDI, to digital pin 11 on the arduino. We connect both SDI pins of the 2 chips together common.

We connect both pin 4s, GND, to the ground terminal on the arduino.

We connect both pin 5s, P0A, to +5V.

We connect pin 6, P0W, the wiper terminal of the potentiometer, to the output device that we want to turn on. In the case of the first digital potentiometer, we can a red LED. And for the second digital potentiomter, we connect a green LED. Being that the wiper terminal attaches to these LEDs, we can adjust the resistance, through software, to display different brightnesses of the LED.

We connect both Pin 7s, P0B, to ground. So one of the terminals of the potentiometer are connected to ground and the other is connected to +5V.

We connect leave pins 8, 9, 10, and 11 disconnected in both chips.

Pin 12, the Shutdown pins, are both connected to +5V. This is just a pin that disconnects the wiper terminal from the resistive network. Being that we don't want the wiper disconnected, we connect it permanently HIGH.

We connect pins 13, SDO, together in common and then connect it to digital pin 12 on the arduino.

We connect pins 14, VDD to +5V.

Code

The code so that we connect 2 SPI digital potentiometers to an arduino microcontroller is shown below.

#include <SPI.h>

byte address = 0x00;
int CS1= 10;
int CS2= 9;

void setup()
{
pinMode (CS1, OUTPUT);
pinMode (CS2, OUTPUT);
SPI.begin();
}

void loop()
{
for (int i = 0; i <= 128; i++)
{
digitalPotWriteRed(i);
delay(10);
}
delay(500);
for (int i = 128; i >= 0; i--)
{
digitalPotWriteRed(i);
delay(10);
}

delay(1000);

for (int i = 0; i <= 128; i++)
{
digitalPotWriteGreen(i);
delay(10);
}
delay(500);
for (int i = 128; i >= 0; i--)
{
digitalPotWriteGreen(i);
delay(10);
}
}

int digitalPotWriteRed(int value)
{
digitalWrite(CS1, LOW);
SPI.transfer(address);
SPI.transfer(value);
digitalWrite(CS1, HIGH);
} int digitalPotWriteGreen(int value)
{
digitalWrite(CS2, LOW);
SPI.transfer(address);
SPI.transfer(value);
digitalWrite(CS2, HIGH);
}


The first thing is we include the SPI.h library. You shouldn't have to download this. It should automatically come with the arduino software. You just have to import the library. Then you should see the line, #include appear.

We then initialize 3 variables. These are address and CS1 and CS2. The Address variable holds a register value. An SPI devices uses registers to know the address of the register on which to perform a command. The MCP4231 command byte is AD3 AD2 AD1 AD0 C1 C0 D9 D8. AD3-1D0 is the address of the register on which you would like to perform a command. The address of the wiper terminal of the potentiometer is 0000. This is what allows you to change the resistance value of the potentiometer. So it's the most important address. C1 C0 is one of 4 possible commands that can be sent to the address we've chosen. We can either read data from the address, write data to the address, increment the data of the wiper by a value of 1, or decrement the data by a value of 1. The command for writing data to the address is 00. Since we want to write data to the wiper terminal (in order to change the resistance), we use 00 (write command). D9 D8 refers the data bits. D9 is undefined and is always 0. D8 refers to the total number of steps in one complete revolution. For 257-step potentiometers, D8 is used to have the full resistance scale. Otherwise, it should be 0. We keep ours as 00.

So the final register value is 00000000, which we can abbreviate as 0x00.

This is the address for the wiper terminals of both digital potentiometers. So the same address is used to reference both wiper terminals on each of the potentiometers.

The chip select pin of the first digital potentiometer is connected to digital pin 10 on the arduino, so we initalize the CS1 variable to 10. The chip select pin of the second digital potentiometer is connected to digital pin 9 on the arduino, so we initalize the CS2 variable to 9.

In the setup() function, we set CS1 and CS2 as output. We then call the SPI.begin() function, which creates all the proper initialization so that the SPI can get up and running.

In our loop() function, we call a for loop that goes from 0 to 128, corresponding to the number of steps in a complete revolution of the potentiometer. We call the digitalPotWriteRed() function in this for loop to pass the i value to the wiper terminal. The first for loop counts from 0 to 128. So during this sequence, the red LED is fully on at its brightest level at first and then gets dimmer and dimmer until it shuts off completely. The second for loop counts from 128 down to 0. So the red LED during this sequence goes from being off to getting brighter and brighter till it's at its brightest level. In between these 2 sequences is a half a second delay. You can adjust this if you want.

Then we wait a second.

We then do the same sequence but only this time for the green LED. It is at its brightest level initially and then dims and dims until it is off. It then turns back on dimly and then gets brighter and brighter.

The digitalPotWriteRed() and digitalPotWriteGreen() functions are the last block of code. In these functions, we select the digital potentiometer chip by drawing the CS pin LOW. This is how we select each device, first the chip attached to the red LED and then next the chip attached to the green LED. After this, we call the address that we want to write to. Above, we initialized the address variable to 0x00; this selects the wiper terminal of the potentiometer which we will write to. We then transfer the value which is taken from the i in the for loop to the wiper terminal. This changes its resistance. Lastly, we draw the CS pin HIGH, ending the communication with the chips in each function. Whenever we write to a slave device, we draw the CS LOW. Afterwards, when we're finished with the function, we draw the CS HIGH, to unselect it.


Related Resources

How to Connect an I2C Device to an Arduino Microcontroller

How to Connect Multiple I2C Devices to an Arduino Microcontroller

HTML Comment Box is loading comments...