delay accurate timestamp

Hello,

I am preparing to log sensor data for a science project but have noticed that the delay for the void loop is off by a factor of about 30 minutes after 4 days taking a reading every 4 seconds using an arduino Uno.

I manually calculated the time using a column in excel next to my data. I have included the code to a test below where I log temperature. My end goal is to log a sound sensor data with less than a second delay over a period of days and record to an SD card with a time stamp.

I am writing to a standard SD card reader and I understand it might take time to write to file slowing it down?

Please keep in mind this is one of my first arduino projects so I am still a beginner at understanding.
I apologize if there is already a topic on this, please direct me to it.
Thank You

//Logger
#include <SD.h> //Load SD card library
#include<SPI.h> //Load SPI Library
int chipSelect = 4; //chipSelect pin for the SD card Reader
File mySensorData; //Data object you will write your sesnor data to
// end logger

//TMP36 Pin Variables
int temperaturePin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
                        //the resolution is 10 mV / degree centigrade 
                        //(500 mV offset) to make negative temperatures an option

/*
 * setup() - this function runs once when you turn your Arduino on
 * We initialize the serial connection with the computer
 */
void setup()
{
  Serial.begin(115200);  //Start the serial connection with the copmuter
                       //to view the result open the serial monitor 
                       //last button beneath the file bar (looks like a box with an antenae)
//logger
pinMode(10, OUTPUT); //Must declare 10 an output and reserve it
SD.begin(4); //Initialize the SD card reader
// end logger
}
 
void loop()                     // run over and over again
{
 float temperature = getVoltage(temperaturePin);  //getting the voltage reading from the temperature sensor
 temperature = ((temperature - .5) * 100*1.8)+32;          //converting from 10 mv per degree wit 500 mV offset
                                                  //to degrees ((volatge - 500mV) times 100)
 Serial.print(temperature);                     //printing the result
 Serial.println(" F");
 delay(4000);                                     //waiting a second
//logger
mySensorData = SD.open("t091516.txt", FILE_WRITE);
mySensorData.print(temperature);            //write temperature data to card
mySensorData.println(",");                    //write a commma
mySensorData.close();                       //close the file
// end logger
}

/*
 * getVoltage() - returns the voltage on the analog input defined by
 * pin
 */
float getVoltage(int pin){
 return (analogRead(pin) * .004882814); //converting from a 0 to 1023 digital range
                                        // to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}

You are correct that the program execution time will extend the 4 seconds to some longer time. You are not actually taking data every 4 seconds, but 4 seconds plus "a bit".

So, if you start at noon on day one and were expecting 15 writes/minute and 900/hour you would not have 900 x 96 records when you check the card at noon after four days days.

You can actually measure the extra loop delay, by placing a startTime=micros()at the start of loop and an endTime=micros() at the end of the loop and calculate the actual loop time.

You have two issues. One is the program execution time added to the delay, and the second is that the Arduino is not a very accurate time keeper.

Programatically, the way to handle accruing errors due to loop time is to not use delay, but to trigger the temperature readings with a millis() timer. Look at the "blink without delay" example in the IDE and the "Demonstration code for several things at the same time".

Your best approach is to use a Real Time Clock (RTC) module like the DS3231. It will keep very accurate time, and you can use its clock to trigger your data collection and keep accurate time..

Thanks for the information. Would the DS3231 be used in conjunction with the millis()timer function or two different solutions?

I use the DS3231 often and get +-7 seconds in a 3 month period.

soundchamber: Thanks for the information. Would the DS3231 be used in conjunction with the millis()timer function or two different solutions?

The DS3231 would be your absolute time, the mills() timer would become your relative time.

Read the absolute time, record the current millis():

dateTime referenceTime = // DS3231 time

int32_t absoluteTimeOffset = // adjustment to millis() such that

// actualTime = millis() + absoluteTimeOffset + referenceTime;

Your code would need to update reference time, recalculate absoluteTimeOffset on a periodic basis.

Chuck.

tThey are two different solutions.

Here’s a millis() timer added to your code and the delay removed. Unfortunately you’ll have to run it for 4 days to see how many records/hour you get :slight_smile:

You can combine the two techniques, and use the millis() timer to trigger the actions, and the RTC to give a time stamp for real time.

With a sample interval of 4 seconds, do you really have a requirement for exactly 900 readings/hour spaced exactly 4 seconds apart?

EDIT

My end goal is to log a sound sensor data with less than a second delay over a period of days and record to an SD card with a time stamp.

I did not see this. You will definitely need the RTC for the time stamp. The RTC will also have a very accurate 1Hz output signal, and you could use this to trigger your readings. If you need faster readings and SD logging, come back with your requirements. Where you go with this will depend on what you need for your project, and what ability you have to deal with increasingly complex code.

//Logger
#include <SD.h> //Load SD card library
#include<SPI.h> //Load SPI Library
int chipSelect = 4; //chipSelect pin for the SD card Reader
File mySensorData; //Data object you will write your sesnor data to
// end logger

//TMP36 Pin Variables
int temperaturePin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
//the resolution is 10 mV / degree centigrade
//(500 mV offset) to make negative temperatures an option

//Timing Variables
unsigned long lastReading;
unsigned long interval = 4000;

/*
   setup() - this function runs once when you turn your Arduino on
   We initialize the serial connection with the computer
*/
void setup()
{
  Serial.begin(115200);  //Start the serial connection with the copmuter
  //to view the result open the serial monitor
  //last button beneath the file bar (looks like a box with an antenae)
  //logger
  pinMode(10, OUTPUT); //Must declare 10 an output and reserve it
  SD.begin(4); //Initialize the SD card reader
  // end logger
}

void loop()                     // run over and over again
{
  if (millis() - lastReading >= interval)
  {
    lastReading += interval;

    float temperature = getVoltage(temperaturePin);  //getting the voltage reading from the temperature sensor
    temperature = ((temperature - .5) * 100 * 1.8) + 32;      //converting from 10 mv per degree wit 500 mV offset
    //to degrees ((volatge - 500mV) times 100)
    Serial.print(temperature);                     //printing the result
    Serial.println(" F");
    // delay(4000);                                     //waiting a second
    //logger
    mySensorData = SD.open("t091516.txt", FILE_WRITE);
    mySensorData.print(temperature);            //write temperature data to card
    mySensorData.println(",");                    //write a commma
    mySensorData.close();                       //close the file
    // end logger
  }
}

/*
   getVoltage() - returns the voltage on the analog input defined by
   pin
*/
float getVoltage(int pin) {
  return (analogRead(pin) * .004882814); //converting from a 0 to 1023 digital range
  // to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}

This is good information. Thank you everyone. I need to spend some time learning and figuring out what has been said so far.

I have no need for exactly 4 seconds. It was arbitrary for my test logging the temperature of my house.

I will however want a delay aka interval in the under 1 second range when I get to logging sound pressure readings because I want to capture short bursts of sound that happen over longer periods of time. The dream at this point is to log sound level with time stamp. I'd be comfortable with -+ a few seconds each 24 hours so it's possible that using that micros and adjusting for the time delay could work in the short term.

I know sound is going to be much more challenging than temperature thermistor or a photocell so that's why I am starting with those first.

I never would have expected that adding a time stamp would be this complicated.

I had been wondering. Will changing my power supply voltage possibly change the delay if someone was not using the DS3231?

Will changing my power supply voltage possibly change the delay if someone was not using the DS3231?

The speed of the processor should not change with the voltage supply. Which Arduino are you using? How do you plan to power it?

You need to be careful with the use of the word "delay". It has specific meaning as a code function-- delay().

I think you talking about the loop speed, and the time spent reading data, processing it, logging it, printing it, etc.

High speed data logging is a great place to learn.