Memorial day is 05/25/2015 – Orders will ship out on May 26th. There will not be any deliveries or shipping on Monday. Any order placed after 11am ET on Friday May 22nd will not start to ship out until Tuesday May 26th.

Linking to Raspberry Pi with SPI
Moderators: adafruit_support_bill, adafruit

Linking to Raspberry Pi with SPI

by Alan Johnstone on Tue Apr 02, 2013 3:16 am

This has also been posted on the Raspberry Pi forum

I am trying to link my Arduino with my Raspbery PI using SPI.

I have found the following links helpful.
http://www.gammon.com.au/forum/?id=10892
http://mitchtech.net/raspberry-pi-arduino-spi/

They connect the two directly but warn that a level shifter should be used to protect the Raspberry PI from the 5v of the Arduino.

When I risk damaging the Pi and link directly everything works fine.
When I put a level shifter in the middle it stops working.

I have tried the TXB0108 and the BSS138 both from ADAFRUIT
http://www.adafruit.com/products/395
http://www.adafruit.com/products/757

I have tried to break the problem down.

Linking the two sets of 4 wires together on the breadboard works properly.
I have moved each wire one at a time so that they connect via the TXB0108. Here are the results:

Ard 10, RPi 26 function = SS Works perfectly
Ard 11, RPi 19 function = MOSI Works perfectly
Ard 12, RPi 21 function = MISO Data transferred from the RPI to the Ard is corrupted. Data transferred from the Ard to RPi seems to be good
Ard 13, RPi 23 function = SCLK it looks like no data is transferred at all which suggests the clock signal is completely distorted.

I repeated the tests with the BSS138 and got similar results although the corruption when the MISO line was connected was not so severe.

I had hoped that the MISO connection at least could be made because I believe that is the only one risking damage as it is feeding in ~5V onto the RPi pin.

Do you have any thought as to how to proceed?

The code I use in the Arduino is:
Code: Select all | TOGGLE FULL SIZE
// Written by Nick Gammon
// February 2011

// MISO pin 12
// MOSI pin 11
// CLK  pin 13
// SS   pin 10

#include <SPI.h>

char buf [100];
volatile byte pos;
volatile boolean process_it;
volatile int count=66;
void setup (void)
{
  Serial.begin (9600);   // debugging
  Serial. println("setup");

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
// pinMode(SS,    INPUT);
  //pinMode(MOSI,  INPUT);
  //pinMode(SCK,   INPUT);
 
  // get ready for an interrupt
  pos = 0;   // buffer empty
  process_it = false;
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
 
  //SPI.setClockDivider(SPI_CLOCK_DIV16);
 
  // now turn on interrupts
  SPI.attachInterrupt();
   
}  // end of setup



// main loop - wait for flag set in interrupt routine
void loop (void)
{
 
    if (process_it)
    {
      Serial.println("Saw Something");   
      //Serial.println (buf);
      for(int i=0;i<pos;i++)
      {
        Serial.print(buf[i]);
      }
  Serial.println ("");     
      pos = 0;
      process_it = false;
     }  // end of flag set
   
}  // end of loop
// SPI interrupt routine
ISR (SPI_STC_vect)
{
    //process_it = true;
    byte c = SPDR;  // grab byte from SPI Data Register
    SPDR=count;
    count++;
    // add to buffer if room
    // example: newline means time to process buffer
    if (c == '\n')
     {
       process_it = true;
     }
     else
    if (pos < sizeof buf)
      {
        buf [pos++] = c;         
      }  // end of room available
}  // end of interrupt routine SPI_STC_vect



The code in the Raspberry Pi is:

Code: Select all | TOGGLE FULL SIZE
#!/usr/bin/python2.7

# MISO pin  9
# MOSi pin 10
# CLK  pin 11
# SS   pin  7 spidev1
import spidev
from time import sleep

def sendToArduino(val):
    # val is a string and need to take each char, change to an integer and send
    result=list()
    for chr in val:
        num=ord(chr)
        temp = spi.xfer2([num])
        result.append(int(temp[0]))
        sleep(.005)
    if val[len(val)-1]!='\n':
        sleep(.005)
        temp = spi.xfer2([ord('\n')])
        returnChar=int(temp[0])
        result.append(returnChar)

    return result
# not currently used
def printListofInts(lst):
    output=""
    for c in lst:
        output += c
    print output
    print '\n'

# reload spi drivers to prevent spi failures
import subprocess
reload_spi = subprocess.Popen('sudo rmmod spi_bcm2708', shell=True, stdout=subprocess.$
start_spi = subprocess.Popen('sudo modprobe spi_bcm2708', shell=True, stdout=subproces$
sleep(3)

spi = spidev.SpiDev()
spi.open(0,1)        # The Gertboard DAC is on SPI channel 1 (CE1 - aka GPIO7)



while True:
    ans=str(raw_input("Another , CR to finish\n"))
    if len(ans)==0 :
       break;
    res=sendToArduino(ans)
    print res






Does anybody have a working example of a combination of code (preferably in Python for the Pi) and a specific level shifter that I could use?

Thank you in advance

Alan
Alan Johnstone
 
Posts: 5
Joined: Mon Apr 01, 2013 4:37 am

Re: Linking to Raspberry Pi with SPI

by Alan Johnstone on Tue Apr 02, 2013 5:02 pm

Decided to use a schottky diode on the MISO line as per

https://www.sparkfun.com/tutorials/65

I will also put the same schottky diode on the other lines just for safety (and use a pull down resistor).
I should have done this 10 days ago when I started to have problems.
Alan Johnstone
 
Posts: 5
Joined: Mon Apr 01, 2013 4:37 am

Re: Linking to Raspberry Pi with SPI

by adafruit_support_rick on Thu May 16, 2013 3:26 pm

You can also use a simple resistor divider to drop the 5V to 3.3V

adafruit_support_rick
 
Posts: 18421
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY