Powered up the 2nd GPS with reliable PPS.
Got the code working with the bouncy PPS that starts like this counting cycles between transition to HIGH in setup:
Requires coding around that and taking the first _isr on pin RISING and having that _ISR do this to itself :: detachInterrupt(gpsPin); Then it has to be turned back on before next PPS pulse.
On the AdaFruit Ultimate GPS the PPS is clean and that same loop reads like this:
Code:
599997583
599997636
T:\tCode\TIME\Teensy_Cycle_CountingT4\Teensy_Cycle_CountingT4.ino Dec 18 2020 21:11:23
Proper PPS Found!
Then the code knows it has the 'Proper PPS'. And the same Sketch does BOTH given that detectable difference in setup().
Interesting thing is both GPS's seem to trigger the PPS at the same time!
Here are TWO T_4.0's with the two diff GPS units - with the code in a single sketch where::
>> 1st T_4 is the bouncy one - that a stable reading has been managed, then it drives a pin HIGH ( like the Pendulum swing detector will I suppose? ) It writes it LOW 600ms later at the same time it re Attaches the PPS interrupt detection.
>> 2nd T_4 in 'Proper PPS' mode has an easier time detecting the stable PPS with _isr, and also has a second _isr on the pin coming from 1st T_4
Those two signals seems to be splitting an I/0 BUS cycle as sometimes the 1st is first pushing it's PPS report by 26 CPU cycles and other times the 2nd gets it first by about 125 CPU cycles.
Output from the 1st as before looks like - now with 4 sample averaging :
Code:
9 599995423 12764862 [599995411 - 599995428] 0 {17 av=599995421
10 599995409 12764872 [599995409 - 599995428] -14 {19 av=599995416
11 599995422 12764857 [599995409 - 599995428] 13 {19 av=599995419
12 599995413 12764859 [599995409 - 599995428] -9 {19 av=599995416
And the 2nd with PPS and PIN (row starts with ^ ) timing combined from setup() detecting the PPS rate of change into looping building the 4 point average. The PIN print puts '?' when it can't read well - and the Proper PPS just prints a newline:
Code:
T:\tCode\TIME\Teensy_Cycle_CountingT4\Teensy_Cycle_CountingT4.ino Dec 18 2020 23:11:06
683744084
599997654
599997687
T:\tCode\TIME\Teensy_Cycle_CountingT4\Teensy_Cycle_CountingT4.ino Dec 18 2020 23:11:06
Proper PPS Found!
PPS MISS RANGE
?1 3023737178 ___ [999999999 - 0] -1271230118 {3294967297 __<?? 3023737178
^2 599998204 ___ [599998204 - 599998204] 1871228322 {0 av=149999551__<<
2 599998204 38706794 [599998204 - 599998204] 1871228451 {0 av=149999551
3 599998207 38706123 [599998204 - 599998207] 3 {3 av=299999102
^3 599998101 ___ [599998101 - 599998204] -103 {103 av=299999076__<<
4 599998197 38706265 [599998197 - 599998207] -10 {10 av=449998652
^4 599998303 ___ [599998101 - 599998303] 202 {202 av=449998652__<<
5 599998201 38706218 [599998197 - 599998207] 4 {10 av=599998202
^5 599998201 ___ [599998101 - 599998303] -102 {202 av=599998202__<<
6 599998198 38706237 [599998197 - 599998207] -3 {10 av=599998200
^6 599998092 ___ [599998092 - 599998303] -109 {211 av=599998174__<<
^7 599998292 ___ [599998092 - 599998303] 200 {211 av=599998222__<<
7 599998186 38706237 [599998186 - 599998207] -12 {21 av=599998195
^8 599998190 ___ [599998092 - 599998303] -102 {211 av=599998193__<<
8 599998190 38706219 [599998186 - 599998207] 4 {21 av=599998193
...
426 599998108 38706202 [599998093 - 599998151] 8 {58 av=599998104
^426 599998108 ___ [599998093 - 599998151] 8 {58 av=599998104__<<
^427 599998101 ___ [599998093 - 599998151] -7 {58 av=599998103__<<
427 599998101 38706209 [599998093 - 599998151] -7 {58 av=599998103
...
1407 599998117 38706183 [599998093 - 599998151] -4 {58 av=599998119
^1407 599998117 ___ [599998078 - 599998151] -4 {73 av=599998119__<<
^1408 599998123 ___ [599998078 - 599998151] 6 {73 av=599998121__<<
1408 599998123 38706183 [599998093 - 599998151] 6 {58 av=599998121
... // Some time later the one GPS lost lock it seems and some missed data points - when it was noted with PPS MISS RANGE code triggered and did a reSync:
^5810 599998241 ___ [599998028 - 599998355] -108 {327 av=599998267__<<
5810 599998241 39996425 [599998119 - 599998375] -2 {256 av=599998241
^5811 599998130 ___ [599998028 - 599998355] -111 {327 av=599998212__<<
^5812 599998244 ___ [599998028 - 599998355] 114 {327 av=599998241__<<
^5813 599998344 ___ [599998028 - 599998355] 100 {327 av=599998239__<<
PPS MISS RANGE
^5812 599998244 ___ [599998028 - 599998355] -100 {327 av=599998240__<<
5812 599998244 39997130 [599998119 - 599998375] -1199996474 {256 av=599998241
...
7404 599998259 39996449 [599998119 - 599998375] 4 {256 av=599998255
^7404 599998259 ___ [599998028 - 599998366] 4 {338 av=599998255__<<
7405 599998250 39996447 [599998119 - 599998375] -9 {256 av=599998253
^7405 599998250 ___ [599998028 - 599998366] -9 {338 av=599998253__<<
The two T_4's have their own clock per GPS PPS - but as received on the 2nd T_4 - both signals arriving within a few cycles of each other shows the same AVG CycCnt value even with the 1st Teensy interrupt being independent it seems ... at 6.75 hours.
Here's the code - it might work well using the with a single T_4.x Proper PPS (on #17) code path and look for PIN (on #16) input from however the Pendulum swing point is read - if both go HIGH then LOW ONCE each second.
The PROPER PPS code path uses GPS GOOD versus GPS BOUNCE function sets. And GPS GOOD here is tied to the PIN ISR XFER functions that run in parallel emulating the Pendulum input on "2nd T_4" here.
It took some tweaking to get here - with the two units on hand (where the 1st simulates the Pendulum) - there may be some kludges left - but it generally looks as expected (gets out of sync it seems if 1st not online before 2nd - and can get out of sync with signal loss)- even with BOTH timing events happening within some hundred CPU cycles.
Here it is - maybe just a start for monitoring - I have made TWO edits to the code as I wrote this post ... first was shared vars in 'good' and 'pin' code for averages, second when it reports PPS MISS RANGE in PIN code - the left side seconds counts are reset:
Code:
// FB: https://forum.pjrc.com/threads/46652-Teensy-3-6-millis()-problem-amp-fastled?p=155323&viewfull=1#post155323
#define qBlink() {digitalToggleFast(LED_BUILTIN);}
uint32_t perMax = 0;
uint32_t perMin = 999999999;
uint32_t perPinMax = 0;
uint32_t perPinMin = 999999999;
const int gpsPin = 17;
const int gpsPinIO = 16;
volatile uint32_t gpsEdge = 0;
volatile uint32_t pinEdge = 0;
uint32_t lastEdge = 0;
uint32_t lastPinEdge = 0;
unsigned long longCount = 0;
unsigned long longPinCount = 0;
long test;
// void yield() {}
elapsedMicros debounceWait;
void setup() {
if ( ARM_DWT_CYCCNT == ARM_DWT_CYCCNT ) {
ARM_DEMCR |= ARM_DEMCR_TRCENA; // info from teensy forum, access cycle counter
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
}
pinMode(gpsPin, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
while (!Serial && (millis() <= 6000));
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
uint32_t tt = 0, ss = 0;
for ( int ii = 0; ii < 7; ii++) { // this shows GPS PPS jitter
int yy = digitalReadFast( gpsPin );
while ( yy == digitalReadFast( gpsPin ));
if ( yy) {
Serial.println( ss = ARM_DWT_CYCCNT - tt );
tt = ARM_DWT_CYCCNT;
}
}
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
if ( ss > 500'000'000) {
Serial.printf("Proper PPS Found!\n");
pinMode(gpsPinIO, INPUT);
attachInterrupt(gpsPinIO, pinISR, RISING); // set flag high on rising edge
attachInterrupt(gpsPin, gpsISR_PPS, RISING); // set flag high on rising edge
while ( 1 ) {
loopPPS();
}
}
else {
pinMode(gpsPinIO, OUTPUT);
attachInterrupt(gpsPin, gpsISR, RISING); // set flag high on rising edge
while ( 1 ) {
loop();
}
}
}
//------------------------------------- GPS BOUNCE
uint32_t lCnt = 0;
void loop() {
lCnt++;
if (gpsEdge != lastEdge) {
gpsTest();
}
if ( debounceWait > 600000 ) {
digitalWriteFast(gpsPinIO, LOW);
debounceWait = 0;
attachInterrupt(gpsPin, gpsISR, RISING);
}
}
//------------------------------------- GPS BOUNCE
void gpsTest() {
static uint32_t lastPeriod = 0;
uint32_t period = F_CPU_ACTUAL;
uint32_t thisEdge = 0;
thisEdge = gpsEdge; // free running time in cycle counts
period = thisEdge - lastEdge;
lastEdge = thisEdge;
longCount++;
debounceWait = 0;
//qBlink();
digitalWriteFast(LED_BUILTIN, LOW);
if ( longCount > 5 ) {
if ( period < perMin ) perMin = period;
if ( period > perMax && period < F_CPU_ACTUAL + 1000 ) perMax = period;
Serial.printf("%lu\t%lu\t%lu\t[%lu - %lu]\t%d\t{%lu\tav=%lu\n", longCount, period, lCnt, perMin, perMax, period - lastPeriod, perMax - perMin, fourAvg(period) );
}
else
Serial.println();
lCnt = 0;
lastPeriod = period;
}
//------------------------------------- GPS BOUNCE
void gpsISR() {
gpsEdge = ARM_DWT_CYCCNT;
digitalWriteFast(LED_BUILTIN, HIGH);
digitalWriteFast(gpsPinIO, HIGH);
detachInterrupt(gpsPin);
}
//------------------------------------- GPS GOOD
void loopPPS() {
lCnt++;
if (gpsEdge != lastEdge) {
gpsTestPPS();
// Serial.printf("\t\tPIvGPS diff=%lu\n", pinEdge - gpsEdge); // 129, 126 or 23 cycles diff : either makles the same IO bus cycle or the next w/ diff ~150 cycles
}
if (pinEdge != lastPinEdge) {
pinTest();
}
}
//------------------------------------- GPS GOOD
void gpsTestPPS() {
static uint32_t lastPeriod = 0;
uint32_t period = F_CPU_ACTUAL;
uint32_t thisEdge = gpsEdge;
qBlink();
period = thisEdge - lastEdge;
lastEdge = thisEdge;
longCount++;
debounceWait = 0;
if ( longCount != longPinCount)
Serial.print('\n');
if ( period < F_CPU_ACTUAL + 3000 ) {
if ( period < perMin ) perMin = period;
if ( period > perMax ) perMax = period;
Serial.printf("%lu\t%lu\t%lu\t[%lu - %lu]\t%d\t{%lu\tav=%lu\n", longCount, period, lCnt, perMin, perMax, period - lastPeriod, perMax - perMin, fourAvg(period) );
}
else {
Serial.println( "PPS MISS RANGE");
longPinCount = longCount; // Assume signal loss and get backin sync ?
}
lCnt = 0;
lastPeriod = period;
}
//------------------------------------- GPS GOOD
void gpsISR_PPS() {
gpsEdge = ARM_DWT_CYCCNT;
}
//------------------------------------- PIN ISR XFER
void pinTest() {
static uint32_t lastPeriod = 0;
uint32_t period = F_CPU_ACTUAL;
uint32_t thisEdge = pinEdge;
qBlink();
period = thisEdge - lastPinEdge;
lastPinEdge = thisEdge;
longPinCount++;
if ( longCount != longPinCount)
Serial.print('\n');
if ( period < F_CPU_ACTUAL + 3000 && period > F_CPU_ACTUAL - 3000 ) {
if ( period < perPinMin ) perPinMin = period;
if ( period > perPinMax ) perPinMax = period;
Serial.printf("^%lu\t%lu\t___\t[%lu - %lu]\t%d\t{%lu\tav=%lu__<<\n", longPinCount, period, perPinMin, perPinMax, period - lastPeriod, perPinMax - perPinMin, fourAvgPin(period) );
}
else
Serial.printf("?%lu\t%lu\t___\t[%lu - %lu]\t%d\t{%lu\t__<??\t%lu\n\n", longPinCount, period, perPinMin, perPinMax, period - lastPeriod, perPinMax - perPinMin, period );
lastPeriod = period;
}
//------------------------------------- PIN ISR XFER
void pinISR() {
pinEdge = ARM_DWT_CYCCNT;
}
//------------------------------------- GPS AVERAGES
uint32_t fourAvg( uint32_t inVal ) {
uint32_t retVal;
static int ii = 0;
static uint32_t vals[4];
vals[ii++] = inVal;
ii = (ii) & 3;
retVal = (vals[0] + vals[1] + vals[2] + vals[3]) / 4;
return retVal;
}
//------------------------------------- PIN ISR XFER
uint32_t fourAvgPin( uint32_t inVal ) {
uint32_t retVal;
static int ii = 0;
static uint32_t vals[4];
vals[ii++] = inVal;
ii = (ii) & 3;
retVal = (vals[0] + vals[1] + vals[2] + vals[3]) / 4;
return retVal;
}
You can see this code came from an old T_3.6 thread by the intro comment.
If the 2nd isn't started first the sync may be off as the two expect to clock together.