topamax once a day

Raspberry Pi + Arduino + SPI

This tutorial will show you how to communicate from your raspberry pi to your arduino using 3-wire SPI.

Requirements

  • 1 Raspberry pi (running Raspbian)
  • 1 Arduino
  • 4 wires

Your raspberry pi should be running the newest version of Raspbian.  To ensure your system is up-to-date please download and run rpi-update.

Wiring

 

Arduino

Open your Arduino ide and flash the below code to your Arduino.

Arduino code

Raspberry Pi

With your updated rasbian system you should have the drivers that you need. Now it’s time to load them.

modprobe spi_bcm2708
modprobe spidev

Check to be sure the modules loaded:

lsmod
Module Size Used by
spidev 5944 0
spi_bcm2708 5350 0
snd_bcm2835 21681 0
snd_pcm 81170 1 snd_bcm2835
snd_seq 59528 0
snd_timer 21602 2 snd_seq,snd_pcm
snd_seq_device 6924 1 snd_seq
snd 57427 5 snd_seq_device,snd_timer,snd_seq,snd_pcm,snd_bcm2835
snd_page_alloc 5343 1 snd_pcm
i2c_bcm2708 3822 0

Raspberry Pi Code

Save the below code as spidev_test.c on to your Raspberry Pi and compile it

gcc spidev_test.c -o spidev_test

Running

Plug your Arduino to your desktop via the serial cable. Open the arduino Serial Monitor and set the bitrate to 115200. Now, on the Raspberry Pi, run the compiled code

sudo ./spidev_test

You should see HELLO WORLD print in the Arduino IDE Serial Monitor.

Debugging

    • Make sure that your kernel has the required drivers (spi-bcm2708.ko and spidev.ko)

pi@raspberrypi ~/spi $ ls -al /lib/modules/`uname -r`/kernel/drivers/spi/
total 64
drwxrwxr-x 2 pi pi 4096 Aug 10 10:53 .
drwxrwxr-x 23 pi pi 4096 Aug 10 10:53 ..
-rw-rw-r– 1 pi pi 14428 Aug 10 10:53 spi-bcm2708.ko
-rw-rw-r– 1 pi pi 10852 Aug 10 10:53 spi-bitbang.ko
-rw-rw-r– 1 pi pi 15803 Aug 10 10:53 spidev.ko
-rw-rw-r– 1 pi pi 10693 Aug 10 10:53 spi-gpio.ko

Thanks to Nick Gammon for the SPI slave code.

Thanks to Anton Vorontsov for the kernel Documentation spidev_test.c example code.

 

  • Wow, can the 3.3V RPi tolerate the 5V TTL levels of the Arduino?

    • meyers

      Hmm from http://elinux.org/RPi_Low-level_peripherals “The pins use a 3V3 logic level and are not tolerant of 5V levels, such as you might find on a 5V powered Arduino.”.
      Let me try and find out from some friends and colleagues why this works and doesn’t blow up 🙂

      • Julian

        Accidentally put 5V on the GPIO Pins of mine and didn’t blow up either 😉

        • Lo

          Put -5V on it and it’s in the heaven now 😀

        • “Non tolerant” doesn’t mean it will blow up right away, just shorten the Pi’s life span. Use a logic level converter like http://www.adafruit.com/products/395 to supply the right voltage levels.

          • TJ

            Many N-Channel Enhancement Mode MOSFETs can also be used for level shifting, some of them costing only the loose change in your back trouser pocket.

  • It might work only because the example doesn’t send any information from the Arduino back to the Pi and thus putting 5v on the Pi input pin.

  • First of all thank you for sharing this code!

    I am new in this, and i would like to know how can the arduino send back the data received to the raspberry.

    Thanks!

    • Zaxd

      I second anjz!
      This would be much more useful

      • I third anjz!
        I’m still searching for a way to work this out. The arduino spi lib itself supports only master mode.

  • Pingback: Raspberry Piの資料リンク集 « nanoblog()

  • Maybe a bus switch from 5V to 3.3V could be useful in order to avoid harming the Raspberry Pi. Something like this: http://www.ti.com/lit/ds/symlink/sn74cbtd3384c.pdf

  • wally

    It would be interesting to learn how the spi-kernel-driver might be used to
    read an SPI ADC (e.g. ADS1100). Additionally this would be more save for the hardware, because this ADC works on 2.7 to 5.5V. Where to find more documentation and/or examples using this kernel-driver ? Thank you!

  • Pingback: The Great Raspberry Pi Post | Jason Raimondi()

  • venkatesh

    im beginner doing spi interface. i tried with above code to start learning. i connected wires as described but i got o/p “can’t able open device”. one thing which is different from above of mine is the broadcom pheripheral mine is BCM2835. is there any change in the code for my bcm. and one more thing spi may be blacklisted when i google for solution how to unlock them. and not able to find spidev under dev. how to resolve it?

    • meyers

      You can observe the blacklisting or not of the spi drivers by following the guide above. Specifically, the lsmod section. Don’t think of blacklisting a driver as locking but rather as a convenience mechanism for specifying that a driver not be loaded when the distribution starts up for one reason or another.

      After you have verified the driver is loaded ensure that the driver created the device nodes. Specifically /dev/spidev0.0

      Let me know if you have further problems.

      • venkatesh

        when i try lsmod, i cant find spidev0.0 how to load it. please guide me. for lsmod i got this

        Module Size Used by
        evdev 8682 4
        joydev 9102 0
        snd_bcm2835 12808 0
        snd_pcm 74834 1 snd_bcm2835
        snd_seq 52536 0
        snd_timer 19698 2 snd_seq,snd_pcm
        snd_seq_device 6300 1 snd_seq
        snd 52489 5 snd_seq_device,snd_timer,snd_seq,snd_pcm,snd_bcm2835
        snd_page_alloc 4951 1 snd_pcm

        • venkatesh

          now i got spi enabled

          Module Size Used by
          snd_bcm2835 12808 0
          snd_pcm 74834 1 snd_bcm2835
          snd_seq 52536 0
          snd_timer 19698 2 snd_seq,snd_pcm
          snd_seq_device 6300 1 snd_seq
          snd 52489 5 snd_seq_device,snd_timer,snd_seq,snd_pcm,snd_bcm2835
          snd_page_alloc 4951 1 snd_pcm
          spidev 5136 0
          evdev 8682 4
          joydev 9102 0
          spi_bcm2708 4401 0

          and in ls /dev/spi*

          /dev/spidev0.0 /dev/spidev0.1

          now im getting output
          “can’t open device : permission denied”

          • meyers

            Try prepending the command you are running with sudo. For example if you are running the command ‘ls’ try ‘sudo ls’.

          • venkatesh

            had u wrote code for receiving data from arduino?

        • parvathi

          how did u get spi enabled? when i am trying to install spi_bcm2708 i am getting “unable locate package spi_bcm2708″… please guide me..

  • meyers

    Arduino example spi receiver code is included in The above tutorial.

    • venkatesh

      two things i want to clarify with you. im sending command byte 0xFE from rpi after its received in arduino im sending {0xAA,0xAB,0xAC} from arduino

      1. while transmitting a buffer why its necessary to add 0x0A at the end of the buffer (arduino) when i look at serial monitor it shows 0xAA,0xAB,0xAC “0x0A” 0xAA,0xAB,0xAC if 0x0A is added it sendinding as 0xAA,0x0A,0xAB,0x0A.

      2.while receiving in rpi, each received byte in sent buffer follwed by command byte(0xFE) for 9 times. eg: if im receiving in rpi as 0xAA 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xFE 0xAB…….

      • venkatesh

        sorry in 1. if 0x0A is not added it sending as 0xAA,0x0A,0xAB,0x0A.

  • Pingback: SPI-Python: Hardware SPI for RasPi | Louis Thiery()

  • TT

    I am pretty new to pro­gram­ming. I have a device which I want to con­nect to the RPi using SPI. I tried out the spi_devtest.c and it works. But the SPI frame of the slave device requires 24 bits. I have searched high and low and have not been able to find a solu­tion. I tried chang­ing the num­ber of bits per word but that does not work. I won­der if I would have to just send 3 bytes instead of 24 bits. In that case, I don’t know how to send 3 bytes with­out the chip select going inac­tive after each word. Any help would be greatly appreciated.

    • TT

      nevermind. i figured it out. thanks anyways 🙂

      • pi-ray

        TT or anyone. I have the same issue of requiring 24 bits without raising syncb. Do tell how you “figured it out”. Wondering if I can use a different gpio bit and create and control my own sincb, but this seems ugly.

        • TT

          Sorry for taking so long to respond, I ended up just sending 3 8bit words. I don’t know if there’s any other way to do it, or if there exists a better way.

  • venkatesh

    why the byte being returned back to rpi which sent to arduino? is any voltage converter required?

  • Pingback: RaspberryPI: un po di link utili()

  • bocius

    Hey,

    I have some errors while compiling the RasPi code..

    They are:
    pi@raspberrypi ~ $ gcc spidev_test.c -o spidev_test
    spidev_test.c:234:13: error: redefinition of ‘pabort’
    spidev_test.c:26:13: note: previous definition of ‘pabort’ was here
    spidev_test.c:240:20: error: redefinition of ‘device’
    spidev_test.c:32:20: note: previous definition of ‘device’ was here
    spidev_test.c:242:16: error: redefinition of ‘bits’
    spidev_test.c:34:16: note: previous definition of ‘bits’ was here
    spidev_test.c:243:17: error: redefinition of ‘speed’
    spidev_test.c:35:17: note: previous definition of ‘speed’ was here
    spidev_test.c:246:13: error: redefinition of ‘transfer’
    spidev_test.c:38:13: note: previous definition of ‘transfer’ was here
    spidev_test.c:279:13: error: redefinition of ‘print_usage’
    spidev_test.c:71:13: note: previous definition of ‘print_usage’ was here
    spidev_test.c:295:13: error: redefinition of ‘parse_opts’
    spidev_test.c:87:13: note: previous definition of ‘parse_opts’ was here
    spidev_test.c:364:5: error: redefinition of ‘main’

    I got the /dev/spidev0.0 and spidev0.1. The RasPi is updated and everything is ok, except the “pi@raspberrypi ~/spi $ ls -al /lib/modules/`uname -r`/kernel/drivers/spi/” part, where I only get: “total 64”.

    Please, help:)

  • Hello,
    Great tuto, just may be asking a stupid question but there is no wire with CE0 ou CE1 between the Arduino and the PI, does the arduino hardware SPI work even if the Chip Enable pin is floating ?
    Thanks

  • this shows great potential for fast raspi to arduino transfers! what is the fastest this can work?

  • TT

    I get this error: spi_slave.ino: In function ‘void setup()’:
    spi_slave:24: error: ‘SPCR’ was not declared in this scope
    spi_slave:24: error: ‘SPE’ was not declared in this scope
    spi_slave:24: error: ‘_BV’ was not declared in this scope
    spi_slave.ino: In function ‘void SPI_STC_vect()’:
    spi_slave:39: error: ‘SPDR’ was not declared in this scope
    Does anyone know what could be the problem and/or know how to fix this? I’m using this code with the arduino due

  • Pingback: 手把手教你树莓派与Arduino Uno的对接(USB及GPIO方式) | 木子目詹()

  • parvathi

    when i am running this code i am getting output as “cant open device” in the raspberry pi terminal.. please help me..

  • pi

    when i am trying to run the raspberry pi code iam getting the error ‘cant open the device’. please guide me…

  • Hi, awesome job here!! I got this working nicely. I am working on a new pi project that is coded in C++ and I am having issues integrating. I’ve tried linking the the above pi C code to my C++ code but get “undefined reference” to the C function (from pi code). Can anyone help convert the above Raspberry Pi code into C++? It will be greatly appreciated! Thank You

  • JR

    Hello,
    I’m looking to do this exact some thing (use SPI between a Pi and an Arduino). But something might’ve happened to this post. The Arduino code seems to have gone missing from this post. If someone could repost this, I’d appreciate it.

  • Jmg

    How to convert hello word to the uint8_t . I’m planning to mod spidev_test to send data in argument

  • pischky

    Just have got it running on an AlaMode Board from wyolum. One note:
    Pull the SS input (Arduino Pin 10) input down to ground by some jumper.

    • Gregory

      How did you get to the conclusion? What happens if you don’t?
      Thank you

      • The transfer does not work. May be you have luck sometimes and the input is floating to ground. Better than pulling SS to ground is using one extra level shifter from Pi pins CS0 or CS1. Level shifter for other pins are includes on AlaMode Board.

  • Pingback: 10 Resources For Getting Into Arduino Or Raspberry Pi  | Maker Co | Maker Resources, Market, & More()

  • Thank you so much for being the only in depth article online!

    I’ve follow this article to the T.

    I’t works great, the SS held high triggers the Arduino’s interrupt but there is a problem with the data.

    The data is only ever 0x0, my stomach is telling me its an issue with the Pi.

    Any idea what the issue could be? Bad sync? Not transmitting data correctly?

    Also, is there any reason to use a logic level converter between these? (I have a bunch of these laying around http://www.mdfly.com/products/logic-level-converter-2-5v-3-3v-5v.html )

  • Pingback: Fix Arduino Error ‘spi’ Was Not Declared In This Scope Windows XP, Vista, 7, 8 [Solved]()

  • kevenlaker

    You may need $11.9 Arduino shield CANBUS here: http://www.elecfreaks.com/store/canbus-shield-p-746.html

  • Pingback: Trouble connecting my raspberry pi to to Arduino Mega 2650 | CL-UAT()

  • Pingback: is it possible to connect a raspberry pi to an arduino via USB and have them communicate? [duplicate] | CL-UAT()

  • Pingback: SPI example with Raspberry Pi and another MCU | CL-UAT()

  • Pingback: SPI (file based) from Rasp Pi to Arduino - DL-UAT()

  • AndiSh

    PROTECT your 3,3V I/O Pins on Raspi… at least with 5kOhms…
    (+ live coding with Mathematica/Wolfram)

    Hello,
    please, if you don’t have anything else available, at least introduce series resistors.
    This limits the current when accidentally “Out LOW” meets “Out HIGH” or Out5V meets In3.3V.
    Current on input shall not exceed 1mA. Makes 5kOhms. OK, 4,7kOhm. Works, if no real fast signals or Pull up/downs or bad EMI-noisy environments are involved.

    The bus transceiver does a 3,3V job in both directions. So the 5V device has to cope with a HIGH signal of 3.3V.
    If the switching hysteresis of the 5V device are OK with this, it is a no-delay fast bidirectional (without having to set direction, has no input for this) thingy to use, more stable than the auto-magic bidirectional true level-shifters also available, which might oszillate when wires are to long or PCB design is not really HF-reflection-proof; and to admit, my lousy breadboard without ground plane underneath, well, did not have the mony for the 3M breadboard… 😉

    (Only the cmos specs state 0,3*VCC and 0,7*VCC for LOW and HIGH. Thats not quite achieved…)
    Why not let arduino run at 3,8V ? Would mitigate things 😉 (Tip I read: best _not_ to translate, meaning not having to translate 😉

    Good luck!

    (We can not run on 5V till end of days, so I sighed and bougt a due and a raspi, no conversion problem; still this is seemingly a contradiction, both beeing 32bit bla… but I want to program Arduino from Mathematica / Wolfram.

    Then Mathworks can be the frontend for a digital/analog workbench, with full force analysis (and synthesis) at hand. http://www.wolfram.com/raspberry-pi/?source=footer
    and
    https://reference.wolfram.com/language/ref/device/Arduino.html
    where they explain how arduino is controlled via serial, but also gets a new c++ program uploaded when the changes in wolfram demand it.
    Should ask them if it could be done via debugging mode code insertion ;))
    Still don’t know if DUE is supportet. Maybe not yet.
    (Matlab/Simulink have this in their classroom licence for schools, it is part of their product named “coder”. Supporting coding for Raspi, Arduino, Lego Mindstorms EV3. It uploads code, afterwards target system runs the program, if wanted, autonomously or with communication.
    What’s missing for me is cpld and the analog programming cypress pSoC4.. offers, but with more cells, at least a few k.)

  • Fred

    May you help me?
    Have you used wiringPi?

    I am trying to establish a connection between both arduino and raspberry, but i only get garbage.

    So I have some questions:

    1) Where is the Slave Select pin?
    2) Can I turn the Arduino using only the SPI?
    3) How to I set the comunication speed on arduino?
    4) Why do I only get garbage?

    Here is my Raspberry code:

    #include // printf()
    #include // signal()
    #include // strerro
    #include

    #include // GPIO
    #include // SPI

    int volatile interrupt = 0;
    #define len_max 100
    int volatile len = 0;
    unsigned char buffer[len_max];
    static const int speed = 500000;

    int const CE0 = 0;

    void sig_handler(int signo)
    {
    if(signo == SIGINT)
    {
    interrupt = 1;
    }
    }

    void setup(void)
    {
    signal(SIGINT, sig_handler);

    wiringPiSetupGpio () ;

    if(wiringPiSPISetup(CE0, speed) < 0)
    {
    printf("SPI setup failed: %s\n", strerror(errno));
    interrupt = 1;
    }

    printf("System ready.\n");
    }

    void loop(void)
    {
    memcpy(buffer, "Hello world!\n", sizeof buffer);
    len = 12;
    if( wiringPiSPIDataRW (CE0, buffer, len) < 0)
    printf("Error while recieving mesage\n");
    printf("Received mesage: %s \n", buffer);
    delay(1000);
    }

    void close(void)
    {
    printf("Ending activities.\n");
    }

    int main(void)
    {
    setup();
    while(!interrupt) loop();
    close();
    return 0;
    }

    Please help.

  • Pingback: How to connect Raspberry Pi and Arduino with SPI? | Question and Answer()

  • Coşkun

    Guys can you give an example for python?

  • Susheel Selvamani

    how to install the mentioned drivers and modules?

  • Pingback: RaspberryPI: un po di link utili - Acor3.it()

  • Pingback: Raspberrypiarduino比較 - Raspberry Pi and Arduino - Raspberry Pi()

  • Horamberg

    Not this manga. I meant other ones haha
    Xi.DAOFI.CASH/Xc5708R

  • MEDEVAC343

    Tf happening it’s like a roller coaster
    vm.DH5WZ4E.CYOUCr5708s