How to obtain and save sensor data at specific samplying rate using Adalogger with RTC + SD?

Hello, I know how to print out and save analog sensor data to a file. Would you please let me know how to do that at specific time interval in msec given a samplying frequency? For example, I want to print/save the time (every 1 msec) and the corresponding data obtained by a sensor. I know the RTC in this Adalogger only has a resolution of 1second.

unsigned long microSecondTime      = 0;
const unsigned long sampleInterval = 1000ul; //In microseconds.
. . . 
//is it time to save the data ?
if (micros() - microSecondTime >= sampleInterval )
{
  //Restart this TIMER
  microSecondTime = microSecondTime + sampleInterval;
  
  //Save our time and data.
}

Thanks. I am a bit confused. Why microseconds function is used when I want to get the data every 1 millisecond? I know 1000 microseconds = 1 millisecond.

Also, we can get the time in hour, minute and second from the RTC by using statements like:

DateTime now = rtc.now();

    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);

Since the RTC in this board has a resolution of 1 second, how to get the following millisecond part accurately?

micros() and millis() return the number of microseconds and millisecond respectively since the Arduino board began running the current program. I want the milliseconds to corresponding to the now.second() rather than from the time the Arduino started the program. I am not sure but perhaps in my specification, the counting should start/reset instantly after a new second has started?

  • When we use micros() we can get a more accurate measurement for the 1ms TIMER.

  • The TIMERs job is to say when it is time to do something; whether timing starts at power up or not is unimportant.

  • When the TIMER expires, we get the real time form the RTC and write that and the sensor data to memory . . .

  • If you want accurate real time down to the millisecond, a better RTC is needed.

Thanks. With your program and the Feather Adalogger's PCF8523 RTC, up to how many millisecond of accuracy can it achieve?

I tried to combine the RTC with millis() timer by syncing millis() to the RTC's 1Hz square-wave output but it gave me only 0 or 1 milliseconds in Serial.print().

  • And when you used micros() ?

  • The PCF8523 can go to 1/60 second (.0167 sec) , I only use the DS3231 :frowning: , have zero experience with PCF8523.

So if it is acceptable for me to take the sample every 20 msec, then the PCF8523 can get the job done? Doesn't the DS3231 also have a resolution of 1 sec?

Using micros()/1000, I get either 1 or 2.

If you have questions about code, post the code, using code tags.

Are you ignoring post 2? You do NOT need an RTC, the built in timers are easier to use.

  • Division defaults to integer, if you want decimal, you need to tell the compiler.
    micros()/1000.00

  • The DS3212 can generate 1 second interrupts.

When configuring the SQW pin of the Adalogger with RTC + SD, how do I determine which pin mode (frequency of square wave) to use for high accuracy?

RTClib: src/RTClib.h File Reference

rtc.writeSqwPinMode(PCF8523_SquareWave16kHz);

I noticed that when using 1Hz, the output of the time in Serial Monitor is very very slow.

Also, when I used these statements to print the time:

  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.print(':');
  Serial.println(micros()/1000);

and got something like:

22:6:46:28939
22:6:46:28945
22:6:46:28951
22:6:46:28957
22:6:46:28963

These are the last four data points of the 46th second. The next was: 22:6:47:28969.
What do these five digit numbers tell us?

The number of milliseconds of program run time that have elapsed since the program started.

28939 28.939ms
28945 28.945ms
28951 28.951ms
28957 28.957ms
28963 28.963ms

28969 28.969ms

This is the number of µs/ms since the program started.

Average is about 6µs between time intervals.

Edit

  • Serial monitor time stamping comes from the PC, turn it on and see what gets printed.

Thanks. Do they look correct and reasonable? I set the clock from the SQW pin to 1KHz. Not sure if that is the right choice. As mentioned before, setting it to 1Hz produced very very slow Serial.print() outputs.

How to make the output looks like this:
clock with milliseconds | envyen

  • To see a better result maybe write the time to SD card for a period of time then look at what was saved.

The format you have used for this information is very confusing. You are communicating that there is a hierarchical relation between the final value and the values that come before it. There is no such relation, so this notation is misleading.

More appropriate would be something like this:

timestamp: 22:6:46, run time: 28963 ms

Could you please elaborate on what to look at and how long a period? When I used a 1Hz clock, the display on the screen was very very slow. For other frequency such as 1KHz here, the last column of numbers changed so fast that I could not see on the Serial Monitor. I saved the data to a card. There are thunderds/thousands of them. I just listed a few here for discussion.

When googling about this RTC chip and millisecond, it was suggested to use a 1Hz clock. I think sometimes 1KHz clock showed up. Still have no idea which to pick.

Thanks. That format is easiler to understand.

Just to clarify... Here the "run time" started the counting from the fall of a square pulse issued by the SQE pin of the Adalogger rather than the actual run time (in millisecond) since the Arduino board begain running the program. Right?

That is incorrect. The micros() function returns the number of microseconds since the sketch program started running.

If you want the elapsed time since an event occurred, you must set a variable to the value of micros() at the time of the event, then subtract that from the current micros() return value:

// Event occurs...
timestamp = micros();
// Other things happen...
Serial.print("elapsed: ");
Serial.println((micros() - timestamp) / 1000);