Arduino Time stamping ADC data using GPS and PPS signal then send it through serial port

Thread Starter

amry priswanto

Joined May 27, 2019
5
Hello guys,
Recently I have a final project to develop digitizer for seismic DAQ using arduino uno.
I have some problems, first I should time stamped the adc data using gps and then send it through serial port.
I'm using Ublox Neo 6m gps, i has pps pin, and update rate can take about 10hz. So i guess it has cenctisecond resolution time.
My first scenario to do it is :
First I connect PPS pin to the digital input arduino, then if PPS signal is coming i take 100sample ADC and update the time and date from gps, then i mark the ADC data with time stamp, then send it through serial port .
My second alternate scenario :
First I take gps data at the first setup arduino program, and then in main void loop , I take the ADC data and also increment the datetime using micros() or millis() from arduino.
For thus two scenarios, which is possible to do ? Or maybe you guys have better option for me .
And the second question is, How to take sample at 100sps properly using arduino ?
I have two sketch to take adc data,
My first sketch to take sample from ADC is like this :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;​
Void loop ()
{
if (millis()-previous >=10) // take sample every 10ms or 100spd
{
previous = millis();
Serial.print(analog.Read(A0));
}
}

The second sketch is :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;​
Void loop ()
{
if (millis()-previous >=1000) // take 100 samples every 1 second
{
previous = millis();
Serial.print(analog.Read(A0));
}
}​
When I tried the first sketch using 1hz sine wave signal, the signal is showed correctly, smooth,
But when i tried the second sketch, it seems that the signal have some missing part or data,
Why the second sketch become like that, i saw that the first sketch and second sketch have some purpose to take 100 samples per second. ?
Thanks for your advice guys​
 

ebeowulf17

Joined Aug 12, 2014
3,307
Hello guys,
Recently I have a final project to develop digitizer for seismic DAQ using arduino uno.
I have some problems, first I should time stamped the adc data using gps and then send it through serial port.
I'm using Ublox Neo 6m gps, i has pps pin, and update rate can take about 10hz. So i guess it has cenctisecond resolution time.
My first scenario to do it is :
First I connect PPS pin to the digital input arduino, then if PPS signal is coming i take 100sample ADC and update the time and date from gps, then i mark the ADC data with time stamp, then send it through serial port .
My second alternate scenario :
First I take gps data at the first setup arduino program, and then in main void loop , I take the ADC data and also increment the datetime using micros() or millis() from arduino.
For thus two scenarios, which is possible to do ? Or maybe you guys have better option for me .
And the second question is, How to take sample at 100sps properly using arduino ?
I have two sketch to take adc data,
My first sketch to take sample from ADC is like this :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;​
Void loop ()
{
if (millis()-previous >=10) // take sample every 10ms or 100spd
{
previous = millis();
Serial.print(analog.Read(A0));
}
}

The second sketch is :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;​
Void loop ()
{
if (millis()-previous >=1000) // take 100 samples every 1 second
{
previous = millis();
Serial.print(analog.Read(A0));
}
}​
When I tried the first sketch using 1hz sine wave signal, the signal is showed correctly, smooth,
But when i tried the second sketch, it seems that the signal have some missing part or data,
Why the second sketch become like that, i saw that the first sketch and second sketch have some purpose to take 100 samples per second. ?
Thanks for your advice guys​
The second sketch appears to take just one reading per second (contrary to what the comments within the code say.)

Just look at the conditional - it waits until 1000ms (1 second) have passed, and then all it does is print the result of 1 analog read before waiting another second.
 

Thread Starter

amry priswanto

Joined May 27, 2019
5
Oh sorry, this is the second sketch :
The second sketch is :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;
Void loop ()
{
if (millis()-previous >=1000) // take 100 samples every 1 second
{
for (int i = 0 ; i <=99; i++)
{
previous = millis();
Serial.print(analog.Read(A0));
}
}
}
 

ebeowulf17

Joined Aug 12, 2014
3,307
As for your timing question, it depends on how accurate you need the time to be. If fractions of a second matter, or if this will run for a long time continuously, I would either read the gps time for every sample, or at least update the internal clock on the Arduino based on gps time fairly frequently. The clock in an Arduino isn't *bad* per se, but it will drift measurably over time compared to a high quality RTC, which in turn is also still rather inaccurate compared to atomic clocks, GPS time signals, etc.
 

Thread Starter

amry priswanto

Joined May 27, 2019
5
As for your timing question, it depends on how accurate you need the time to be. If fractions of a second matter, or if this will run for a long time continuously, I would either read the gps time for every sample, or at least update the internal clock on the Arduino based on gps time fairly frequently. The clock in an Arduino isn't *bad* per se, but it will drift measurably over time compared to a high quality RTC, which in turn is also still rather inaccurate compared to atomic clocks, GPS time signals, etc.
I need accuracy just in millisecond or centisecond,
I was tries to read gps time every sample, but its affected the sampling rate of my data. Without read gps data for every sample i can take sample at 100sps, but when i use gps and read it every sample data, it affected the sampling rate
 

Thread Starter

amry priswanto

Joined May 27, 2019
5
The second sketch appears to take just one reading per second (contrary to what the comments within the code say.)

Just look at the conditional - it waits until 1000ms (1 second) have passed, and then all it does is print the result of 1 analog read before waiting another second.
Oh sorry, this is the second sketch :
The second sketch is :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;
Void loop ()
{
if (millis()-previous >=1000) // take 100 samples every 1 second
{
for (int i = 0 ; i <=99; i++)
{
previous = millis();
Serial.print(analog.Read(A0));
}
}
 

ebeowulf17

Joined Aug 12, 2014
3,307
Oh sorry, this is the second sketch :
The second sketch is :
Unsigned long previous
Void setup()
{
Serial.begin(57600);
previous = 0;
Void loop ()
{
if (millis()-previous >=1000) // take 100 samples every 1 second
{
for (int i = 0 ; i <=99; i++)
{
previous = millis();
Serial.print(analog.Read(A0));
}
}
}
Well, strictly speaking either sketch does take 100 samples per second, so if that's really the intent, they're both ok. However, I suspect that's not really all you want.

If you want 100 samples per second, evenly spaced in time (in other words, one sample every 10ms,) then you need to do it the first way.

The second method doesn't take evenly spaced samples. Rather, it takes 100 samples as fast as it can, then waits most of a second, then takes another 100 really fast. Depending on the subtleties of the ADC and the libraries being used to communicate with it, those 100 samples might each be separated by several ms or more... or they might not even be "fresh" readings. You might just be reading the result buffer 100 times almost instantly, all with the same result.
 

Thread Starter

amry priswanto

Joined May 27, 2019
5
Well, strictly speaking either sketch does take 100 samples per second, so if that's really the intent, they're both ok. However, I suspect that's not really all you want.

If you want 100 samples per second, evenly spaced in time (in other words, one sample every 10ms,) then you need to do it the first way.

The second method doesn't take evenly spaced samples. Rather, it takes 100 samples as fast as it can, then waits most of a second, then takes another 100 really fast. Depending on the subtleties of the ADC and the libraries being used to communicate with it, those 100 samples might each be separated by several ms or more... or they might not even be "fresh" readings. You might just be reading the result buffer 100 times almost instantly, all with the same result.
How i can reading the result buffer 100 times almost instantly ? It seems new for me , sory :)
 

ebeowulf17

Joined Aug 12, 2014
3,307
I need accuracy just in millisecond or centisecond,
I was tries to read gps time every sample, but its affected the sampling rate of my data. Without read gps data for every sample i can take sample at 100sps, but when i use gps and read it every sample data, it affected the sampling rate
Can you afford to have a glitch, or a missed sample, once an hour, or once a day, or at some other predictable interval?

If you really need millisecond accuracy, you'll need to update the clock periodically, because the Arduino clock will gradually drift. How often you need to reset the clock depends on the Arduino accuracy and your tolerance for error. I don't remember Arduino clock accuracy specs off the top of my head, but I think the potential for error is significant, maybe a few seconds per day?

Ok, a quick Google search suggests that typical crystal oscillators have roughly 50ppm accuracy, which would mean up to 4.32 seconds per day of error, or 3 milliseconds of error per minute. So, if you need to guarantee millisecond accuracy, you need to update your clock at least once every 20 seconds!
 

ebeowulf17

Joined Aug 12, 2014
3,307
How i can reading the result buffer 100 times almost instantly ? It seems new for me , sory :)
Hard to explain if you haven't written code down to the level of directly addressing the ADC, and honestly I'm pretty new at trying to work down at that level myself.

Having said that, if you're working with a discrete ADC device with I2C, SPI, or some similar interface, it almost certainly uses "registers" or memory addresses to get things done. When you read the register that contains the result of the last ADC conversion, the device doesn't guarantee that you're getting a "fresh" reading - it doesn't limit you to reading each unique result just once. You can read that result as many times as you want before telling it to perform another conversion. Admittedly, if you're working with well written libraries, they're probably set up to protect you from such behavior, but there's no guarantee.

Some ADCs allow you to choose two modes of operation, one which takes one sample on command and then goes to sleep, and another in which it just keeps sampling as fast as it can, continuously. In the second mode, you don't explicitly tell it when to convert, so if you read 100 times a second, but it only does fresh conversions 10 times per second, then you'll end up reading roughly ten duplicate samples for each actual sample update.

Anyway, I probably shouldn't have brought up the whole buffer thing. The odds are pretty good that you don't need to worry about that. However, the other problem I mentioned, where it takes 100 real readings as fast as it can, which may be much faster than you want, is real. If you need them to be regular 10ms intervals, then you need to sample at those exact intervals.
 
Top