SPI Communications Issues

I use Arduino Uno to acquire data using it's I/O. I need to communicate this data to a raspberry pi for other processing and connection to the internet. I've got an arduino sketch that uses SPI to communicate a floating point number to the pi using SPI. I have two issues.

  1. If I leave out the Serial.begin(9600); line in the attached program, the pi side gets occasional errors. Why is it needed?
  2. How do I change the value of f in the union (that is transferred over to the pi as four characters - c) without the union being clobbered by the SPI interrupt in the process?

Preformatted text
#include <SPI.h>

union Data {
unsigned char buff[4];
float f=PI;
} data;

void setup() {
/* If Serial.begin is not invoked, then the SPI communications

  • will give errors on the Master Side
    */
    Serial.begin(9600);
    SPI.setDataMode(SPI_MODE0);

// Send on master in, slave out
pinMode(MISO, OUTPUT);
// Turn on SPI in slave mode
SPCR |= _BV(SPE);
// Attach an interrupts
SPI.attachInterrupt();
}

// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;
SPDR=data.buff[c];
} // end of interrupt service routine (ISR) for SPI

void loop (){}
Preformatted text

Thanks.

what are the errors?
how much data/second are you transmiiting?
why not use the pi to acquire the original data and the UNO is then no longer required

Errors are that all four bytes of the float are not transferred cleanly (one or more are bad) so the pi doesn't read the float properly.
I've tried to slow down to one float (4 bytes every 100msec).
The problem appears to be that if I change the floating value f outside the interrupt, the interrupt may be in the process of sending the four bytes of the float and clobber some bytes.

I've been using pi's to acquire data for a long time and just started using the Arduino because I need the A/D's of the UNO.

I've used serial communication to transfer between Arduino and
Pi. This works fine but I'd like to have the serial port free for loading the UNO.

While ssh'd into the pi, I've used arduino-cli on the pi to upload new sketches to the UNO, but this has issues. The arduino-cli does not give any feedback during upload to confirm that the upload is successful.

I tend to use TTL serial between Arduinos and PI (using a voltage divider on the UNO Tx to pi Rx) as the simplest way to transfer data
why not use a raspberry-pi-adc-hat to acquire the analogue data?

Thanks, Yeah that will work.

It still leaves the fundamental question: How do I change the float value that is processed by the interrupt without the value being clobbered by the SPI interrupt?

Here's some actual data. The Pi is set to read SPI from Uno every 100msec and the Uno changes the value of f that it returns every 100ms.

After 50 seconds (500 SPI transfers) there were 5 clobbered readings. So for this very limited test, a ~1% probability that the interrupt will be processing the four bytes while the loop just changed the floating value. Unacceptable.

I need to a way to disable the interrupt, after it has successfully transferred the four bytes, while I change the floating point value. Semaphores.

Problem solved. There was an error, on the pi side, in reading the bytes. Sent 3million floats from the Uno to Pi with zero errors!

Now I can transfer all the data I need from the Uno to the Pi over SPI at about 1Khz! :grin:

So now I use Arduino (and the Pi) to acquire data, combine them on the Pi and store, analyze, email, etc.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.