Raspberry Pi and Arduino communications using SPI with Python and CPP

preview_player
Показать описание
In an earlier I showed how you can control an Arduino from a Raspberry Pi using USB serial communications (UART). In this I show an alternative way to communicate between a Raspberry Pi and an Arduino by using the SPI (Serial Peripheral Interface) protocol.

The advantage of SPI is that you can control multiple devices through one SPI bus. It can also be faster. It is however a little more complicated to understand and code and I've not properly used the full-duplex feature in my example code.

For more details and to download the source code see:

The SPI ports on the Raspberry Pi are 3.3V only. They can be damaged by if a slave device raises a bus to 5V. If connecting to a 5V device then a level shifter should be used. Based on all models of the Raspberry Pi with 40pins, the pins for SPI0 are (physical pins):
MOSI - pin 19
MISO - pin 21
SCLK - pin 23
CE0 - pin 24
CE1 - pin 26
Ground - pin 25

Different models of the Arduino have different capabilities and ports for SPI. The newer MKR series run at 3.3V, but the more common UNO runs at 5V. I tested this using a Freeduino UNO which has the advantage of being able to switch between 3.3V and 5V, but otherwise similar to the official Arduino. It did have the advantage of allowing me to test the connection was working using 3.3V prior to adding the level shifter.

The ports on the Arduino UNO that are used are:
MOSI - pin 11
MISO - pin 12
SCLK - pin 13
SS / CE - pin 10 (optional)

Due to the voltage difference I suggest that you use a logic level convertor (sometimes called a level-shifter or voltage shifter) between the Raspberry Pi and Arduino. The model I used is the "4-channel I2C-safe Bi-directional Logic Level Converter - BSS138". This is designed for I2C, but also works well with SPI up to 2Mhz.

For test purposes I have connected digital outputs 3 to 9 to LEDs and resistors to ground. I used a bar graph LED and resistor array for convenience, but did not use all the LEDs on the bar graph. I used digital pin 2 to test an input (moving between +5V and Gnd) and I also added a variable resistor so that I could measure an analog voltage on analog input A0. This is shown in the diagram below (for convenience this is turned 90 degrees compared with the earlier diagram).

This allows the code to demonstrate two way communication, with the Raspberry Pi asking the Arduino to set digital outputs on or off and request the Arduino provide information about digital and analog inputs. The Arduino sends the relevant information back to the Raspberry Pi. This provides something that can be used as a standalone system, although it's really just a small demonstration of what you can do.

Chapters:
00:00 Introduction to video
00:39 Introduction to SPI
02:37 The difference between UART / USB serial and SPI
05:48 Communicating with multiple devices by SPI
06:10 Handling voltage difference between Raspberry Pi and Arduino
07:24 Test setup
07:58 Creating my own protocol for sending data with bitmasks
09:32 Arduino code in C++
10:58 Raspberry Pi code using Python
12:34 Summary and demo
Рекомендации по теме
Комментарии
Автор

This is the only time I've seen this done with python on yt. Thanks 👍

JimMaz
Автор

The good thing is that even the small Attiny85 and Attiny841 SPI hardware have built in.
With UART Serial it only works in software, or I2C half hardware and software.

The big Mega328 also have SPI, UART Serial and I2C all in hardware.

jensschroder
Автор

Nice presentation and clear coverage. I tried to use 2 RPI (instead of RPI and Uno) connected to communicated via SPI using python but does not seem to work. Any suggestion or a script that you can point me to?

ramizballou
Автор

Hi thank you for the explanation! I have one question. Is it possible to control 22+ servos over spi from raspberry pi4b 8gb? Sending servo commands through spi and receiving their positions and sensor data. From the slave stm32 (in my case)

I want to make a humanoid robot but I think the data transmition and receiving end of it need to be decent precice for it to work.

Any thoughts?

DeadManRising
Автор

Thanks for this awesome tutorial. What is the maximum distance over which SPI can communicate? Also, please let us know if you are are coming up with SPI Communication between Raspberry PI & Pi Pico.

RajeshJaswalPune
Автор

Wow, Raspberry Pi is soo great... r

Remind me again, what's the current draw of a Raspberry Pi on startup? (It's 5 Amps).

And is Raspberry Pi deterministic and safety critical? (It isn't).

Can you do ADC operations with a Raspberry Pi? (No)

Can you easily use bare metal programming on a Raspberry Pi? Debatable, but most people who use it probably have no idea how.

There is a very good reason microcontrollers exist in the world of microprocessors, just like the invention of nail guns and rocket and jackhammers didn't make hammers obsolete.
MCUs are simpler to program on a hardware level, the architecture is easier to understand, which is essential for real time operations; they can typically control more peripherals, do so with a lower response time, and as I said, in a deterministic manner. Traditional operating systems are fast enough for the human eye, but if you're running several cascade control loops with various sensors, and the time constant of each inner loop needs to be 10 times faster than the outer one, you VERY quickly go from micoseconds to miliseconds, to ten miliseconds, to 100 miliseconds... and that's 10 fps, for people out there.

Sure, you're not going to build a spacecraft with Arduino Uno, which is why actual embedded MCUs are much more powerful, but for simple prototyping Arduino probably the least painful way to go.

horvathbenedek
Автор

If i want use 5 arduinos as slaves?? I can use spi_device 0 and 1 for two of them. what can I use for the other 3 arduinos?? Eagerly waiting for your reply...

Asifu
Автор

I was wondering if spidev supports 16-bit SPI transfers. I'm using a PI 4B, and the processor is indeed capable of being programmed to use a 16-bit word length. So I was just wondering if the Python library spidev supported this. Thanks.

tzampini
Автор

Why I always get the wrong result of the data send by Arduino. When I send 0*80 to arduino, it will always return 255 or something else

陈天逸-vy
Автор

I fail to see what slavery has to with an SPI tutorial... But I guess I'm not political correct... And another thing, serial communication over UART is full duplex as well, unless you use a hardware layer like EIA-485(Also known as RS485) then the hardware limits you to half duplex at the advantage of higher distance. It just depends on your implementation...

arjanvuik
Автор

Why do I get the impression the guy in the video did not do this stuff, but is reading from a script a real engineer prepared.

TurboElectricLtd