SPI vs I2C; which is best?

I want to have the Arduino Uno monitoring a number of different digital sensors that use either I2C or SPI.

With some sensors I am stuck with whatever is available, with other sensors I am offered a choice of using I2C or SPI. The SPI technology appears to be more robust than the I2C. I2C can handle a lot of devices with only two digital pins but there is the overhead of addressing and requirements for acknowledgement plus clocking appears to be more critical. SPI requires four pins plus one additional for each sensor but there is no acknowledgement and the clocking appears to be less critical.

What does experience say? Is it easier to have a number of sensors on I2C or SPI?

Pete

My sense is that I2C is fine if the devices offer as many address options as you need. For example, some devices only allow a choice of 1 or 2 addresses. If you needed three such devices you would need a separate I2C bus. Some devices have larger selections of addresses so it depends on the device and your requirements.

It is easy to expand the output pins on the Arduino with shift registers. That makes SPI quite expandable.

If you ever need temperature sensors you might want to look into the OneWire devices. They each have a unique 64-bit address so you can hang quite a few on one data pin.

SPI is faster. I2C while appearing more robust in my experience can give you no end of trouble especially in the multi master mode. Given the choice I would go for an SPI interface over an I2C but both are good and have their place.

Thank you, John,

Every bit of advice is valuable and will be taken into consideration.

In fact I do need a number of temperature sensors. Do you have part numbers for these? I am usually dealing with Sparkfun and Digi-Key.

Thank you Mike,

Although your moniker and picture do not inspire as much confidence as John's, I will take your advice into consideration. I rather like the simplicity of SPI and am leaning in that direction.

In fact I do need a number of temperature sensors.

Are they all nearby, perhaps on the same pc board?

Don

PeteC: In fact I do need a number of temperature sensors. Do you have part numbers for these?

I'm using DS18b20 1-wire digital temperature sensors like these, although mine came from ebay and were a fraction of the price shown there.

I2C has the advantage of being address driven only, while SPI needs unique slave select per device. SPI can be a faster hardware interface. If using multiples of the same I2C part that don't have address select pins, will need an I2C multiplexer also such as: http://www.dsscircuits.com/i2c-multiplexer.html

Hi,

Info on the temperature sensors here: http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20

If I read correctly, SPI from the Master is 3 control wires (but can be 2) plus 1 Select per Slave .. sometimes, not with daisy chain config (or maybe some other ways?). Cascading shift registers is an example of daisy-chaining, as many as you connect all act as one device. LOL, the same SPI bus can have multiple independents mixed with daisy chains. Actually, SPI looks very "roll your own" capable to me.

Between multiplexing, chalieplexing and using shift-registers it doesn't require 3 pins + 1 pin per Independent Slave either. Shift registers are SPI? Then you could use one SPI device to address others.

Thank you Mike,
Although your moniker and picture do not inspire as much confidence as John’s, I will take your advice into consideration.

Just to inspire you with a bit more confidence then, note the number of posts I have made and also check out these three sections of my web site:-
http://www.thebox.myzen.co.uk/Hardware/Hexome.html

http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

http://www.thebox.myzen.co.uk/Workshop/LED_Matrix.html

Lately, I've gone over to 100% SPI whenever possible, largely because the SPI interface is so much smaller and simpler. Look at the memory the Wire library eats up. FIVE 32-byte buffers, plus 20 bytes more other random overhead.

00800273 g     O .bss 00000020 TwoWire::rxBuffer
00800293 g     O .bss 00000001 TwoWire::rxBufferIndex
00800294 g     O .bss 00000001 TwoWire::rxBufferLength
00800295 g     O .bss 00000001 TwoWire::txAddress
00800296 g     O .bss 00000020 TwoWire::txBuffer
008002b6 g     O .bss 00000001 TwoWire::txBufferIndex
008002b7 g     O .bss 00000001 TwoWire::txBufferLength
008002b8 g     O .bss 00000001 TwoWire::transmitting
008002b9 g     O .bss 0000000c Wire
008002c6 l     O .bss 00000001 twi_slarw
008002c7 l     O .bss 00000001 twi_masterBufferIndex
008002c8 l     O .bss 00000001 twi_masterBufferLength
008002c9 l     O .bss 00000020 twi_masterBuffer
008002e9 l     O .bss 00000001 twi_error
008002ea l     O .bss 00000001 twi_state
008002eb l     O .bss 00000001 twi_rxBufferIndex
008002ec l     O .bss 00000020 twi_rxBuffer
0080030c l     O .bss 00000002 twi_onSlaveReceive
0080030e l     O .bss 00000001 twi_txBufferIndex
0080030f l     O .bss 00000001 twi_txBufferLength
00800310 l     O .bss 00000002 twi_onSlaveTransmit
00800312 l     O .bss 00000020 twi_txBuffer

You didn't answer my question in reply #5. You may be wasting your time considering I2C.

Don

GoForSmoke, Yes, SPI is SCK to all devices, MOSI out to the devices (to all in paralel, or just to the end one if daisy chaining, or both in combination), MISO from the devices being read (to all in parallel, or just the end one if daisy chaining, or both in combination), and unique SS to each device.

A great example is a 8 serial in/parallel out shift registers (74HC595 as example) - you can arrange them as one long string, with SCK and SS to all, and MOSI to the end device (with its output going to the next device's input). Then need to do 8 SPI.transfers every time to re-load them any time you want a change. Or arrange them in parallel, with SCK to all, MOSI to all, and 8 unique SS lines - then you can access individual registers, and only update the you want. And, the SS lines can be created from a 9th device if you wanted with SCK, MOSI and its SS to create the 8 SS's for the other parts - so still just using 3 I/O pins, and still way faster than software driven shiftout().

I think that MISO is not free to be used as another pin once SPI.begin() is called per this from the ATMega datasheet: "When the SPI is enabled, the data direction of the MOSI, MISO, SCK, and SS pins is overridden according to Table 19-1 on page 170."

maniacbug: Lately, I've gone over to 100% SPI whenever possible, largely because the SPI interface is so much smaller and simpler. Look at the memory the Wire library eats up. FIVE 32-byte buffers, plus 20 bytes more other random overhead.

So stop using Wire for I2C... It's design is fundamentally flawed, not just in terms of memory.

I always just grab the twi.c and twi.h that's underneath Wire and use those, or write quick master-only polling code instead

oh and just go in and delete the slave buffers if you don't need them

Grumpy_Mike: Just to inspire you with a bit more confidence then, note the number of posts I have made

I usually don't pay a lot of attention to that, but have you become Brattain level member #2?

I think the trade-off is pretty clear, if you have output pins to spare SPI has many advantages over I2C. To be honest I've been pretty lucky with both the SPI and I2C projects I've played with but I suspect they haven't been real demanding as they were mostly just proof of concept sketches to prove out various modules and chips. My impression is that SPI doesn't carry/need much software overhead, as much is handled by the AVR internal hardware, so will always have a fundemental speed advantage, no?

Lefty

SPI is faster most of the time, yes

But I2C offers mechanisms such as ack/nack and clock stretching and multi-master schemes

In the end, just choose what is right for your application, it's just a trade-off between features and speed