0

Data Logger Shield - Code Walkthrough - Delay() question
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Data Logger Shield - Code Walkthrough - Delay() question

by SteveInCalif on Tue Jan 15, 2019 12:02 am

Your Code Walkthrough on the Data Logger Shield is very clear and helpful. Thanks for including that! I'm buying the shield tonight with some other parts.

I am stumped by the calculation for delay; could you explain this? Why not just use a fixed delay as defined in LOG_INTERVAL?

#define LOG_INTERVAL 1000 // mills between entries

In the "Timestamping" section:
// delay for the amount of time we want between readings
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); // <-- What is being calculated here?

The "delay" formula
I ran this formula independently with fixed delay and got these results:

Code: Select all | TOGGLE FULL SIZE
#define LOG_INTERVAL  1000 // millis between entries

unsigned long timeNow;

void setup() {
  Serial.begin(9600);
}

void loop() {
    float delayTime;

    timeNow = millis();
    Serial.print(timeNow);
    Serial.print("\t");
    Serial.print(timeNow % LOG_INTERVAL);
    Serial.print("\t");
    Serial.println((LOG_INTERVAL -1) - (timeNow % LOG_INTERVAL));

    delay(500);
}


Col 1 = millis
Col 2 = millis % LOG_Interval
Col 3 = (LOG_INTERVAL -1) - (timeNow % LOG_INTERVAL)
1439978 978 21
1440479 479 520
1440979 979 20
1441480 480 519

The values are being correctly calculated. I then ran using the variable delay per your provided code and got these results:

Code: Select all | TOGGLE FULL SIZE
#define LOG_INTERVAL  1000 // millis between entries

unsigned long timeNow;

void setup() {
  Serial.begin(9600);
}

void loop() {
    float delayTime;

    timeNow = millis();
    Serial.print(timeNow);
    Serial.print("\t");
    Serial.print(timeNow % LOG_INTERVAL);
    Serial.print("\t");
    Serial.println((LOG_INTERVAL -1) - (timeNow % LOG_INTERVAL));

    delay((LOG_INTERVAL -1) - (timeNow % LOG_INTERVAL));
}


Col 1 = millis
Col 2 = millis % LOG_Interval
Col 3 = (LOG_INTERVAL -1) - (timeNow % LOG_INTERVAL)
17000 0 999
17999 999 0
17999 999 0
18000 0 999
19000 0 999
19999 999 0
20000 0 999
21000 0 999
21999 999 0
22000 0 999
23000 0 999
23999 999 0

Would appreciate any insights as to your thinking about the variable Delay calc. Thanks!

SteveInCalif
 
Posts: 4
Joined: Mon Jan 14, 2019 11:37 pm

Re: Data Logger Shield - Code Walkthrough - Delay() question

by franklin97355 on Tue Jan 15, 2019 1:07 am

The formula creates a variable delay that lasts the difference between the time running since the last delay and when the next action should start. This will create an action as close to LOG_INTERVAL as possible no matter how long the code running took (in case a sensor reading took longer than expected.)

franklin97355
 
Posts: 21089
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: Data Logger Shield - Code Walkthrough - Delay() question

by SteveInCalif on Tue Jan 15, 2019 3:40 am

Thanks. So conceptually what you are doing is a bit similar to using...

if (millis() - debounceStart >= debounceDuration )

...to account for execution time? This approach assures that the next invocation will be regularly spaced after accounting for execution time.

It sounds like the approach you use in your formula is to modify the delay to try to stay as close to the desired interval as possible. Is that right?

I'm still struggling to understand how your formula works.

SteveInCalif
 
Posts: 4
Joined: Mon Jan 14, 2019 11:37 pm

Re: Data Logger Shield - Code Walkthrough - Delay() question

by adafruit_support_bill on Tue Jan 15, 2019 7:06 am

I'm still struggling to understand how your formula works.


The calculation in question:
Code: Select all | TOGGLE FULL SIZE
delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); // <-- What is being calculated here?

Take it one piece at a time - this part calculates the current time - modulo the LOG_INTERVAL. The result of this calculation will be zero at every LOG_INTERVAL.
Code: Select all | TOGGLE FULL SIZE
(millis() % LOG_INTERVAL)

The minus 1 here is because the result of the modulo ('%') operator is zero relative
Code: Select all | TOGGLE FULL SIZE
(LOG_INTERVAL -1)

And the difference between the two is how long you need to wait for the LOG_INTERVAL to come around again
Code: Select all | TOGGLE FULL SIZE
(LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)


A simpler way of achieving the same thing would be:

Code: Select all | TOGGLE FULL SIZE
while((millis() % LOG_INTERVAL) != 0) { /* do nothing */}

adafruit_support_bill
 
Posts: 74337
Joined: Sat Feb 07, 2009 10:11 am

Please be positive and constructive with your questions and comments.