Sometimes I need a relatively high precision in my programs. But the time measured by millis() or micros() changes from board to board.
If I use different Arduinos - actually I'm working with Arduino Mega 2560 - the measured times are never the same.
My high precision reference is the PPS-signal from my BN-280 GPS-Borad. The PPS-signal has a very high accuricy, so I use the PPS to trigger the Arduinos with an Interrupt.
The fastest 2560 I own is very fast. In 12 hours it counts 46, 119484sec to much. My slowest 2560 was in 12 hours 10, 056192sec to late.
The time-difference on Arduino increases or decreases linear over time (only with a small deviation over temperature).
If I measured the deviation of the used Arduine I can calibrate them individually.
The solution is easy: with the PPS-signal from my BN-280 (each GPS-modul with a PPS-signal works well) I trigger the Arduino, read the time with micros() or millis() and send the times to the computer.
With the measured difference I can adjust each Arduino individual.
In the Video my "slow" Arduino counts in 40sec only 39.748168sec.
GPS-accuracy
Arduino/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// demonstrate how to receive GPS-data character by character with an Beitian BN-280 and an Arduino Mega 2560
//
// with the 2.nd and 3.rd listing you can test the accuracy of your Arduinos - the clock-rate is mostly not very precise
//
//
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// x x
// x BN-280 x
// x x
// x x
// x ceramic-antenna upwards x
// x x
// x x
// x LED's (downside) x blue LED flasches 1x per sec -
// x x red LED flashes only if you receive valid data
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// | | | | | |
// pin-nr. 6 5 4 3 2 1
// | | | | | |
// | | | | | 1-- = PPS (1 short pulse pes second if BN-280 received valid data)
// | | | | 2----- = GND ( 0V from Arduino Mega)
// | | | 3 ------- = TX ( GPS-data to PC)
// | | 4----------- = RX ( data from PC - mostly not needed)
// | 5-------------- = VCC ( +5V from Arduino Mega)
// 6----------------- = BOOT (NC) normally not used
//
//
// wiring diagram BN-280 to Arduino Mega 2560:
//
// BN-280 --- Arduino Mega 2560
// ------------------------------------
// pin-1 --- pin 2 (used in anothe program for Interrupt to test the accuracy of the Arduino)
// pin-2 --- GND
// pin-3 --- pin 19 (used as Serial1 with 9600)
// pin-4 --- not used
// pin-5 --- VCC
// pin-6 --- not used
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// Listing 1 can be used for a High-Precision Clock, for a GPS-Tracker or someone else - Time is GPS-time //
// //
// With Listings 2 and 3 you can check the accuracy of your Arduino Mega (or other Arduini too) //
// The PPS of your BN-280 has a very high accuracy (like GPS) //
// //
// The internal 'clock' or 'timer' of an Arduino is not very precise //
// //
// My Mega 2560 works not like discribed with 16MHz //
// It works with about 16,017MHZ //
// This value is relatively constant, only with a small temperature-drift //
// //
// Program 2 and 3 counts the PPS-signal and read the time of your Arduino with micros() or nanos() //
// //
// Tis listing contains 3 programs - please choose only one at the same time //
// //
// //
// Response of Listing 1 is: 155230 = 15:52:30 ; lat ; 51.362358093261; lon ; 7.077597618103 //
// //
// Time h m s Lat Lon //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
///////////////////////////////////////////////////// Begin Program 1 ///////////////////////////////////////////////
// //
const byte interruptPin = 2; //
char vergleich='$'; // new line start with "$" //
char zeichen; //
char teil0[20]; //
char teil1[20]; //
char teil2[20]; //
String zeichenkette, gesamttext,text1, text2, text3, text4, text5, text6;; //
int pos=1; //
double latoriginal; // lat = 52,... //
double lonoriginal; // lon = 7,... //
double Zeit,Puffer,stunde,minute,sekunde;; //
//-----------------------------------------------------------------------------------------------------------------//
void setup() //
{ //
Serial.begin(115200); // speed to computer //
Serial1.begin(9600); // speed from BN-280 //
pinMode(interruptPin, INPUT_PULLUP); // Important: INPUT_PULLUP !!! //
zeichenkette=" "; //
} //
//-----------------------------------------------------------------------------------------------------------------//
void loop() //
{ //
if(zeichenkette=="$") // a new line starts with "$" //
{ //
do //
{ //
zeichen=Serial1.read(); //
if((zeichen>36)&&(zeichen<91)) // valid character from ASCII 36 to ASCII 91 //
{ //
if (zeichen!=',') // data are separated by "," //
{ //
zeichenkette = zeichenkette + zeichen; // add each character to a string //
} //
else //
{ //
if (pos==6) //
{ //
text6=zeichenkette; //
zeichenkette=""; //
pos++; //
} //
if (pos==5) //
{ //
text5=zeichenkette; //
zeichenkette=""; //
pos++; //
} //
if (pos==4) //
{ //
text4=zeichenkette; //
zeichenkette=""; //
pos++; //
} //
if (pos==3) //
{ //
text3=zeichenkette; //
zeichenkette=""; //
pos++; //
} //
if (pos==2) //
{ //
text2=zeichenkette; //
zeichenkette=""; //
pos++; //
} //
if (pos==1) //
{ //
zeichenkette=""; //
pos++; //
} //
} //
} //
} //
while(zeichen!=vergleich ); //
} //
else //
{ //
if (text3=="A") // Ist die ein gltiger Datensatz ? // valid data? //
{ // //
text2.toCharArray(teil0,20); // //
Zeit=strtod(teil0,NULL); // convert time(text) to time(number) //
// //
text4.toCharArray(teil1,20); // //
latoriginal=strtod(teil1,NULL); // convert lat(text) to lat(number) //
latoriginal=latoriginal/100; // //
// //
text6.toCharArray(teil2,20); // //
lonoriginal=strtod(teil2,NULL); // convert lon(text) to lon(number) //
lonoriginal=lonoriginal/100; // //
// //
stunde=int(Zeit/10000.0); // separate time in: //
Puffer=Zeit-stunde*10000; // hours //
minute=int(Puffer/100.0); // minutes //
sekunde=Zeit-stunde*10000-minute*100; // seconds //
//
//////////////////////////////////////////////////////////////////////// Output only with valid data //
// //
Serial.print(Zeit,0); // print received time //
Serial.print(" = "); // //
Serial.print(stunde,0); // print hours //
Serial.print(":"); // //
Serial.print(minute,0); // print minutes //
Serial.print(":"); // //
Serial.print(sekunde,0); // print seconds //
// //
Serial.print(" ; lat ; "); // //
Serial.print(latoriginal,12); // print lat //
Serial.print("; lon ; "); // //
Serial.println(lonoriginal,12); // print lon //
} //
zeichenkette = vergleich; //
pos=1; //
} //
} //
///////////////////////////////////////////////////////// End Program 1 /////////////////////////////////////////////
*/
//////////////////////////////////////////////////////// Begin Program 2 ////////////////////////////////////////////
// //
// This program show the difference between GPS-precision und Arduino //
// This Program uses micros() //
// //
// Arduino is triggerd vis interrupt from BN-280 //
// The PPS-signal has GPS-accuracy //
// //
// PPS has the highest precision you get free if your board has a pps-output //
// //
// At the beginning you have a countdown //
// On 0 the time is reset to 0 //
// Then every sec you get a new response like: //
// -2 8188288 //
// -1 9189348 //
// 0 0 //
// 1 1001064 //
// 2 2002124 //
// 3 3003188 //
// and so on //
// //
// The example values of my Arduino shows, that every sec the internal //
// counter - called by micros() - added not exactly 1000000microsecons //
// //
// Here the difference is 1064microsec in the first sec //
// After 2sec the differece is 2124microsec //
// //
// My Arduino is to fast. In 3sec it counts 3188microsec to much //
// In 12 hours the different was 46,119484sec //
// //
// That's nothing for high precision //
// But it's good enogh for many experiments //
// //
// You can copy the values from the monitor-program into Win-Editor //
// Save the file to test.txt //
// Open the file with Excel, separated by " " (blank) //
// Then show an x-y plot //
// //
//-----------------------------------------------------------------------------------------------------------------//
// //
const byte interruptPin = 2; //
const byte ausgang1 = 5; //
const byte ausgang2 = 7; //
const byte ledPin = 13; //
double Ausgabe,Zeitpunkt,microsPrevious, microsNow1,microsDelta1; //
int identifier; //
int messwerte; //
int messpos = 0; //
int idlevel = 0; //
int gesendet = 0; //
//----------------------------------------------------------------------- //
void setup() //
{ //
Serial.begin(115200); //
pinMode(ledPin, OUTPUT); //
pinMode(ausgang1, OUTPUT); //
pinMode(ausgang2, OUTPUT); //
pinMode(interruptPin, INPUT_PULLUP); // Important: INPUT_PULLUP !!! //
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING); //
Zeitpunkt=-10; //
microsPrevious = micros(); //
} //
//-----------------------------------------------------------------------------------------------------------------//
void loop() //
{ //
// nothing to do - Program run through the Interrupt //
} //
//-----------------------------------------------------------------------------------------------------------------//
void blink() //
{ //
microsNow1 = micros(); //
microsDelta1=microsNow1-microsPrevious; //
microsPrevious=microsNow1; //
if(Zeitpunkt==0) //
{ //
Ausgabe=0; //
} //
else //
{ //
Ausgabe=Ausgabe+microsDelta1; //
} //
Serial.print(Zeitpunkt,0); // , 0); //
Serial.print(" "); //
Serial.println(Ausgabe,0); // , 0); //
Zeitpunkt++; //
} //
//-----------------------------------------------------------------------------------------------------------------//
//////////////////////////////////////////////////////// End Program 2 //////////////////////////////////////////////
/*
//////////////////////////////////////////////////////// Begin Program 3 ////////////////////////////////////////////
// //
// Show the difference between GPS-precision und Arduino //
// This Program uses millis() //
// //
// Arduino is triggerd vis interrupt from BN-280 //
// The PPS-signal has GPS-accuracy //
// //
// PPS has the highest precision you get free if your board has a pps-output //
// //
// At the beginning you have a countdown //
// On 0 the time is reset to 0 //
// Then every sec you get a new response like: //
// -3 7133 //
// -2 8134 //
// -1 9135 //
// 0 0 //
// 1 1002 //
// 2 2002 //
// 3 3003 //
// and so on //
// //
// The example values of my Arduino shows, that every sec the internal //
// counter - called by millis() - added not exactly 1000msec //
// //
// Here the difference is about 2msec in the first sec //
// After 2sec the differece show 2msec too //
// But it's rounded, so sometimes it shows the same difference //
// //
// My Arduino is to fast - the same like with micros() //
// A short test shows: //
// 598 598638 //
// 599 599638 //
// ---> 600 600640 <--- //
// 601 601641 //
// 602 602641 //
// //
// In 10min the difference was 640msec - see marking above --> <-- //
// In 938sec the difference was about 1sec //
// That's the same like the test's with micros() //
// //
// That's nothing for high precision //
// But it's good enogh for many experiments //
// //
// You can copy the values from the monitor-program into Win-Editor //
// Save the file to test.txt //
// Open the file with Excel, separated by " " (blank) //
// Then show an x-y plot //
// //
// left: time in sec (GPS) right: counts called by millis() //
// //
// at the beginning you have a countdown to compare the time with a clock //
// //
// if you run the program for 1000sec and Arduino is perfect then //
// you get "1000 1000000" //
// (in 1000sec you get 1000000msec) //
// //
// With my Arduino I get "1000 1001069" //
// (That's very bad for long-time experiments) //
// (For short-time-use it's o.K) //
// //
//-----------------------------------------------------------------------------------------------------------------//
// //
const byte interruptPin = 2; //
double Zeitpunkt,Ausgabe,millisPrevious,millisDelta,millisNow; //
//----------------------------------------------------------------------- //
void setup() //
{ //
Serial.begin(115200); //
pinMode(interruptPin, INPUT_PULLUP); //
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING); //
Zeitpunkt=-10; //
Ausgabe=0; //
millisPrevious = millis(); //
} //
//-----------------------------------------------------------------------------------------------------------------//
void loop() //
{ //
// nothing to do - Program run through the Interrupt //
} //
//-----------------------------------------------------------------------------------------------------------------//
void blink() //
{ //
millisNow = millis(); //
millisDelta=millisNow-millisPrevious; //
millisPrevious=millisNow; //
if(Zeitpunkt==0) //
{ //
Ausgabe=0; //
} //
else //
{ //
Ausgabe=Ausgabe+millisDelta; //
} //
//messwerte=microsDelta1; //
//Serial.println(messwerte, 0); //
Serial.print(Zeitpunkt,0); // , 0); //
Serial.print(" "); //
Serial.println(Ausgabe,0); // , 0); //
Zeitpunkt++; //
} //
//-----------------------------------------------------------------------------------------------------------------//
//////////////////////////////////////////////////////// End Progam 3 ///////////////////////////////////////////////
*/
Comments