user28362: I am working on creating sensor poller that is going to be polling multiple sensors and then, on request, provides its data to the master.
The master polls the slave (SPI) at 50hz and the slave is polling it's sensor (BNO055) (I2C) at 100hz. 
The transaction works most of the time but every once in a while it returns an overflow. 
Any ideas why this might occur?
Slave code:
/*************************************************************************
 * 
 * objeeAirlines
 * __________________
 * 
 *  Written by Julian Blanco
 *  
 *  Spi slave code written by
    Nick Gammon
    February 2011
 */


#include "Adafruit_BNO055.h"

float yawInput=0;
float yawOffset=0;
float pitchInput=0;
float rollInput=0;

int calibration=0;

volatile byte command = 0;
Adafruit_BNO055 bno = Adafruit_BNO055();

void setup (void)
{

  if(!bno.begin())while(1){};
  bno.setExtCrystalUse(true);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // turn on interrupts
  SPCR |= _BV(SPIE);
}  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
{
  union first_union{
    float f;
    byte b[4];}
  data;

  byte c = SPDR;

  data.f = yawInput;

  command = c; 

  switch (command)
  {
  // no command? then this is the command
  case 0:

    SPDR = 0;
    break;

  // incoming byte, return byte result
  case 'a':

    SPDR = data.b[0];  
    break;

  // incoming byte, return byte result
  case 'b':

    SPDR = data.b[1];  
    break;

  // incoming byte, return byte result    
  case 'c':

    SPDR = data.b[2];  
    break;

  // incoming byte, return byte result    
  case 'd':

    SPDR = data.b[3];  
    break;

  } // end of switch

}  // end of interrupt service routine (ISR) SPI_STC_vect
float tiempo=millis();
void loop (void)
{

  // if SPI not active, clear current command
  if (digitalRead (SS) == HIGH) command = 0;

    if(millis()>(tiempo+10))
    {
      tiempo=millis();
      SampleGyro(bno);
    }

}  // end of loop

void SampleGyro(Adafruit_BNO055 &gyroIMU){
    /* Display the floating  point data */
    imu::Vector<3> euler = gyroIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
    yawInput=euler.x()-yawOffset;

    if (yawInput >= 360)
    {
          yawInput -= 360;
        }
    else 
    {if (yawInput < 0)yawInput += 360;
    }
    pitchInput=euler.y();
    //rollInput=fmod((euler.z()+(360+90)), 360)-180;
    rollInput=euler.z();
    uint8_t system, gyro, accel, mag = 0;
    gyroIMU.getCalibration(&system, &gyro, &accel, &mag);
    calibration=system;
}

Master Code:
#include <SPI.h>

#define SS 10
void setup (void)
{
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);
    pinMode(SCK, OUTPUT);
    pinMode(SS, OUTPUT);



  Serial.begin (115200);
  Serial.println ();

  digitalWrite(SS, HIGH);

  SPI.begin ();


  SPI.setClockDivider(SPI_CLOCK_DIV8);
}

  byte transferAndWait (const byte what)
{
  byte a = SPI.transfer (what);
  delayMicroseconds (10);
  return a;
} 

  union first_union{
    float f;
    byte b[4];}
  data;



void loop (void)
{

  digitalWrite(SS, LOW);

  transferAndWait ('a');  

  data.b[0] = transferAndWait ('b');
  data.b[1] = transferAndWait ('c');
  data.b[2] = transferAndWait ('d');
  data.b[3] = transferAndWait (0);

  digitalWrite(SS, HIGH);





  Serial.print("data.f = ");Serial.println(data.f);


  //Serial.print("data.b[0] = ");Serial.println(data.b[0]);
  //Serial.print("data.b[1] = ");Serial.println(data.b[1]);
  //Serial.print("data.b[2] = ");Serial.println(data.b[2]);
  //Serial.print("data.b[3] = ");Serial.println(data.b[3]);

  delay(10);
}


user14167: It is likely that your SPI interrupt on the slave is firing in the middle of updating your global yawInput variable. This would cause the value to be partially updated when you send it back to the master. You might even be sending part of the old value and part of the new value back to the master. It depends on when the interrupts fire.
You need to lock your SampleGyro function somehow. The easiest way would be to disable interrupts when modifying any interrupt accessible variables (i.e. yawInput). 
Something like this should tell you if the interrupt timing is the issue:
void SampleGyro(Adafruit_BNO055 &gyroIMU){
    /* Display the floating  point data */
    imu::Vector<3> euler = gyroIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
    uint8_t system, gyro, accel, mag = 0;
    gyroIMU.getCalibration(&system, &gyro, &accel, &mag);

    // Disable interrupts while modifying the global variable
    noInterrupts()
    yawInput=euler.x()-yawOffset;
    if (yawInput >= 360) {
          yawInput -= 360;
    } else if (yawInput < 0) {
          yawInput += 360;
    }
    pitchInput=euler.y();
    //rollInput=fmod((euler.z()+(360+90)), 360)-180;
    rollInput=euler.z();
    calibration=system;
    // re-enable interrupts once your global variable
    // modification is done.
    interrupts();
}

It's also worth noting that you want to put as little code between the noInterrupts() and interrupts() calls as possible. Things like I2C and SPI and basically any other communication will likely not work inside of that block. I rearranged your SampleGyro function to put all calls to the gyro outside of the lock. This is to prevent the sensor reading from failing.

28362: <p>I am working on creating sensor poller that is going to be polling multiple sensors and then, on request, provides its data to the master.</p>

<p>The master polls the slave (SPI) at 50hz and the slave is polling it's sensor (BNO055) (I2C) at 100hz. </p>

<p>The transaction works most of the time but every once in a while it returns an overflow. </p>

<p>Any ideas why this might occur?</p>

<p>Slave code:</p>

<pre><code>/*************************************************************************
 * 
 * objeeAirlines
 * __________________
 * 
 *  Written by Julian Blanco
 *  
 *  Spi slave code written by
    Nick Gammon
    February 2011
 */


#include "Adafruit_BNO055.h"

float yawInput=0;
float yawOffset=0;
float pitchInput=0;
float rollInput=0;

int calibration=0;

volatile byte command = 0;
Adafruit_BNO055 bno = Adafruit_BNO055();

void setup (void)
{

  if(!bno.begin())while(1){};
  bno.setExtCrystalUse(true);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
  // turn on interrupts
  SPCR |= _BV(SPIE);
}  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
{
  union first_union{
    float f;
    byte b[4];}
  data;

  byte c = SPDR;

  data.f = yawInput;

  command = c; 

  switch (command)
  {
  // no command? then this is the command
  case 0:

    SPDR = 0;
    break;

  // incoming byte, return byte result
  case 'a':

    SPDR = data.b[0];  
    break;

  // incoming byte, return byte result
  case 'b':

    SPDR = data.b[1];  
    break;

  // incoming byte, return byte result    
  case 'c':

    SPDR = data.b[2];  
    break;

  // incoming byte, return byte result    
  case 'd':

    SPDR = data.b[3];  
    break;

  } // end of switch

}  // end of interrupt service routine (ISR) SPI_STC_vect
float tiempo=millis();
void loop (void)
{

  // if SPI not active, clear current command
  if (digitalRead (SS) == HIGH) command = 0;

    if(millis()&gt;(tiempo+10))
    {
      tiempo=millis();
      SampleGyro(bno);
    }

}  // end of loop

void SampleGyro(Adafruit_BNO055 &amp;gyroIMU){
    /* Display the floating  point data */
    imu::Vector&lt;3&gt; euler = gyroIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
    yawInput=euler.x()-yawOffset;

    if (yawInput &gt;= 360)
    {
          yawInput -= 360;
        }
    else 
    {if (yawInput &lt; 0)yawInput += 360;
    }
    pitchInput=euler.y();
    //rollInput=fmod((euler.z()+(360+90)), 360)-180;
    rollInput=euler.z();
    uint8_t system, gyro, accel, mag = 0;
    gyroIMU.getCalibration(&amp;system, &amp;gyro, &amp;accel, &amp;mag);
    calibration=system;
}
</code></pre>

<p>Master Code:</p>

<pre><code>#include &lt;SPI.h&gt;

#define SS 10
void setup (void)
{
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);
    pinMode(SCK, OUTPUT);
    pinMode(SS, OUTPUT);



  Serial.begin (115200);
  Serial.println ();

  digitalWrite(SS, HIGH);

  SPI.begin ();


  SPI.setClockDivider(SPI_CLOCK_DIV8);
}

  byte transferAndWait (const byte what)
{
  byte a = SPI.transfer (what);
  delayMicroseconds (10);
  return a;
} 

  union first_union{
    float f;
    byte b[4];}
  data;



void loop (void)
{

  digitalWrite(SS, LOW);

  transferAndWait ('a');  

  data.b[0] = transferAndWait ('b');
  data.b[1] = transferAndWait ('c');
  data.b[2] = transferAndWait ('d');
  data.b[3] = transferAndWait (0);

  digitalWrite(SS, HIGH);





  Serial.print("data.f = ");Serial.println(data.f);


  //Serial.print("data.b[0] = ");Serial.println(data.b[0]);
  //Serial.print("data.b[1] = ");Serial.println(data.b[1]);
  //Serial.print("data.b[2] = ");Serial.println(data.b[2]);
  //Serial.print("data.b[3] = ");Serial.println(data.b[3]);

  delay(10);
}
</code></pre>
 14167: <p>It is likely that your SPI interrupt on the slave is firing in the middle of updating your global <code>yawInput</code> variable. This would cause the value to be partially updated when you send it back to the master. You might even be sending part of the old value and part of the new value back to the master. It depends on when the interrupts fire.</p>

<p>You need to lock your <code>SampleGyro</code> function somehow. The easiest way would be to disable interrupts when modifying any interrupt accessible variables (i.e. <code>yawInput</code>). </p>

<p>Something like this should tell you if the interrupt timing is the issue:</p>

<pre><code>void SampleGyro(Adafruit_BNO055 &amp;gyroIMU){
    /* Display the floating  point data */
    imu::Vector&lt;3&gt; euler = gyroIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
    uint8_t system, gyro, accel, mag = 0;
    gyroIMU.getCalibration(&amp;system, &amp;gyro, &amp;accel, &amp;mag);

    // Disable interrupts while modifying the global variable
    noInterrupts()
    yawInput=euler.x()-yawOffset;
    if (yawInput &gt;= 360) {
          yawInput -= 360;
    } else if (yawInput &lt; 0) {
          yawInput += 360;
    }
    pitchInput=euler.y();
    //rollInput=fmod((euler.z()+(360+90)), 360)-180;
    rollInput=euler.z();
    calibration=system;
    // re-enable interrupts once your global variable
    // modification is done.
    interrupts();
}
</code></pre>

<p>It's also worth noting that you want to put as little code between the <code>noInterrupts()</code> and <code>interrupts()</code> calls as possible. Things like I2C and SPI and basically any other communication will likely not work inside of that block. I rearranged your <code>SampleGyro</code> function to put all calls to the gyro outside of the lock. This is to prevent the sensor reading from failing.</p>
