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
// 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
Code: Select all
#!/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