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