Timing Loop Anamolies

I am designing a project that needs to write acquired data to a micro SD card every 5 mS. Writing the data is not an issue, but getting it to be written consistently at 5mS is. The below code is outputting a PWM signal that I am sending to a buffer circuit to turn into an analog signal. I am also writing it to the SD card. The issue is the loop timing is consistently inconsistent (see graph below.)

void timing()
timestart = micros();
stepval = 25;
while (stepval!=155)
	datastring = "";
	datatime = micros() - timestart;
	analogWrite(aoutpin0, stepval);
	datastring +=(stepval); 
	datastring +=(", ");
	datastring +=(datatime);
	stepval ++;

The graph show deltaT in microseconds between readings and the number of readings. As you can see deltaT increases in small steps as the acquisition continues. It also spikes an increase every 40-45 samples taken. This is my issue.

I hope someone out there can help me to understand what is going on with this.



Three possibilities...

  1. The SD card library is flushing the write buffer

  2. Timer 0 interrupt service handler is firing

  3. Heap manager is recombining memory blocks

Since you didn't post the code that defines the variables, this is a guess.

datastring +=(stepval);

This suggests that "datastring" is a String object. The String object is known to be buggy ESPECIALLY related to concatenation.

You really should only be using character arrays (strings) of known length. All the dynamic junk the String object is doing is going to cause you problems, even if it is unrelated to your timing issue.

I'm not sure I even see any value in creating a variable just to print it to the sd card. Skip that step. Just print the data directly.

You’re using fixed delays, which means the timing of your loop is essentially controlled only by the execution time of the code in it. That’s not a good way to control timing.

Since you’re using dynamic memory allocation (a bad idea in any case) the execution time could vary all over the place.

Better to explicitly test whether it’s time to do the next thing.

In the current blocking design, you could do that like this:

while(micros() - lastMicros() < interval) { /* do nothing */ };
lastMicros += interval;
// do other stuff which is supposed to happen once per interval

If you design your sketch to use a non-blocking approach, you would be free to do other things in the meantime:

if(micros() - lastMicros >= interval)
    lastMicros += interval;
  // do other stuff which is supposed to happen once per interval