I've got an I2C pressure sensor working with an Arduino Mega 2560 R3.
I'm aiming for a 20Hz sampling rate, that's constant for 15 hours straight. Hence I have a loop that requests a reading from the sensor every 50,000 microseconds:
if ((micros() - lastWrite) > 50000) {
takeReading()
lastWrite +- 50000
}
The result is the image uploaded. X-axis is seconds, and y-axis is number of samples. So each dot shows how many samples were recorded (on an SD card) each second, in the ~100 second experiment.
Does anyone know why I'm getting such a sampling frequency pattern?
There are many ways to get things wrong.
First off why use microseconds? Especially when you want to delay for milliseconds. It is not more accurate and it rolls over very much quicker.
Fixed!! I tried 10 Hz and the same pattern showed up. As I was about to post the code, I realised that instead of lastWrite += 50000, I had lastWrite +- 50000!
After correcting that, this is what I got.
I would set a hardware timer for 50 ms. Have an interrupt set a flag each time the timer rolls over. Then the main loop will see the flag, take a reading then reset the flag.
Wrap round is when a counter holds a number so big that all the bits in the number are at a logic one. If you then add one to that number then the number wraps round and becomes zero.
For milliseconds this happens every 40 days or so but for microseconds this happens after approximately 70 minutes.
Your technique for coping with this is fine but all variables used must be the unsigned long type.
In this code
The constant 50000 is not in this form. You could put this into an unsigned long variable or force the compiler to treat it as one by using 50000UL.
By using milliseconds you would not fall into this trap.
Every .flush() adds to the time required to collect data, and increases the overall error rate of the already miserable performance of the Arduino SD library.
If the Arduino is powered down without closing, the only data you lose (in the absence of other failures) is the last, unwritten 512 byte buffer.
Ok, so if I don't have a myFile.close(); statement, I can expect to lose, on average, ~256 bytes of data?
In this case that would be 128 pressure sensor values, or ~6 seconds worth of data at 20Hz, which would be absolutely fine.
I just ran the script for ~140 seconds with myFile being opened once in setup, and no myFile.close(); in loop. After unplugging the Arduino, and checking the SD card, I saw that no data had been written. Do you know what could be going on?
I currently have no other way (e.g. a button) triggering the myFile.close(); statement.