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: 12924
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY