Table des matières

Communication entre Raspberry Pi et Arduino en SPI

Une ESP32 n'est pas une carte Arduino

Les sketchs ci-dessous ne fonctionnent pas avec une ESP32

Exemple 1

https://roboticsbackend.com/raspberry-pi-master-arduino-uno-slave-spi-communication-with-wiringpi/

Raspberry Pi (master) Arduino Uno (slave) SPI communication with WiringPi

#include <SPI.h>
void setup() {
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // turn on interrupts
  SPI.attachInterrupt();
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;
  SPDR = c+10;
}  // end of interrupt service routine (ISR) for SPI
 
void loop () { }

Raspberry Pi avec wiringPi

#include <iostream>
#include <wiringPiSPI.h>
#define SPI_CHANNEL 0
#define SPI_CLOCK_SPEED 1000000
int main(int argc, char **argv)
{
    int fd = wiringPiSPISetupMode(SPI_CHANNEL, SPI_CLOCK_SPEED, 0);
    if (fd == -1) {
        std::cout << "Failed to init SPI communication.\n";
        return -1;
    }
    std::cout << "SPI communication successfully setup.\n";
   
    unsigned char buf[2] = { 23, 0 };
    wiringPiSPIDataRW(SPI_CHANNEL, buf, 2);
    std::cout << "Data returned: " << +buf[1] << "\n"; 
    return 0;
}

Voir le lien pour la compilation de wiringPi et de ce script

Exemple 2

Tiré de penguintutor.com Using Raspberry Pi and Arduino together through SPI serial communications**
Arduino: SPCR et SPDR pas défini !

Raspberry

import spidev
import time
spi_bus = 0
spi_device = 0
spi = spidev.SpiDev()
spi.open(spi_bus, spi_device)
spi.max_speed_hz = 1000000
# Send a null byte to check for value
send_byte = 0x80
rcv_byte = spi.xfer2([send_byte])
# repeat to check for a response
rcv_byte = spi.xfer2([send_byte])
data_recv = rcv_byte[0]
if (data_recv != 0x80):
    print ("Unable to communicate with Arduino "+str(data_recv))
    quit()
# Data is sent as single bytearray
# lower 4 bits = pin number
# returns a value that is used to set a digital pin
# pin = Arduino pin number
# state = True for high, False for low
# returns byte or 0xff = invalid
def req_set_digital (pin, state):
    if (pin < 0 or pin > 10):
        return 0xff
    if (state == True):
        pin += 0x60
    else :
        pin += 0x20
    return pin
# read analog pin
def req_read_analog (pin):
    if (pin < 0 or pin > 5):
        return 0xff
    return pin + 0x10
# read digital pin
def req_read_digital (pin):
    if (pin < 0 or pin > 10):
        return 0xff
    return pin
while True:
    # Turn LEDs on
    for i in range (3, 10) :
        send_byte = req_set_digital (i, True)
        rcv_byte = spi.xfer2([send_byte])
        time.sleep (0.5)
    # Turn back off again
    for i in range (3, 10) :
        send_byte = req_set_digital (i, False)
        rcv_byte = spi.xfer2([send_byte])
        time.sleep (0.5)
    # Get status of pin 2
    send_byte = req_read_digital(2)
    rcv_byte = spi.xfer2([send_byte])
    # Delay to allow Arduino to get answer ready
    time.sleep (0.25)
    # Send null request
    send_byte = 0xf0
    rcv_byte = spi.xfer2([send_byte])
    print ("Value of digital pin 2 is "+str(rcv_byte[0]))
 
    # Get status of analog 0
    send_byte = req_read_analog(0)
    rcv_byte = spi.xfer2([send_byte])
    # Delay to allow Arduino to get answer ready
    time.sleep (0.25)
    # Send null request
    send_byte = 0xf0
    rcv_byte = spi.xfer2([send_byte])
    print ("Value of A0 is "+str(rcv_byte[0]))

Arduino

#include <SPI.h>
// track if digital pins are set as input or output (saves reading registers) 
// Pins 0 to 9 can be used, pin 10 can be used for SS (but can be used if that's not required) 
bool pin_output[11];
void setup() 
{
  // by default all pins are inputs
  for (int i=0; i<11; i++) 
  {
    pin_output[i] = false;  
  }
  // Set the Main in Secondary Out as an output
  pinMode(MISO, OUTPUT);
  // turn on SPI as a secondary
  // Set appropriate bit in SPI Control Register
  SPCR |= _BV(SPE);
}
void loop () 
{ char print_text [50];
  byte in_byte;
  // SPIF indicates transmission complete (byte received)
  if ((SPSR & (1 << SPIF)) != 0)
  {
    in_byte = SPDR;
    // if no action bit sent then return same 
    if (in_byte & 0x80) SPDR = in_byte;
    // if write set
    else if (in_byte & 0x20) 
    {
      // set digital pin output - use mask to extract pin and output
      if (set_digital_pin (in_byte & 0x0F, in_byte & 0x40) != 0xFF) SPDR = in_byte;
    }    
    // If value is only pin numbers then digital read
    else if (in_byte < 0x10) 
    {
      byte return_val = read_digital_pin (in_byte);
      SPDR = return_val;
    }
    else if ((in_byte & 0x10) && !(in_byte & 0x20))
    {
      byte return_val = read_analog_pin (in_byte & 0x0F);
      SPDR = return_val;
    }
    else // Otherwise an error - return 0xff
    {
      SPDR = 0xFF;
    }}}
 
byte set_digital_pin (byte address, bool high_value) 
{
  if (address < 0 || address > 10) return 0xFF;
  // Is it currently set as output - if not then set to output
  if (!pin_output[address]) 
  {
    pinMode(address, OUTPUT);
    pin_output[address] = true;
  }
  // set to low if 0, otherwise 1
  if (high_value == 0) digitalWrite(address, LOW);
  else digitalWrite (address, HIGH);
}
 
// Returns 1 for high and 0 for low
// If invalid then returns 0xff
byte read_digital_pin (byte address)
{
  if (address < 0 || address > 10) return 0xFF;
  // if currently output then change to input
  if (pin_output[address]) 
  {
    pinMode(address, INPUT);
    pin_output[address] = false;
  }
  return digitalRead (address);
}
// As full byte is used for value there is no invalid value
// If invalid then returns 0x00
byte read_analog_pin (byte address)
{
  if (address < 0 || address > 5) return 0x00;
  int analog_val = analogRead (address);
  // Analog value is between 0 and 1024 - div by 4 for byte
  return (analog_val / 4);
}