SPI Command and Response - Out of Sync

I am using a simplified version of Nick Gammon's SPI Tutorial. Specifically, I am using code from the section "How to get a response from a slave".

In this section, the SPI Master sends a number to the SPI Slave which adds a number to it and returns it to the Master. Ultimately what I'd like to do is use the slave to return a sensor reading back to the master.

For the sensor in my project, I'm using the Adafruit SHT31 sensor with the Adafruit SHT31 library. When I try each component of my slave code separately - the SPI Master/Slave communication and the sensor reading, they work okay. However, when I try to run both sections of the code together, the Master/Slave communication occasionally gets "out of sync".

In my code example, without the sensor code running, if the Master sends a "5", the Slave adds "2" and returns a "7". However, if I include the " tempSensor(); " function call, the Slave occasionally returns not the "7", but the same number the Master sent to the Slave, in my example, it returns a "5". Somehow, running the sensor part of the code causes the SPI communications to get out of sync.

My code example below shows a section of the Slave code

Thanks for any suggestions

void loop (void)
{
//-------------Get Temperature-----------
    tempSensor();         //Call function to measure temperature
    
    if (process_it) //if byte has arrived from MASTER
      {

      Serial.println(inByte, DEC);
      SPDR = inByte +2; //add 2 to byte from MASTER & put it in SLAVE Data Register
                        // to be read by MASTER at next SPI.Transfer from MASTER
      process_it = false;
      }
}  // end of loop

//--------------------------------FUNCTIONS----------------------------
// SPI interrupt routine
ISR (SPI_STC_vect)
{
  inByte = SPDR;  // read byte received from Master in Slave SPI Data Register (SPDR)

   process_it = true;
}  // end of interrupt service routine (ISR) SPI_STC_vect

//------------Read Temperature and Humdity Sensor--------------------

  void tempSensor()
  {
      float t = sht31.readTemperature();

      if (! isnan(t)) {  // check if 'is not a number'
        Serial.print("Temp *C = "); Serial.println(t);
      } else { 
        Serial.println("Failed to read temperature");
      }
    Serial.println();
    delay(1000);
  }

Not sure what could be the actual cause but I suspect if could be because of the delay used in the tempSensor function.
Try commenting that out as well as the Serial.Print lines and see if that fixes the problem.

The way your code is written there could be several calls to the slave while it is delay()ed and each of them will return the unchanged value.

Have a look at how millis() is used to manage timing without blocking in Several things at a time

And, for the future, please post a complete program.

...R

Thanks for the responses.

I removed the delay(1000); from the void tempSensor() function and the errors returned by the Slave to the Master stopped. When I adjust that delay from 0 upwards, the errors start roughly between 500 and 1000 milliseconds.

I also attempted to measure the time it takes sht31.readTemperature() to read and return the temperature and this seems to be about 500 milliseconds. This would appear to be on the edge of when Slave return errors begin.

Is there a better why to configure my sensor code on the Slave without interfering with the Master/Slave SPI timing?

use "millis()" in place of delay as suggested by Robin2.

so maybe something like this in your code:

unsigned long oldtime=0; //global variable

void loop (void)
{
//-------------Get Temperature-----------
    if(millis()-oldtime>500){ //call function every 500ms
	oldtime=millis();       //update oldtime
	tempSensor();         //Call function to measure temperature
    }
    
    if (process_it) //if byte has arrived from MASTER
      {

      Serial.println(inByte, DEC);
      SPDR = inByte +2; //add 2 to byte from MASTER & put it in SLAVE Data Register
                        // to be read by MASTER at next SPI.Transfer from MASTER
      process_it = false;
      }
}  // end of loop

//--------------------------------FUNCTIONS----------------------------
// SPI interrupt routine
ISR (SPI_STC_vect)
{
  inByte = SPDR;  // read byte received from Master in Slave SPI Data Register (SPDR)

   process_it = true;
}  // end of interrupt service routine (ISR) SPI_STC_vect

//------------Read Temperature and Humdity Sensor--------------------

  void tempSensor()
  {
      float t = sht31.readTemperature();

      if (! isnan(t)) {  // check if 'is not a number'
        Serial.print("Temp *C = "); Serial.println(t);
      } else {
        Serial.println("Failed to read temperature");
      }
    Serial.println();
  }