Skip to content

Commit 9bfe29c

Browse files
committed
Add support for external trigger control
1 parent c6945d4 commit 9bfe29c

File tree

7 files changed

+213
-10
lines changed

7 files changed

+213
-10
lines changed

Firmware/RTK_Surveyor/Begin.ino

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,38 @@ void beginSystemState()
497497
ButtonCheckTaskPriority,
498498
&ButtonCheckTaskHandle); //Task handle
499499
}
500+
501+
//Setup the timepulse output on the PPS pin for external triggering
502+
//Setup TM2 time stamp input as need
503+
void beginExternalTriggers()
504+
{
505+
UBX_CFG_TP5_data_t timePulseParameters;
506+
507+
if (i2cGNSS.getTimePulseParameters(&timePulseParameters) == false)
508+
log_e("getTimePulseParameters failed!");
509+
510+
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
511+
512+
// While the module is _locking_ to GNSS time, turn off pulse
513+
timePulseParameters.freqPeriod = 1000000; //Set the period between pulses in us
514+
timePulseParameters.pulseLenRatio = 0; //Set the pulse length in us
515+
516+
// When the module is _locked_ to GNSS time, make it generate 1kHz
517+
timePulseParameters.freqPeriodLock = settings.externalPulseTimeBetweenPulse_us; //Set the period between pulses is us
518+
timePulseParameters.pulseLenRatioLock = settings.externalPulseLength_us; //Set the pulse length in us
519+
520+
timePulseParameters.flags.bits.active = settings.enableExternalPulse; //Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
521+
timePulseParameters.flags.bits.lockedOtherSet = 1; //Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
522+
timePulseParameters.flags.bits.isFreq = 0; //Tell the module that we want to set the period
523+
timePulseParameters.flags.bits.isLength = 1; //Tell the module that pulseLenRatio is a length (in us)
524+
timePulseParameters.flags.bits.polarity = (uint8_t)settings.externalPulsePolarity; //Rising or failling edge type pulse
525+
526+
if (i2cGNSS.setTimePulseParameters(&timePulseParameters, 1000) == false)
527+
log_e("setTimePulseParameters failed!");
528+
529+
if (settings.enableExternalHardwareEventLogging == true)
530+
i2cGNSS.setAutoTIMTM2callback(&eventTriggerReceived); //Enable automatic TIM TM2 messages with callback to eventTriggerReceived
531+
else
532+
i2cGNSS.setAutoTIMTM2callback(NULL);
533+
534+
}

Firmware/RTK_Surveyor/RTK_Surveyor.ino

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
const int FIRMWARE_VERSION_MAJOR = 1;
4545
const int FIRMWARE_VERSION_MINOR = 10;
4646

47-
#define COMPILE_WIFI //Comment out to remove all WiFi functionality
48-
#define COMPILE_BT //Comment out to disable all Bluetooth
49-
//#define ENABLE_DEVELOPER //Uncomment this line to enable special developer modes (don't check power button at startup)
47+
//#define COMPILE_WIFI //Comment out to remove all WiFi functionality
48+
//#define COMPILE_BT //Comment out to disable all Bluetooth
49+
#define ENABLE_DEVELOPER //Uncomment this line to enable special developer modes (don't check power button at startup)
5050

5151
//Define the RTK board identifier:
5252
// This is an int which is unique to this variant of the RTK Surveyor hardware which allows us
@@ -353,6 +353,11 @@ uint32_t lastSetupMenuChange = 0; //Auto-selects the setup menu option after 150
353353
uint32_t lastTestMenuChange = 0; //Avoids exiting the test menu for at least 1 second
354354

355355
bool firstRoverStart = false; //Used to detect if user is toggling power button at POR to enter test menu
356+
357+
bool newEventToRecord = false; //Goes true when INT pin goes high
358+
uint32_t triggerCount = 0; //Global copy - TM2 event counter
359+
uint32_t towMsR = 0; //Global copy - Time Of Week of rising edge (ms)
360+
uint32_t towSubMsR = 0; //Global copy - Millisecond fraction of Time Of Week of rising edge in nanoseconds
356361
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
357362

358363
void setup()
@@ -386,6 +391,8 @@ void setup()
386391

387392
beginAccelerometer();
388393

394+
beginExternalTriggers(); //Configure the time pulse output and TM2 input
395+
389396
beginSystemState(); //Determine initial system state. Start task for button monitoring.
390397

391398
Serial.flush(); //Complete any previous prints
@@ -396,6 +403,7 @@ void setup()
396403
void loop()
397404
{
398405
i2cGNSS.checkUblox(); //Regularly poll to get latest data and any RTCM
406+
i2cGNSS.checkCallbacks(); //Process any callbacks: ie, eventTriggerReceived
399407

400408
updateSystemState();
401409

@@ -467,6 +475,27 @@ void updateLogs()
467475
}
468476
}
469477

478+
//Record any pending trigger events
479+
if (newEventToRecord == true)
480+
{
481+
Serial.println("Recording event");
482+
483+
//Record trigger count with Time Of Week of rising edge (ms) and Millisecond fraction of Time Of Week of rising edge (ns)
484+
char eventData[82]; //Max NMEA sentence length is 82
485+
snprintf(eventData, sizeof(eventData), "%d,%d,%d", triggerCount, towMsR, towSubMsR);
486+
487+
char nmeaMessage[82]; //Max NMEA sentence length is 82
488+
createNMEASentence(CUSTOM_NMEA_TYPE_EVENT, nmeaMessage, eventData); //textID, buffer, text
489+
490+
if (xSemaphoreTake(xFATSemaphore, fatSemaphore_shortWait_ms) == pdPASS)
491+
{
492+
ubxFile.println(nmeaMessage);
493+
494+
xSemaphoreGive(xFATSemaphore);
495+
newEventToRecord = false;
496+
}
497+
}
498+
470499
//Report file sizes to show recording is working
471500
if (millis() - lastFileReport > 5000)
472501
{

Firmware/RTK_Surveyor/States.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ void updateSystemState()
571571
if (online.logging == true)
572572
{
573573
char nmeaMessage[82]; //Max NMEA sentence length is 82
574-
createNMEASentence(1, 2, nmeaMessage, (char*)"CustomEvent"); //sentenceNumber, textID, buffer, text
574+
createNMEASentence(CUSTOM_NMEA_TYPE_WAYPOINT, nmeaMessage, (char*)"CustomEvent"); //textID, buffer, text
575575
ubxFile.println(nmeaMessage);
576576
displayEventMarked(500); //Show 'Event Marked'
577577
}

Firmware/RTK_Surveyor/System.ino

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,15 @@ boolean SFE_UBLOX_GNSS_ADD::getModuleInfo(uint16_t maxWait)
756756

757757
//Create $GNTXT, type message complete with CRC
758758
//https://www.nmea.org/Assets/20160520%20txt%20amendment.pdf
759-
//Used for reporting a system reboot inside the log
760-
void createNMEASentence(uint8_t sentenceNumber, uint8_t textID, char *nmeaMessage, char *textMessage)
759+
//Used for recording system events (boot reason, event triggers, etc) inside the log
760+
void createNMEASentence(customNmeaType_e textID, char *nmeaMessage, char *textMessage)
761761
{
762+
//Currently we don't have messages longer than 82 char max so we hardcode the sentence numbers
763+
const uint8_t totalNumberOfSentences = 1;
764+
const uint8_t sentenceNumber = 1;
765+
762766
char nmeaTxt[82]; //Max NMEA sentence length is 82
763-
sprintf(nmeaTxt, "$GNTXT,01,%02d,%02d,%s*", sentenceNumber, textID, textMessage);
767+
sprintf(nmeaTxt, "$GNTXT,%02d,%02d,%02d,%s*", totalNumberOfSentences, sentenceNumber, textID, textMessage);
764768

765769
//From: http://engineeringnotes.blogspot.com/2015/02/generate-crc-for-nmea-strings-arduino.html
766770
byte CRC = 0; // XOR chars between '$' and '*'

Firmware/RTK_Surveyor/menuMessages.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ void beginLogging()
384384
}
385385

386386
char nmeaMessage[82]; //Max NMEA sentence length is 82
387-
createNMEASentence(1, 1, nmeaMessage, rstReason); //sentenceNumber, textID, buffer, text
387+
createNMEASentence(CUSTOM_NMEA_TYPE_RESET_REASON, nmeaMessage, rstReason); //textID, buffer, text
388388
ubxFile.println(nmeaMessage);
389389

390390
if (reuseLastLog == true)

Firmware/RTK_Surveyor/menuPorts.ino

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ void menuPorts()
33
if (productVariant == RTK_SURVEYOR)
44
menuPortsSurveyor();
55
else if (productVariant == RTK_EXPRESS || productVariant == RTK_EXPRESS_PLUS)
6-
menuPortsExpress();
6+
menuPortsMultiplexed();
77
}
88

99
//Set the baud rates for the radio and data ports
@@ -67,7 +67,7 @@ void menuPortsSurveyor()
6767
}
6868

6969
//Set the baud rates for the radio and data ports
70-
void menuPortsExpress()
70+
void menuPortsMultiplexed()
7171
{
7272
while (1)
7373
{
@@ -100,6 +100,10 @@ void menuPortsExpress()
100100
Serial.print(getSerialRate(COM_PORT_UART1));
101101
Serial.println(F(" bps"));
102102
}
103+
else if (settings.dataPortChannel == MUX_PPS_EVENTTRIGGER)
104+
{
105+
Serial.print(F("3) Configure External Triggers"));
106+
}
103107

104108
Serial.println(F("x) Exit"));
105109

@@ -155,6 +159,94 @@ void menuPortsExpress()
155159
i2cGNSS.setSerialRate(newBaud, COM_PORT_UART1); //Set Data Port
156160
}
157161
}
162+
else if (incoming == '3' && settings.dataPortChannel == MUX_PPS_EVENTTRIGGER)
163+
{
164+
menuPortHardwareTriggers();
165+
}
166+
else if (incoming == 'x')
167+
break;
168+
else if (incoming == STATUS_GETBYTE_TIMEOUT)
169+
break;
170+
else
171+
printUnknown(incoming);
172+
}
173+
174+
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
175+
}
176+
177+
//Configure the behavior of the PPS and INT pins on the ZED-F9P
178+
//Most often used for logging events (inputs) and when external triggers (outputs) occur
179+
void menuPortHardwareTriggers()
180+
{
181+
int menuTimeoutExtended = 30; //Increase time needed for complex data entry (mount point ID, ECEF coords, etc).
182+
183+
while (1)
184+
{
185+
Serial.println();
186+
Serial.println(F("Menu: Port Hardware Trigger Menu"));
187+
188+
Serial.print(F("1) Enable External Pulse: "));
189+
if (settings.enableExternalPulse == true) Serial.println(F("Enabled"));
190+
else Serial.println(F("Disabled"));
191+
192+
if (settings.enableExternalPulse == true)
193+
{
194+
Serial.print(F("2) Set time between pulses: "));
195+
Serial.print(settings.externalPulseTimeBetweenPulse_us / 1000.0);
196+
Serial.println(F("ms"));
197+
198+
Serial.print(F("3) Set pulse length: "));
199+
Serial.print(settings.externalPulseLength_us / 1000.0);
200+
Serial.println(F("ms"));
201+
202+
Serial.print(F("4) Set pulse polarity: "));
203+
if (settings.externalPulsePolarity == PULSE_RISING_EDGE) Serial.println(F("Rising"));
204+
else Serial.println(F("Falling"));
205+
}
206+
207+
Serial.print(F("5) Log External Events: "));
208+
if (settings.enableExternalHardwareEventLogging == true) Serial.println(F("Enabled"));
209+
else Serial.println(F("Disabled"));
210+
211+
Serial.println(F("x) Exit"));
212+
213+
byte incoming = getByteChoice(menuTimeout); //Timeout after x seconds
214+
215+
if (incoming == '1')
216+
{
217+
settings.enableExternalPulse ^= 1;
218+
}
219+
else if (incoming == '2' && settings.enableExternalPulse == true)
220+
{
221+
Serial.print(F("Time between pulses in milliseconds: "));
222+
double pulseTime = getDouble(menuTimeoutExtended); //Timeout after x seconds
223+
224+
if (pulseTime != STATUS_GETNUMBER_TIMEOUT && pulseTime != STATUS_PRESSED_X)
225+
{
226+
settings.externalPulseTimeBetweenPulse_us = pulseTime * 1000;
227+
}
228+
}
229+
else if (incoming == '3' && settings.enableExternalPulse == true)
230+
{
231+
Serial.print(F("Pulse length in milliseconds: "));
232+
double pulseLength = getDouble(menuTimeoutExtended); //Timeout after x seconds
233+
234+
if (pulseLength != STATUS_GETNUMBER_TIMEOUT && pulseLength != STATUS_PRESSED_X)
235+
{
236+
settings.externalPulseLength_us = pulseLength * 1000;
237+
}
238+
}
239+
else if (incoming == '4' && settings.enableExternalPulse == true)
240+
{
241+
if (settings.externalPulsePolarity == PULSE_RISING_EDGE)
242+
settings.externalPulsePolarity = PULSE_FALLING_EDGE;
243+
else
244+
settings.externalPulsePolarity = PULSE_RISING_EDGE;
245+
}
246+
else if (incoming == '5')
247+
{
248+
settings.enableExternalHardwareEventLogging ^= 1;
249+
}
158250
else if (incoming == 'x')
159251
break;
160252
else if (incoming == STATUS_GETBYTE_TIMEOUT)
@@ -164,4 +256,27 @@ void menuPortsExpress()
164256
}
165257

166258
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
259+
260+
beginExternalTriggers(); //Update with new settings
261+
262+
if (settings.enableExternalHardwareEventLogging == true)
263+
i2cGNSS.setAutoTIMTM2callback(&eventTriggerReceived); // Enable automatic TIM TM2 messages with callback to eventMessageReceived
264+
else
265+
i2cGNSS.setAutoTIMTM2callback(NULL);
266+
}
267+
268+
void eventTriggerReceived(UBX_TIM_TM2_data_t ubxDataStruct)
269+
{
270+
// It is the rising edge of the sound event (TRIG) which is important
271+
// The falling edge is less useful, as it will be "debounced" by the loop code
272+
if (ubxDataStruct.flags.bits.newRisingEdge) // 1 if a new rising edge was detected
273+
{
274+
Serial.println("Rising Edge Event");
275+
276+
triggerCount = ubxDataStruct.count;
277+
towMsR = ubxDataStruct.towMsR; // Time Of Week of rising edge (ms)
278+
towSubMsR = ubxDataStruct.towSubMsR; // Millisecond fraction of Time Of Week of rising edge in nanoseconds
279+
280+
newEventToRecord = true;
281+
}
167282
}

Firmware/RTK_Surveyor/settings.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ typedef enum
7070
COORD_TYPE_GEOGRAPHIC,
7171
} coordinateType_e;
7272

73+
//User can select output pulse as either falling or rising edge
74+
typedef enum
75+
{
76+
PULSE_FALLING_EDGE = 0,
77+
PULSE_RISING_EDGE,
78+
} pulseEdgeType_e;
79+
80+
//Custom NMEA sentence types output to the log file
81+
typedef enum
82+
{
83+
CUSTOM_NMEA_TYPE_RESET_REASON = 0,
84+
CUSTOM_NMEA_TYPE_WAYPOINT,
85+
CUSTOM_NMEA_TYPE_EVENT,
86+
} customNmeaType_e;
87+
7388
//Freeze and blink LEDs if we hit a bad error
7489
typedef enum
7590
{
@@ -291,6 +306,11 @@ struct struct_settings {
291306
bool autoIMUmountAlignment = true; //Allows unit to automatically establish device orientation in vehicle
292307
bool enableResetDisplay = false;
293308
uint8_t resetCount = 0;
309+
bool enableExternalPulse = false; //Send pulse once lock is achieved
310+
uint32_t externalPulseTimeBetweenPulse_us = 500000; //us between pulses, max of 65s
311+
uint32_t externalPulseLength_us = 100000; //us length of pulse
312+
pulseEdgeType_e externalPulsePolarity = PULSE_RISING_EDGE; //Pulse rises for pulse length, then falls
313+
bool enableExternalHardwareEventLogging = false; //Log when INT/TM2 pin goes low
294314
} settings;
295315

296316
//Monitor which devices on the device are on or offline.

0 commit comments

Comments
 (0)