Data Logger Shield - Code Walkthrough - Delay() question

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
SteveInCalif
 
Posts: 4
Joined: Mon Jan 14, 2019 11:37 pm

Data Logger Shield - Code Walkthrough - Delay() question

Post by SteveInCalif »

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

#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

#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!

User avatar
Franklin97355
 
Posts: 23912
Joined: Mon Apr 21, 2008 2:33 pm

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

Post by Franklin97355 »

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.)

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

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

Post by SteveInCalif »

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.

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

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

Post by adafruit_support_bill »

I'm still struggling to understand how your formula works.
The calculation in question:

Code: Select all

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

(millis() % LOG_INTERVAL)
The minus 1 here is because the result of the modulo ('%') operator is zero relative

Code: Select all

(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

(LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)
A simpler way of achieving the same thing would be:

Code: Select all

while((millis() % LOG_INTERVAL) != 0) { /* do nothing */}

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”