Merge pull request #2 from sparkfun/release_candidate

v2.0.1 : Adding time pulse examples
This commit is contained in:
Paul
2021-01-14 09:12:40 +00:00
committed by GitHub
7 changed files with 444 additions and 1 deletions
@@ -0,0 +1,120 @@
/*
Time Pulse Parameters - Bullet Time (https://en.wikipedia.org/wiki/Bullet_time)
By: Paul Clark (PaulZC)
Date: January 13th, 2021
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
pin to produce a pulse once per second but with an adjustable delay. You could use this to
trigger multiple cameras and replicate the "bullet time" effect.
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
accurate timelapse camera shutter signal? This is the product for you!
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
NEO-M8P RTK: https://www.sparkfun.com/products/15005
SAM-M8Q: https://www.sparkfun.com/products/15106
Hardware Connections:
Plug a Qwiic cable into the GNSS and a BlackBoard
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <Wire.h> //Needed for I2C to GNSS
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;
void setup()
{
Serial.begin(115200);
while (!Serial)
; //Wait for user to open terminal
Serial.println(F("SparkFun u-blox Example"));
Wire.begin();
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
{
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
while (1)
;
}
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
// Create storage for the time pulse parameters
UBX_CFG_TP5_data_t timePulseParameters;
// Get the time pulse parameters
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("getTimePulseParameters failed! Freezing..."));
while (1) ; // Do nothing more
}
// Print the CFG TP5 version
Serial.print(F("UBX_CFG_TP5 version: "));
Serial.println(timePulseParameters.version);
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
// We can configure the time pulse pin to produce a defined frequency or period
// Here is how to set the period:
// Let's say that we want our pulse-per-second to be as accurate as possible. So, let's tell the module
// to generate no signal while it is _locking_ to GNSS time. We want the signal to start only when the module is
// _locked_ to GNSS time.
timePulseParameters.freqPeriod = 0; // Set the frequency/period to zero
timePulseParameters.pulseLenRatio = 0; // Set the pulse ratio to zero
// When the module is _locked_ to GNSS time, make it generate a 0.1 second pulse once per second
timePulseParameters.freqPeriodLock = 1000000; // Set the period to 1,000,000 us
timePulseParameters.pulseLenRatioLock = 100000; // Set the pulse length to 0.1s (100,000 us)
timePulseParameters.flags.bits.polarity = 1; // Set the polarity to "1" (high for 0.1s, low for 0.9s, rising edge at top of second)
// We can use userConfigDelay to delay the pulse for each camera. The delay needs to be negative for this example.
// We can delay the pulse by +/- 2^31 nanoseconds (+/- 2.147 seconds)
//timePulseParameters.userConfigDelay = 0; // Camera 1: delay the pulse by 0ns
//timePulseParameters.userConfigDelay = -100000000; // Camera 2: delay the pulse by 0.1s (100,000,000 ns)
//timePulseParameters.userConfigDelay = -200000000; // Camera 3: delay the pulse by 0.2s (200,000,000 ns)
timePulseParameters.userConfigDelay = -300000000; // Camera 4: delay the pulse by 0.3s (300,000,000 ns)
//timePulseParameters.userConfigDelay = -400000000; // Camera 5: delay the pulse by 0.4s (400,000,000 ns)
//timePulseParameters.userConfigDelay = -500000000; // Camera 6: delay the pulse by 0.5s (500,000,000 ns)
//timePulseParameters.userConfigDelay = -600000000; // Camera 7: delay the pulse by 0.6s (600,000,000 ns)
//timePulseParameters.userConfigDelay = -700000000; // Camera 8: delay the pulse by 0.7s (700,000,000 ns)
//timePulseParameters.userConfigDelay = -800000000; // Camera 9: delay the pulse by 0.8s (800,000,000 ns)
//timePulseParameters.userConfigDelay = -900000000; // Camera 10: delay the pulse by 0.9s (900,000,000 ns)
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
timePulseParameters.flags.bits.isFreq = 0; // Tell the module that we want to set the period (not the frequency)
timePulseParameters.flags.bits.isLength = 1; // Tell the module that pulseLenRatio is a length (in us) - not a duty cycle
// Now set the time pulse parameters
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("setTimePulseParameters failed!"));
}
else
{
Serial.println(F("Success!"));
}
// Finally, save the time pulse parameters in battery-backed memory so the pulse will automatically restart at power on
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); // Save the configuration
}
void loop()
{
// Nothing to do here
}
@@ -0,0 +1,101 @@
/*
Time Pulse Parameters - Frequency
By: Paul Clark (PaulZC)
Date: January 13th, 2021
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
pin to produce a 1kHz squarewave
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
accurate frequency or clock source for your latest project? This is the product for you!
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
NEO-M8P RTK: https://www.sparkfun.com/products/15005
SAM-M8Q: https://www.sparkfun.com/products/15106
Hardware Connections:
Plug a Qwiic cable into the GNSS and a BlackBoard
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <Wire.h> //Needed for I2C to GNSS
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;
void setup()
{
Serial.begin(115200);
while (!Serial)
; //Wait for user to open terminal
Serial.println(F("SparkFun u-blox Example"));
Wire.begin();
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
{
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
while (1)
;
}
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
// Create storage for the time pulse parameters
UBX_CFG_TP5_data_t timePulseParameters;
// Get the time pulse parameters
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("getTimePulseParameters failed! Freezing..."));
while (1) ; // Do nothing more
}
// Print the CFG TP5 version
Serial.print(F("UBX_CFG_TP5 version: "));
Serial.println(timePulseParameters.version);
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
// We can configure the time pulse pin to produce a defined frequency or period
// Here is how to set the frequency:
// While the module is _locking_ to GNSS time, make it generate 2kHz
timePulseParameters.freqPeriod = 2000; // Set the frequency/period to 2000Hz
timePulseParameters.pulseLenRatio = 0x55555555; // Set the pulse ratio to 1/3 * 2^32 to produce 33:67 mark:space
// When the module is _locked_ to GNSS time, make it generate 1kHz
timePulseParameters.freqPeriodLock = 1000; // Set the frequency/period to 1000Hz
timePulseParameters.pulseLenRatioLock = 0x80000000; // Set the pulse ratio to 1/2 * 2^32 to produce 50:50 mark:space
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
timePulseParameters.flags.bits.isFreq = 1; // Tell the module that we want to set the frequency (not the period)
timePulseParameters.flags.bits.isLength = 0; // Tell the module that pulseLenRatio is a ratio / duty cycle (* 2^-32) - not a length (in us)
timePulseParameters.flags.bits.polarity = 1; // Tell the module that we want the rising edge at the top of second. (Set to 0 for falling edge.)
// Now set the time pulse parameters
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("setTimePulseParameters failed!"));
}
else
{
Serial.println(F("Success!"));
}
}
void loop()
{
// Nothing to do here
}
@@ -0,0 +1,108 @@
/*
Time Pulse Parameters - Period
By: Paul Clark (PaulZC)
Date: January 13th, 2021
License: MIT. See license file for more information but you can
basically do whatever you want with this code.
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
pin to produce a 1 second pulse every 30 seconds. What's really cool is that if you run this
example on two GNSS boards, the pulses are precisely synchronised!
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
accurate timelapse camera shutter signal? This is the product for you!
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
NEO-M8P RTK: https://www.sparkfun.com/products/15005
SAM-M8Q: https://www.sparkfun.com/products/15106
Hardware Connections:
Plug a Qwiic cable into the GNSS and a BlackBoard
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
Open the serial monitor at 115200 baud to see the output
*/
#include <Wire.h> //Needed for I2C to GNSS
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
SFE_UBLOX_GNSS myGNSS;
void setup()
{
Serial.begin(115200);
while (!Serial)
; //Wait for user to open terminal
Serial.println(F("SparkFun u-blox Example"));
Wire.begin();
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
{
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
while (1)
;
}
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
// Create storage for the time pulse parameters
UBX_CFG_TP5_data_t timePulseParameters;
// Get the time pulse parameters
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("getTimePulseParameters failed! Freezing..."));
while (1) ; // Do nothing more
}
// Print the CFG TP5 version
Serial.print(F("UBX_CFG_TP5 version: "));
Serial.println(timePulseParameters.version);
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
// We can configure the time pulse pin to produce a defined frequency or period
// Here is how to set the period:
// Let's say that we want our 1 pulse every 30 seconds to be as accurate as possible. So, let's tell the module
// to generate no signal while it is _locking_ to GNSS time. We want the signal to start only when the module is
// _locked_ to GNSS time.
timePulseParameters.freqPeriod = 0; // Set the frequency/period to zero
timePulseParameters.pulseLenRatio = 0; // Set the pulse ratio to zero
// When the module is _locked_ to GNSS time, make it generate a 1 second pulse every 30 seconds
// (Although the period can be a maximum of 2^32 microseconds (over one hour), the upper limit appears to be around 33 seconds)
timePulseParameters.freqPeriodLock = 30000000; // Set the period to 30,000,000 us
timePulseParameters.pulseLenRatioLock = 1000000; // Set the pulse length to 1,000,000 us
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
timePulseParameters.flags.bits.isFreq = 0; // Tell the module that we want to set the period (not the frequency)
timePulseParameters.flags.bits.isLength = 1; // Tell the module that pulseLenRatio is a length (in us) - not a duty cycle
timePulseParameters.flags.bits.polarity = 1; // Tell the module that we want the rising edge at the top of second. (Set to 0 for falling edge.)
// Now set the time pulse parameters
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
{
Serial.println(F("setTimePulseParameters failed!"));
}
else
{
Serial.println(F("Success!"));
}
// Finally, save the time pulse parameters in battery-backed memory so the pulse will automatically restart at power on
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); // Save the configuration
}
void loop()
{
// Nothing to do here
}
+1 -1
View File
@@ -1,5 +1,5 @@
name=SparkFun u-blox GNSS Arduino Library
version=2.0.0
version=2.0.1
author=SparkFun Electronics <techsupport@sparkfun.com>
maintainer=SparkFun Electronics <sparkfun.com>
sentence=Library for I2C and Serial Communication with u-blox modules
@@ -4252,6 +4252,81 @@ boolean SFE_UBLOX_GNSS::resetIMUalignment(uint16_t maxWait)
return (sendCommand(&packetCfg, maxWait, true) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
}
//Get the time pulse parameters using UBX_CFG_TP5
boolean SFE_UBLOX_GNSS::getTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t maxWait)
{
if (data == NULL) // Check if the user forgot to include the data pointer
return (false); // Bail
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_TP5;
packetCfg.len = 0;
packetCfg.startingSpot = 0;
if (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
return (false);
// Extract the data
data->tpIdx = extractByte(&packetCfg, 0);
data->version = extractByte(&packetCfg, 1);
data->antCableDelay = extractSignedInt(&packetCfg, 4);
data->rfGroupDelay = extractSignedInt(&packetCfg, 6);
data->freqPeriod = extractLong(&packetCfg, 8);
data->freqPeriodLock = extractLong(&packetCfg, 12);
data->pulseLenRatio = extractLong(&packetCfg, 16);
data->pulseLenRatioLock = extractLong(&packetCfg, 20);
data->userConfigDelay = extractSignedLong(&packetCfg, 24);
data->flags.all = extractLong(&packetCfg, 28);
return(true);
}
//Set the time pulse parameters using UBX_CFG_TP5
boolean SFE_UBLOX_GNSS::setTimePulseParameters(UBX_CFG_TP5_data_t *data, uint16_t maxWait)
{
if (data == NULL) // Check if the user forgot to include the data pointer
return (false); // Bail
packetCfg.cls = UBX_CLASS_CFG;
packetCfg.id = UBX_CFG_TP5;
packetCfg.len = UBX_CFG_TP5_LEN;
packetCfg.startingSpot = 0;
// Insert the data
payloadCfg[0] = data->tpIdx;
payloadCfg[1] = data->version;
payloadCfg[4] = data->antCableDelay & 0xFF; // Little Endian
payloadCfg[5] = data->antCableDelay >> 8;
payloadCfg[6] = data->rfGroupDelay & 0xFF; // Little Endian
payloadCfg[7] = data->rfGroupDelay >> 8;
payloadCfg[8] = data->freqPeriod & 0xFF; // Little Endian
payloadCfg[9] = (data->freqPeriod >> 8) & 0xFF;
payloadCfg[10] = (data->freqPeriod >> 16) & 0xFF;
payloadCfg[11] = (data->freqPeriod >> 24) & 0xFF;
payloadCfg[12] = data->freqPeriodLock & 0xFF; // Little Endian
payloadCfg[13] = (data->freqPeriodLock >> 8) & 0xFF;
payloadCfg[14] = (data->freqPeriodLock >> 16) & 0xFF;
payloadCfg[15] = (data->freqPeriodLock >> 24) & 0xFF;
payloadCfg[16] = data->pulseLenRatio & 0xFF; // Little Endian
payloadCfg[17] = (data->pulseLenRatio >> 8) & 0xFF;
payloadCfg[18] = (data->pulseLenRatio >> 16) & 0xFF;
payloadCfg[19] = (data->pulseLenRatio >> 24) & 0xFF;
payloadCfg[20] = data->pulseLenRatioLock & 0xFF; // Little Endian
payloadCfg[21] = (data->pulseLenRatioLock >> 8) & 0xFF;
payloadCfg[22] = (data->pulseLenRatioLock >> 16) & 0xFF;
payloadCfg[23] = (data->pulseLenRatioLock >> 24) & 0xFF;
payloadCfg[24] = data->userConfigDelay & 0xFF; // Little Endian
payloadCfg[25] = (data->userConfigDelay >> 8) & 0xFF;
payloadCfg[26] = (data->userConfigDelay >> 16) & 0xFF;
payloadCfg[27] = (data->userConfigDelay >> 24) & 0xFF;
payloadCfg[28] = data->flags.all & 0xFF; // Little Endian
payloadCfg[29] = (data->flags.all >> 8) & 0xFF;
payloadCfg[30] = (data->flags.all >> 16) & 0xFF;
payloadCfg[31] = (data->flags.all >> 24) & 0xFF;
return (sendCommand(&packetCfg, maxWait) == SFE_UBLOX_STATUS_DATA_SENT); // We are only expecting an ACK
}
// CONFIGURATION INTERFACE (protocol v27 and above)
//Form 32-bit key from group/id/size
@@ -645,6 +645,10 @@ public:
//Reset ESF automatic IMU-mount alignment
boolean resetIMUalignment(uint16_t maxWait = defaultMaxWait);
//Configure Time Pulse Parameters
boolean getTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Get the time pulse parameters using UBX_CFG_TP5
boolean setTimePulseParameters(UBX_CFG_TP5_data_t *data = NULL, uint16_t maxWait = defaultMaxWait); // Set the time pulse parameters using UBX_CFG_TP5
//General configuration (used only on protocol v27 and higher - ie, ZED-F9P)
//It is probably safe to assume that users of the ZED-F9P will be using I2C / Qwiic.
+35
View File
@@ -1789,4 +1789,39 @@ typedef struct
UBX_HNR_INS_data_t *callbackData;
} UBX_HNR_INS_t;
// UBX-CFG-TP5 (0x06 0x31): Time pulse parameters
const uint16_t UBX_CFG_TP5_LEN = 32;
typedef struct
{
uint8_t tpIdx; // Time pulse selection (0 = TIMEPULSE, 1 = TIMEPULSE2)
uint8_t version; // Message version (0x01 for this version)
uint8_t reserved1[2];
int16_t antCableDelay; // Antenna cable delay: ns
int16_t rfGroupDelay; // RF group delay: ns
uint32_t freqPeriod; // Frequency or period time, depending on setting of bit 'isFreq': Hz_or_us
uint32_t freqPeriodLock; // Frequency or period time when locked to GNSS time, only used if 'lockedOtherSet' is set: Hz_or_us
uint32_t pulseLenRatio; // Pulse length or duty cycle, depending on 'isLength': us_or_2^-32
uint32_t pulseLenRatioLock; // Pulse length or duty cycle when locked to GNSS time, only used if 'lockedOtherSet' is set: us_or_2^-32
int32_t userConfigDelay; // User-configurable time pulse delay: ns
union
{
uint32_t all;
struct
{
uint32_t active : 1; // If set enable time pulse; if pin assigned to another function, other function takes precedence.
uint32_t lockGnssFreq : 1; // If set, synchronize time pulse to GNSS as soon as GNSS time is valid. If not set, or before GNSS time is valid, use local clock.
uint32_t lockedOtherSet : 1; // If set the receiver switches between the timepulse settings given by 'freqPeriodLocked' & 'pulseLenLocked' and those given by 'freqPeriod' & 'pulseLen'.
uint32_t isFreq : 1; // If set 'freqPeriodLock' and 'freqPeriod' are interpreted as frequency, otherwise interpreted as period.
uint32_t isLength : 1; // If set 'pulseLenRatioLock' and 'pulseLenRatio' interpreted as pulse length, otherwise interpreted as duty cycle.
uint32_t alignToTow : 1; // Align pulse to top of second (period time must be integer fraction of 1s). Also set 'lockGnssFreq' to use this feature.
uint32_t polarity : 1; // Pulse polarity: 0: falling edge at top of second; 1: rising edge at top of second
uint32_t gridUtcGnss : 4; // Timegrid to use: 0: UTC; 1: GPS; 2: GLONASS; 3: BeiDou; 4: Galileo
uint32_t syncMode : 3; // Sync Manager lock mode to use:
// 0: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, never switch back to 'freqPeriod' and 'pulseLenRatio'
// 1: switch to 'freqPeriodLock' and 'pulseLenRatioLock' as soon as Sync Manager has an accurate time, and switch back to 'freqPeriod' and 'pulseLenRatio' as soon as time gets inaccurate
} bits;
} flags;
} UBX_CFG_TP5_data_t;
#endif