-
Notifications
You must be signed in to change notification settings - Fork 5
Added initial gps logger functionalities #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
avfonseca
wants to merge
8
commits into
CCOMJHC:main
Choose a base branch
from
avfonseca:ZED_RTK
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
cd366b7
Added initial gps logger functionalities
af737bb
Did not commit header file changes
cfe5cba
Added calibration function
d4f4b47
Added error control, chose available raw values for RINEX post proces…
b6e4e2d
Cleaned up error handling
6e11d68
Added gps_cal as an available command
739b582
Forced IMU to be disabled until further testing
19c6e96
Forced IMU to be disabled until further testing[A
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
#include "GPSLogger.h" | ||
#include "serialisation.h" | ||
#include "LogManager.h" | ||
#include "Wire.h" | ||
|
||
namespace gps { | ||
|
||
Logger::Logger(logger::Manager *logManager) | ||
: m_logManager(logManager), m_verbose(false), m_isCalibrating(false) | ||
{ | ||
m_sensor = new SFE_UBLOX_GNSS(); | ||
} | ||
|
||
Logger::~Logger(void) | ||
{ | ||
delete m_sensor; | ||
} | ||
|
||
bool Logger::begin(void) | ||
{ | ||
// Configure I2C pins for GPS | ||
Wire.begin(33, 36); // SDA, SCL | ||
Wire.setClock(I2C_CLOCK_SPEED); // Set I2C clock to 400kHz for faster data transfer | ||
Wire.setBufferSize(I2C_BUFFER_SIZE); // Increase buffer size for larger RAWX messages | ||
|
||
if (!m_sensor->begin(Wire)) { | ||
Serial.println("Failed to initialize ZED-F9P GPS"); | ||
return false; | ||
} | ||
|
||
// Set larger internal buffer for u-blox library | ||
m_sensor->setPacketCfgPayloadSize(I2C_BUFFER_SIZE); | ||
|
||
configureDevice(); | ||
return true; | ||
} | ||
|
||
void Logger::configureDevice(void) | ||
{ | ||
// Configure GPS settings | ||
m_sensor->setI2COutput(COM_TYPE_UBX); // Set the I2C port to output UBX only | ||
m_sensor->setNavigationFrequency(5); // Set output rate to 5 Hz | ||
m_sensor->setAutoPVT(true); // Enable automatic PVT messages | ||
m_sensor->setDynamicModel(DYN_MODEL_MARINE); // Set dynamic model for marine applications | ||
|
||
// Enable messages needed for RINEX post-processing with optimized rates | ||
m_sensor->enableMessage(UBX_NAV_PVT, COM_PORT_I2C, 1); // Position, Velocity, Time (1Hz) | ||
m_sensor->enableMessage(UBX_NAV_HPPOSLLH, COM_PORT_I2C, 1); // High Precision Position (1Hz) | ||
m_sensor->enableMessage(UBX_NAV_TIMEUTC, COM_PORT_I2C, 1); // UTC Time Solution (1Hz) | ||
m_sensor->enableMessage(UBX_RXM_RAWX, COM_PORT_I2C, 1); // Raw GNSS Measurements (1Hz) | ||
|
||
// Configure additional settings for better data quality | ||
m_sensor->setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP); // Set GPS as main constellation | ||
m_sensor->setHighPrecisionMode(true); // Enable high precision mode | ||
|
||
// Save configuration | ||
m_sensor->saveConfiguration(); | ||
} | ||
|
||
bool Logger::data_available(void) | ||
{ | ||
return m_sensor->getPVT(); | ||
} | ||
|
||
void Logger::update(void) | ||
{ | ||
static uint32_t lastI2CReset = 0; | ||
|
||
if (data_available()) { | ||
if (!logGPSData() && Wire.getErrorCode() != 0) { | ||
// Only reset I2C every 5 seconds at most | ||
if (millis() - lastI2CReset > 5000) { | ||
Serial.println("I2C error detected, resetting bus..."); | ||
Wire.flush(); | ||
Wire.begin(33, 36); | ||
Wire.setClock(I2C_CLOCK_SPEED); | ||
lastI2CReset = millis(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
bool Logger::logGPSData(void) | ||
{ | ||
if (m_logManager == nullptr) return false; | ||
|
||
// Create JSON document for logging | ||
StaticJsonDocument<2048> doc; // Further increased size for reliability | ||
|
||
doc["type"] = "GPS"; | ||
|
||
// Standard PVT data | ||
doc["lat"] = m_sensor->getLatitude() / 10000000.0; | ||
doc["lon"] = m_sensor->getLongitude() / 10000000.0; | ||
doc["alt"] = m_sensor->getAltitude() / 1000.0; | ||
doc["fix"] = m_sensor->getFixType(); | ||
doc["siv"] = m_sensor->getSIV(); | ||
doc["acc_h"] = m_sensor->getHorizontalAccuracy() / 1000.0; | ||
doc["acc_v"] = m_sensor->getVerticalAccuracy() / 1000.0; | ||
|
||
// High precision position data | ||
if (m_sensor->getHPPOSLLH()) { | ||
doc["hp_lat"] = m_sensor->getHighResLatitude(); | ||
doc["hp_lon"] = m_sensor->getHighResLongitude(); | ||
doc["hp_alt"] = m_sensor->getHighResAltitude(); | ||
} | ||
|
||
// UTC Time data | ||
if (m_sensor->getNAVTIMEUTC()) { | ||
doc["utc_year"] = m_sensor->getYear(); | ||
doc["utc_month"] = m_sensor->getMonth(); | ||
doc["utc_day"] = m_sensor->getDay(); | ||
doc["utc_hour"] = m_sensor->getHour(); | ||
doc["utc_min"] = m_sensor->getMinute(); | ||
doc["utc_sec"] = m_sensor->getSecond(); | ||
doc["utc_nano"] = m_sensor->getNano(); | ||
} | ||
|
||
// Raw measurement data (for RINEX) | ||
if (m_sensor->getRXMRAWX()) { | ||
JsonArray rawx = doc.createNestedArray("rawx"); | ||
for (int i = 0; i < m_sensor->getNumRXMRAWXmessages(); i++) { | ||
JsonObject meas = rawx.createNestedObject(); | ||
meas["pr"] = m_sensor->getRXMRAWXPseudorange(i); | ||
meas["cp"] = m_sensor->getRXMRAWXCarrierPhase(i); | ||
meas["do"] = m_sensor->getRXMRAWXDoppler(i); | ||
meas["gnss"] = m_sensor->getRXMRAWXGNSSId(i); | ||
meas["sv"] = m_sensor->getRXMRAWXSvId(i); | ||
meas["cno"] = m_sensor->getRXMRAWXCNo(i); | ||
} | ||
} | ||
|
||
try { | ||
String output; | ||
serializeJson(doc, output); | ||
return m_logManager->LogData(output.c_str()); | ||
} catch (const std::exception& e) { | ||
Serial.printf("Error serializing GPS data: %s\n", e.what()); | ||
return false; | ||
} | ||
} | ||
|
||
bool Logger::runCalibration(void) | ||
{ | ||
if (m_isCalibrating) return false; | ||
|
||
m_isCalibrating = true; | ||
configureCalibration(); | ||
|
||
// Log calibration start | ||
if (m_logManager != nullptr) { | ||
StaticJsonDocument<256> doc; | ||
doc["type"] = "GPS_CAL"; | ||
doc["event"] = "start"; | ||
|
||
String output; | ||
serializeJson(doc, output); | ||
m_logManager->LogData(output.c_str()); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void Logger::configureCalibration(void) | ||
{ | ||
// Set high precision mode | ||
m_sensor->setAutoPVT(false); | ||
m_sensor->setNavigationFrequency(1); // Reduce to 1Hz during calibration | ||
|
||
// Enable Raw Measurements | ||
m_sensor->enableMeasurement(UBX_RXM_RAWX, true); | ||
m_sensor->enableMeasurement(UBX_RXM_SFRBX, true); | ||
|
||
// Configure Survey-In Mode | ||
m_sensor->enableSurveyMode(300, 2.0); // 300 seconds minimum, 2.0m precision | ||
|
||
// Save the calibration configuration | ||
m_sensor->saveConfiguration(); | ||
} | ||
|
||
bool Logger::isCalibrating(void) | ||
{ | ||
if (!m_isCalibrating) return false; | ||
|
||
bool surveying = m_sensor->getSurveyInActive(); | ||
bool valid = m_sensor->getSurveyInValid(); | ||
|
||
if (!surveying && valid) { | ||
// Calibration completed successfully | ||
stopCalibration(); | ||
return false; | ||
} | ||
|
||
// Log current calibration status | ||
if (m_logManager != nullptr) { | ||
StaticJsonDocument<256> doc; | ||
doc["type"] = "GPS_CAL"; | ||
doc["event"] = "progress"; | ||
doc["observations"] = m_sensor->getSurveyInObservationTime(); | ||
doc["mean_accuracy"] = m_sensor->getSurveyInMeanAccuracy(); | ||
|
||
String output; | ||
serializeJson(doc, output); | ||
m_logManager->LogData(output.c_str()); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void Logger::stopCalibration(void) | ||
{ | ||
if (!m_isCalibrating) return; | ||
|
||
// Disable Survey-In Mode | ||
m_sensor->disableSurveyMode(); | ||
|
||
// Restore normal operation settings | ||
configureDevice(); | ||
|
||
m_isCalibrating = false; | ||
|
||
// Log calibration completion | ||
if (m_logManager != nullptr) { | ||
StaticJsonDocument<256> doc; | ||
doc["type"] = "GPS_CAL"; | ||
doc["event"] = "complete"; | ||
doc["valid"] = m_sensor->getSurveyInValid(); | ||
doc["total_time"] = m_sensor->getSurveyInObservationTime(); | ||
doc["final_accuracy"] = m_sensor->getSurveyInMeanAccuracy(); | ||
|
||
String output; | ||
serializeJson(doc, output); | ||
m_logManager->LogData(output.c_str()); | ||
} | ||
} | ||
|
||
} // namespace gps |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#ifndef __GPS_LOGGER_H__ | ||
#define __GPS_LOGGER_H__ | ||
|
||
#include <Arduino.h> | ||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> | ||
#include "LogManager.h" | ||
|
||
namespace gps { | ||
|
||
class Logger { | ||
public: | ||
Logger(logger::Manager *logManager); | ||
~Logger(void); | ||
|
||
bool begin(void); | ||
void update(void); | ||
bool data_available(void); | ||
bool runCalibration(void); | ||
bool isCalibrating(void); | ||
void stopCalibration(void); | ||
|
||
private: | ||
SFE_UBLOX_GNSS *m_sensor; | ||
logger::Manager *m_logManager; | ||
bool m_isCalibrating; | ||
static const uint32_t I2C_BUFFER_SIZE = 2048; | ||
static const uint32_t I2C_CLOCK_SPEED = 400000; | ||
|
||
void configureDevice(void); | ||
bool logGPSData(void); | ||
void configureCalibration(void); | ||
}; | ||
|
||
} // namespace gps | ||
|
||
#endif // __GPS_LOGGER_H__ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Add to the private section | ||
private: | ||
void HandleGPSCalibration(void); // New command handler |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,9 +39,10 @@ | |
#include "SupplyMonitor.h" | ||
#include "Configuration.h" | ||
#include "HeapMonitor.h" | ||
#include "GPSLogger.h" | ||
|
||
/// Hardware version for the logger implementation (for NMEA2000 declaration) | ||
#define LOGGER_HARDWARE_VERSION "2.4.1" | ||
#define LOGGER_HARDWARE_VERSION "2.6.0" | ||
|
||
const unsigned long TransmitMessages[] PROGMEM={0}; ///< List of messages the logger transmits (null set) | ||
const unsigned long ReceiveMessages[] PROGMEM = | ||
|
@@ -66,6 +67,7 @@ StatusLED *LEDs = nullptr; ///< Pointer to the status L | |
SerialCommand *CommandProcessor = nullptr;///< Pointer for the command processor object | ||
mem::MemController *memController = nullptr; ///< Pointer for the storage abstraction | ||
logger::SupplyMonitor *supplyMonitor = nullptr; ///< Pointer for the supply voltage monitoring code | ||
gps::Logger *GPSLogger = nullptr; ///< Pointer for the GPS data logger | ||
|
||
/// \brief Primary setup code for the logger | ||
/// | ||
|
@@ -204,6 +206,13 @@ void setup() | |
|
||
Serial.printf("DBG: After voltage monitoring start, free heap = %d B, delta = %d B\n", heap.CurrentSize(), heap.DeltaSinceLast()); | ||
|
||
Serial.println("Starting GPS logger ..."); | ||
GPSLogger = new gps::Logger(logManager); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll want this to be optional so that we don't have to turn it on if the hardware isn't there (or the user isn't interested). Similar code is used for IMU, etc. |
||
if (!GPSLogger->begin()) { | ||
Serial.println("Failed to initialize GPS logger"); | ||
LEDs->SetStatus(StatusLED::Status::sERROR); | ||
} | ||
|
||
Serial.println("Setup complete, setting status for normal operations."); | ||
LEDs->SetStatus(StatusLED::Status::sNORMAL); | ||
|
||
|
@@ -242,4 +251,7 @@ void loop() | |
//Serial.printf("DBG: Supply voltage ADC dropped to %hu\n", supply_voltage); | ||
CommandProcessor->EmergencyStop(); | ||
} | ||
if (GPSLogger != nullptr) { | ||
GPSLogger->update(); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is also used by the IMU, we'll have to check that re-initialising this isn't going to cause problems (or vice versa if the IMU is also enabled).