How to collect 100 samples per second precisely Timer library

Hi,

I used an analog pin to collected sensor data. And I knew that the board is fast enough to allow me to collect sensor data more than 100Hz. My goal is to collect 100 samples per second, display it on serial monitor, and eventually save the data to a text file or csv file. (add time stamp as well).

Since I cannot control the running time of your loop, I came out with a solution to use "Timer.h". I

#include "Timer.h"

// Global variables

int vibdat[100];        // vibration 100 samples in one second  
int count;              // loop count 
Timer t;               // time event 

void setup() {
  //initialize serial
  Serial.begin(115200);
  //Read 100 sample vibration data every second
  t.every(1000,vibration);
}

void loop() {
   t.update();
}

void vibration()
{
   // put 100 samples into vibdat[]
   for (count=0;count<100;count++){
       vibdat[count] = analogRead(A0);
     }
     
   // Serial print the 100 sample data 
   for (count = 0 ; count<100; count++){
     Serial.print(count);
     Serial.print(',');
     Serial.println(vibdat[count]);
    }  
}

I used a software called CoolTerm to add timestamp and save the serial output, I found that the in some second there are 160 data, some seconds there are less than 50 data. I can never get exactly 100 data per second.

What is the best way to do it?
Thanks a lot!

You can use the onboard timers to accurately do something at a repeating period.

See:

100 samples per second is relatively slow. It may be simpler to use millis() to manage the timing as illustrated in Several Things at a Time

...R

  //Read 100 sample vibration data every second
  t.every(1000,vibration);

Every what? If those are microseconds, you are trying to take 1000 samples/second.

Is it so hard ?

uint32_t millis_ref;

void setup()
{
  ...
  millis_ref = millis() - 10;
}

void loop()
{
  if (millis() - millis_ref >= 10)
  {
    millis_ref += 10;
    ... do something 100Hz
  }
}

Robin2:
100 samples per second is relatively slow. It may be simpler to use millis() to manage the timing as illustrated in Several Things at a Time

...R

Thanks Robin, I now understand how to use millis() ~~~!

bricoleau:
Is it so hard ?

uint32_t millis_ref;

void setup()
{
  ...
  millis_ref = millis() - 10;
}

void loop()
{
  if (millis() - millis_ref >= 10)
  {
    millis_ref += 10;
    ... do something 100Hz
  }
}

Thanks! I get a lot of help from your code. I want to include some other codes in this loop, will this affect the sampling speed?

channinglin:
Thanks! I get a lot of help from your code. I want to include some other codes in this loop, will this affect the sampling speed?

Yes. I have a clock that ticks off hundredths of a second. It works fine with a segmented LED display. However with an OLED (using either Adafruit's or the SSD1306Ascii library) it bogs down and the hundredths lags noticeably.

It depends on the exec duration of your other codes.
Even if you find it huge, it might be fine if there is no delay included.

Please also notice that millis_ref += 10; is more accurate than millis_ref = millis(); in the main loop.

This will allow to catch up time, in case of little lag due to your other codes.
At the end, you will have your 100 samples per second, even if time between some samples is greater than 10 ms.

If you want accurate 100Hz, use micros(), not millis(). Millis() has significant jitter.
If you want quartz crystal accuracy you'll need an Arduino board with a quartz crystal
for the clock - many do not have this (alas).