Delay is NOT working on SPI slave

I have two Arduino nanos, one is a master the other a slave using SPI.

I send a byte to my slave to tell it to do something.
The slave receives the byte and calls a function something like this

void Read()
{
    //doSomething
    delay(2000);
    //doSomethingElse
}

However the delay does not work. I can put the delay at 20000 and still it will happen within a second.
Any ideas as to what is going on here?

Please post the whole sketch or a minimal verifiable sketch that exhibits the problem.

Not without seeing your slave sketch. It depends on how you have it implemented.

#include<SPI.h>

char buff[51] = "";
volatile byte pos;
volatile boolean process_it;
//=================define=================
#define VoltagePin1 A0
#define VoltagePin2 A1

#define RelayPin1 8
#define RelayPin2 A2

#define ChargeMOSFET1 5
#define ChargeMOSFET2 6

#define LoadMOSFET1 3
#define LoadMOSFET2 9
//================Vars===================
float R1 = 47000;
float R2 = 10000;
float LoadR = 6.6;

int Mos1Val = 0;
int Mos2Val = 0;
int Rel1State = 0;
int Rel2State = 0;

//================Misc===================
#define NUM_SAMPLES 80
unsigned char sample_count = 0;
long sum = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(MISO, OUTPUT);
  SPCR |= bit(SPE);
  SPCR |= bit(SPIE);
  pos = 0;
  process_it = false;

  pinMode(VoltagePin1, INPUT);
  pinMode(VoltagePin2, INPUT);
  pinMode(RelayPin1, OUTPUT);
  pinMode(RelayPin2, OUTPUT);
  pinMode(ChargeMOSFET1, OUTPUT);
  pinMode(ChargeMOSFET2, OUTPUT);
  pinMode(LoadMOSFET1, OUTPUT);
  pinMode(LoadMOSFET2, OUTPUT);
}

ISR (SPI_STC_vect)
{
  byte c = SPDR;

  if (c == 1)  
    {
     float IR = LoadTest(VoltagePin1, LoadMOSFET1);
      String vol = String(IR);
      vol.toCharArray(buff, sizeof(buff));
      active = true;
      poss = 0;
      SPDR = buff [poss++];   // send first byte
      return;
    }

if (!active)
    {
    SPDR = 0;
    return;
    }
    
    SPDR = buff [poss];
    if (buff [poss] == 0 || ++poss >= sizeof (buff))
    active = false;
    *buff = 0;
}

void loop()
{
  if (process_it)
    {
      readBuff [pos] = 0;  
      Serial.println (readBuff);
      checkCMD();
      pos = 0;
      process_it = false;
    }
}

float LoadTest(int bay, int loadMos)
{
  while(sample_count < NUM_SAMPLES)
  {
    sum += analogRead(bay);
    sample_count++;
    Serial.println(sample_count);
    delay(15);
  }
  float Voltage = (((float)sum/(float)NUM_SAMPLES * 5.015)/1024.0)/(R2/(R1+R2));
  float I = Voltage/LoadR;
  sample_count = 0;
  sum = 0;

  analogWrite(loadMos, 255);
  delay(5000);

  while(sample_count < NUM_SAMPLES)
  {
    sum += analogRead(bay);
    sample_count++;
    Serial.println(sample_count);
    delay(15);
  }
  float Vl = (((float)sum/(float)NUM_SAMPLES * 5.015)/1024.0)/(R2/(R1+R2));
  float Vi = Voltage-Vl;
  analogWrite(loadMos, 0);
  sample_count = 0;
  sum = 0;

  float IR = 0;
  if(I > 0)
  {
    IR = Vi/I;
  }
  Serial.println(IR);
  return IR;
}
untitled text 26:5: volatile boolean process_it;
untitled text 26:40:   process_it = false;
untitled text 26:81:   if (process_it)
untitled text 26:87:       process_it = false;

Please post both sketches, or smaller examples that show the problem. There is not going to be discovered a problem with delay(), normally, in regular code. More likely a logic error.

And you could take a few more words to say what all is going on and how you are doing it. And what you are doing.

We don't have all night to read your code to figure it out.

In the code you did post, I don't see process_it being set true. Is it some kind of magic variable or... did you not actually post code you are running?

You kinda have to come more than halfway for us to meet you.

a7

In the posted code, I do not see the Read function nor do I see where the Read function is called.

Also the code for the checkCMD() function is missing.

Here is a HUGE issue:

ISR (SPI_STC_vect)
{
  byte c = SPDR;

  if (c == 1)
  {
    float IR = LoadTest(VoltagePin1, LoadMOSFET1);

You are calling LoadTest() from an interrupt and it has delay() and Serial calls in it.

So the Load test() is the function that has the delays that don't work.
Could it be that calling the function during the interrup is the cause?

So the master sends the byte to initiate the the transfer, the slave receives the byte, reads voltage and runs a load test and returns the value that needs to be sent back to the master.
The transfer of data between the master and slave works fine, it's just the delays in the LoadTest() that don't seem to work

Interrupts are disabled inside of any ISR. The delay function depends on millis() and millis() depends on interrupts (as do Serial prints). So millis() can not update in an ISR so delay won't work. If you need serial prints set a flag in the ISR and, in loop(), if the flag is set do the print and clear the flag.

Any ISR should take the least time possible. Do the high priority stuff in the ISR and, like above, use a flag to signal the loop() function to do the lower priority stuff.

The common "newbie" mistake, is attempting to use an interrupt where it is clearly not needed in any way. :roll_eyes:

1 Like

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