Compare commits

...

12 commits

Author SHA1 Message Date
brentru
6b90085793 CI - Resolve file name error
Some checks failed
Arduino Library CI / build (push) Has been cancelled
2025-07-30 13:05:29 -04:00
brentru
57c7b6cb03 CI - Resolve warnings, attempt to fix error for examples/ublox_ddc/ublox_dcc.ino 2025-07-30 13:01:16 -04:00
brentru
8081d05d6f Move example/ files to folders 2025-07-30 12:55:45 -04:00
Brent Rubell
2ffb9de69b
Merge pull request #2 from brentru/fix-default-arg-bug
Fixes Default Parameter Bug
2025-07-22 14:53:09 -04:00
brentru
0ca6e789eb Fixes a bug with default arg in one func 2025-07-22 12:22:41 -04:00
Brent Rubell
c885a346fc
Merge pull request #1 from brentru/release-init
Add Files for Future Release
2025-07-22 10:28:03 -04:00
brentru
431d1a98b7 chunksz 2025-07-21 11:55:56 -04:00
brentru
e369e88efe fix CI 2025-07-21 11:51:19 -04:00
brentru
739f2be25a add parse 2025-07-21 11:49:41 -04:00
brentru
569ff1495e doxygen and clang 2025-07-21 11:13:53 -04:00
brentru
5eb550766a Clang 2025-07-21 10:52:34 -04:00
brentru
8f6b59b218 pre-doxy/clang changes 2025-07-21 10:48:46 -04:00
16 changed files with 1099 additions and 438 deletions

46
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

26
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

32
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino
path: ci
- name: Install the prerequisites
run: bash ci/actions_install.sh
- name: Check for correct code formatting with clang-format
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: Check for correct documentation with doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit uBlox Library"
run: bash ci/doxy_gen_and_deploy.sh
- name: Test the code on supported platforms
run: python3 ci/build_platform.py main_platforms

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
# Our handy .gitignore for automation ease
Doxyfile*
doxygen_sqlite3.db
html

View file

@ -5,15 +5,16 @@
*
* @section intro_sec Introduction
*
* This is a library for parsing UBX protocol messages from u-blox GPS/RTK modules.
* It works with any Stream-based interface including UART and DDC (I2C).
* This is a library for parsing UBX protocol messages from u-blox GPS/RTK
* modules. It works with any Stream-based interface including UART and DDC
* (I2C).
*
* Designed specifically to work with u-blox GPS/RTK modules
* like NEO-M8P, ZED-F9P, etc.
*
* @section author Author
*
* Written by Your Name for Project Name.
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* @section license License
*
@ -22,17 +23,24 @@
#include "Adafruit_UBX.h"
/*!
* @brief Constructor
* @param stream Reference to a Stream object (Serial, Adafruit_UBloxDDC, etc.)
* @param stream Reference to a Stream object (Serial, Adafruit_UBloxDDC,
* etc.)
*/
Adafruit_UBX::Adafruit_UBX(Stream &stream) {
_stream = &stream;
onUBXMessage = NULL;
}
/*!
* @brief Destructor
*/
Adafruit_UBX::~Adafruit_UBX() {
if (onUBXMessage)
onUBXMessage = NULL;
}
/*!
* @brief Initializes the UBX parser
* @return Always returns true (initialization is trivial)
@ -42,9 +50,6 @@ bool Adafruit_UBX::begin() {
return true;
}
/*!
* @brief Configure the GPS module to output only UBX protocol (disables NMEA)
* @param portID Port identifier (UBX_PORT_DDC, UBX_PORT_UART1, etc.)
@ -52,7 +57,8 @@ bool Adafruit_UBX::begin() {
* @param timeout_ms Maximum time to wait for acknowledgment in milliseconds
* @return UBXSendStatus indicating success, failure, or timeout
*/
UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck, uint16_t timeout_ms) {
UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck,
uint16_t timeout_ms) {
UBX_CFG_PRT_t cfgPrt;
// Zero out the structure
@ -103,7 +109,8 @@ UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck, uint16_t
// Send the message and wait for acknowledgment if requested
if (checkAck) {
return sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw, sizeof(cfgPrt), timeout_ms);
return sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw,
sizeof(cfgPrt), timeout_ms);
} else {
if (sendMessage(UBX_CLASS_CFG, UBX_CFG_PRT, cfgPrt.raw, sizeof(cfgPrt))) {
return UBX_SEND_SUCCESS;
@ -113,12 +120,10 @@ UBXSendStatus Adafruit_UBX::setUBXOnly(UBXPortId portID, bool checkAck, uint16_t
}
}
/*!
* @brief Sets the callback function for UBX messages
* @param callback Function pointer to call when a complete UBX message is received
* @param callback Function pointer to call when a complete UBX message is
* received
*/
void Adafruit_UBX::setMessageCallback(UBXMessageCallback callback) {
onUBXMessage = callback;
@ -140,7 +145,8 @@ void Adafruit_UBX::resetParser() {
* @param checksumA Reference to store the first checksum byte
* @param checksumB Reference to store the second checksum byte
*/
void Adafruit_UBX::calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA, uint8_t &checksumB) {
void Adafruit_UBX::calculateChecksum(uint8_t *buffer, uint16_t len,
uint8_t &checksumA, uint8_t &checksumB) {
checksumA = 0;
checksumB = 0;
@ -222,7 +228,8 @@ bool Adafruit_UBX::checkMessages() {
case GET_CHECKSUM_A:
// Calculate expected checksum
calculateChecksum(_buffer + 2, _payloadLength + 4, _checksumA, _checksumB);
calculateChecksum(_buffer + 2, _payloadLength + 4, _checksumA,
_checksumB);
if (incomingByte == _checksumA) {
_parserState = GET_CHECKSUM_B; // Checksum A matches
@ -235,7 +242,8 @@ bool Adafruit_UBX::checkMessages() {
if (incomingByte == _checksumB) {
// We have a valid message!
if (onUBXMessage != NULL) {
onUBXMessage(_msgClass, _msgId, _payloadLength, _buffer + 6); // Call the callback with the message
onUBXMessage(_msgClass, _msgId, _payloadLength,
_buffer + 6); // Call the callback with the message
}
messageReceived = true;
@ -253,19 +261,23 @@ bool Adafruit_UBX::checkMessages() {
// Print header (sync chars, class, id, length)
Serial.print("HDR[B5 62 ");
if (_msgClass < 0x10) Serial.print("0");
if (_msgClass < 0x10)
Serial.print("0");
Serial.print(_msgClass, HEX);
Serial.print(" ");
if (_msgId < 0x10) Serial.print("0");
if (_msgId < 0x10)
Serial.print("0");
Serial.print(_msgId, HEX);
Serial.print(" ");
uint8_t lenLSB = _payloadLength & 0xFF;
uint8_t lenMSB = (_payloadLength >> 8) & 0xFF;
if (lenLSB < 0x10) Serial.print("0");
if (lenLSB < 0x10)
Serial.print("0");
Serial.print(lenLSB, HEX);
Serial.print(" ");
if (lenMSB < 0x10) Serial.print("0");
if (lenMSB < 0x10)
Serial.print("0");
Serial.print(lenMSB, HEX);
Serial.print("] ");
@ -273,7 +285,8 @@ bool Adafruit_UBX::checkMessages() {
if (verbose_debug > 1 && _payloadLength > 0) {
Serial.print("PL[");
for (uint16_t i = 0; i < _payloadLength; i++) {
if (_buffer[6 + i] < 0x10) Serial.print("0");
if (_buffer[6 + i] < 0x10)
Serial.print("0");
Serial.print(_buffer[6 + i], HEX);
Serial.print(" ");
}
@ -282,10 +295,12 @@ bool Adafruit_UBX::checkMessages() {
// Print checksum
Serial.print("CS[");
if (_checksumA < 0x10) Serial.print("0");
if (_checksumA < 0x10)
Serial.print("0");
Serial.print(_checksumA, HEX);
Serial.print(" ");
if (_checksumB < 0x10) Serial.print("0");
if (_checksumB < 0x10)
Serial.print("0");
Serial.print(_checksumB, HEX);
Serial.println("]");
}
@ -299,7 +314,6 @@ bool Adafruit_UBX::checkMessages() {
return messageReceived;
}
/*!
* @brief Send a UBX message and wait for acknowledgment
* @param msgClass Message class
@ -309,7 +323,10 @@ bool Adafruit_UBX::checkMessages() {
* @param timeout_ms Maximum time to wait for acknowledgment
* @return UBXSendStatus indicating success, failure, or timeout
*/
UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length, uint16_t timeout_ms = 500) {
UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
uint8_t *payload,
uint16_t length,
uint16_t timeout_ms) {
// First send the message
if (!sendMessage(msgClass, msgId, payload, length)) {
if (verbose_debug > 0) {
@ -332,10 +349,12 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) {
if (verbose_debug > 0) {
Serial.print(F("UBX ACK: SUCCESS for message class 0x"));
if (msgClass < 0x10) Serial.print("0");
if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX);
Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0");
if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX);
}
return UBX_SEND_SUCCESS;
@ -345,10 +364,12 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
if (_lastPayload[0] == msgClass && _lastPayload[1] == msgId) {
if (verbose_debug > 0) {
Serial.print(F("UBX ACK: NAK for message class 0x"));
if (msgClass < 0x10) Serial.print("0");
if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX);
Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0");
if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX);
}
return UBX_SEND_NAK;
@ -362,28 +383,33 @@ UBXSendStatus Adafruit_UBX::sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
}
if (verbose_debug > 0) {
Serial.print(F("UBX ACK: TIMEOUT waiting for ACK/NAK for message class 0x"));
if (msgClass < 0x10) Serial.print("0");
Serial.print(
F("UBX ACK: TIMEOUT waiting for ACK/NAK for message class 0x"));
if (msgClass < 0x10)
Serial.print("0");
Serial.print(msgClass, HEX);
Serial.print(" ID 0x");
if (msgId < 0x10) Serial.print("0");
if (msgId < 0x10)
Serial.print("0");
Serial.println(msgId, HEX);
}
return UBX_SEND_TIMEOUT;
}
/*!
* @brief Send a UBX message to the GPS module
* @param msgClass Message class
* @param msgId Message ID
* @param payload Pointer to the payload data (can be NULL for zero-length payload)
* @param payload Pointer to the payload data (can be NULL for zero-length
* payload)
* @param length Length of payload
* @return True if message was sent successfully
*/
bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length) {
// Buffer for message (2 sync chars + class + id + 2 length bytes + payload + 2 checksum bytes)
bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId,
uint8_t *payload, uint16_t length) {
// Buffer for message (2 sync chars + class + id + 2 length bytes + payload +
// 2 checksum bytes)
uint8_t msgBuffer[length + 8];
// Sync characters
@ -417,7 +443,8 @@ bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload
// Print header (sync chars, class, id, length)
Serial.print("HDR[");
for (int i = 0; i < 6; i++) {
if (msgBuffer[i] < 0x10) Serial.print("0");
if (msgBuffer[i] < 0x10)
Serial.print("0");
Serial.print(msgBuffer[i], HEX);
Serial.print(" ");
}
@ -427,7 +454,8 @@ bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload
if (verbose_debug > 1 && length > 0) {
Serial.print("PL[");
for (uint16_t i = 0; i < length; i++) {
if (msgBuffer[6 + i] < 0x10) Serial.print("0");
if (msgBuffer[6 + i] < 0x10)
Serial.print("0");
Serial.print(msgBuffer[6 + i], HEX);
Serial.print(" ");
}
@ -436,10 +464,12 @@ bool Adafruit_UBX::sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload
// Print checksum
Serial.print("CS[");
if (checksumA < 0x10) Serial.print("0");
if (checksumA < 0x10)
Serial.print("0");
Serial.print(checksumA, HEX);
Serial.print(" ");
if (checksumB < 0x10) Serial.print("0");
if (checksumB < 0x10)
Serial.print("0");
Serial.print(checksumB, HEX);
Serial.println("]");
}

View file

@ -9,7 +9,7 @@
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Your Name for Project Name.
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*/
@ -17,49 +17,60 @@
#ifndef ADAFRUIT_UBX_H
#define ADAFRUIT_UBX_H
#include "Adafruit_uBlox_Ubx_Messages.h"
#include "Adafruit_uBlox_typedef.h"
#include <Arduino.h>
#include <Stream.h>
#include "Adafruit_uBlox_typedef.h"
// UBX protocol constants
#define UBX_SYNC_CHAR_1 0xB5 // First UBX protocol sync char (µ)
#define UBX_SYNC_CHAR_2 0x62 // Second UBX protocol sync char (b)
#define UBX_SYNC_CHAR_1 0xB5 ///< First UBX protocol sync char (<28>)
#define UBX_SYNC_CHAR_2 0x62 ///< Second UBX protocol sync char (b)
// UBX ACK Message IDs
#define UBX_ACK_NAK 0x00 // Message Not Acknowledged
#define UBX_ACK_ACK 0x01 // Message Acknowledged
// Callback function type for UBX messages - defined at global scope so other classes can use it
typedef void (*UBXMessageCallback)(uint8_t msgClass, uint8_t msgId, uint16_t payloadLen, uint8_t *payload);
#define UBX_ACK_NAK 0x00 ///< Message Not Acknowledged
#define UBX_ACK_ACK 0x01 ///< Message Acknowledged
/*!
* @brief Callback function type for UBX messages - defined at global scope so
* other classes can use it
* @param msgClass Message class
* @param msgId Message ID
* @param payloadLen Length of payload data
* @param payload Pointer to payload data
*/
typedef void (*UBXMessageCallback)(uint8_t msgClass, uint8_t msgId,
uint16_t payloadLen, uint8_t *payload);
/*!
* @brief Class for parsing UBX protocol messages from u-blox GPS/RTK modules
*/
class Adafruit_UBX {
public:
// Constructor
public:
Adafruit_UBX(Stream &stream);
uint8_t verbose_debug = 0; // 0=off, 1=basic, 2=verbose
~Adafruit_UBX();
uint8_t verbose_debug = 0; ///< 0=off, 1=basic, 2=verbose
// Basic methods
bool begin();
bool checkMessages(); // Message parsing
bool sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length); // Send a UBX message
UBXSendStatus sendMessageWithAck(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t length, uint16_t timeout_ms = 500);
bool sendMessage(uint8_t msgClass, uint8_t msgId, uint8_t *payload,
uint16_t length); // Send a UBX message
UBXSendStatus sendMessageWithAck(uint8_t msgClass, uint8_t msgId,
uint8_t *payload, uint16_t length,
uint16_t timeout_ms = 500);
// Configure port to use UBX protocol only (disable NMEA)
UBXSendStatus setUBXOnly(UBXPortId portID, bool checkAck = true, uint16_t timeout_ms = 500);
UBXSendStatus setUBXOnly(UBXPortId portID, bool checkAck = true,
uint16_t timeout_ms = 500);
void setMessageCallback(UBXMessageCallback callback); // Set callback function
UBXMessageCallback onUBXMessage; // Callback for message received
UBXMessageCallback onUBXMessage; ///< Callback for message received
private:
private:
Stream *_stream; // Stream interface for reading data
// Buffer for reading messages
static const uint16_t MAX_PAYLOAD_SIZE = 64; // Maximum UBX payload size
uint8_t _buffer[MAX_PAYLOAD_SIZE + 8]; // Buffer for message (header, payload, checksum)
uint8_t _buffer[MAX_PAYLOAD_SIZE +
8]; // Buffer for message (header, payload, checksum)
// Parser state machine
enum ParserState {
@ -83,7 +94,8 @@ class Adafruit_UBX {
uint8_t _checksumB; // Running checksum B
// Calculate checksum for a block of data
void calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA, uint8_t &checksumB);
void calculateChecksum(uint8_t *buffer, uint16_t len, uint8_t &checksumA,
uint8_t &checksumB);
// Reset parser state
void resetParser();

View file

@ -1,25 +1,23 @@
/*!
* @file Adafruit_UBloxDDC.cpp
*
* @mainpage Arduino library for u-blox GPS/RTK modules over DDC (I2C)
*
* @section intro_sec Introduction
* @section ddc_intro_sec Introduction
*
* This is a library for the u-blox GPS/RTK modules using I2C interface (DDC)
*
* Designed specifically to work with u-blox GPS/RTK modules
* like NEO-M8P, ZED-F9P, etc.
*
* @section dependencies Dependencies
* @section ddc_dependencies Dependencies
*
* This library depends on:
* <a href="https://github.com/adafruit/Adafruit_BusIO">Adafruit_BusIO</a>
*
* @section author Author
* @section ddc_author Author
*
* Written by Your Name for Project Name.
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* @section license License
* @section ddc_license License
*
* MIT license, all text above must be included in any redistribution
*/
@ -50,9 +48,7 @@ Adafruit_UBloxDDC::~Adafruit_UBloxDDC() {
* @brief Initializes the GPS module and I2C interface
* @return True if GPS module responds, false on any failure
*/
bool Adafruit_UBloxDDC::begin() {
return _i2cDevice->begin();
}
bool Adafruit_UBloxDDC::begin() { return _i2cDevice->begin(); }
/*!
* @brief Gets the number of bytes available for reading
@ -62,7 +58,8 @@ int Adafruit_UBloxDDC::available() {
uint8_t buffer[2];
// Create a register for reading bytes available
Adafruit_BusIO_Register bytesAvailableReg = Adafruit_BusIO_Register(_i2cDevice, REG_BYTES_AVAILABLE_MSB, 2);
Adafruit_BusIO_Register bytesAvailableReg =
Adafruit_BusIO_Register(_i2cDevice, REG_BYTES_AVAILABLE_MSB, 2);
if (!bytesAvailableReg.read(buffer, 2)) {
return 0;
@ -88,7 +85,8 @@ int Adafruit_UBloxDDC::read() {
uint8_t value;
// Create a register for the data stream
Adafruit_BusIO_Register dataStreamReg = Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
Adafruit_BusIO_Register dataStreamReg =
Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
if (!dataStreamReg.read(&value, 1)) {
return -1;
@ -153,7 +151,7 @@ size_t Adafruit_UBloxDDC::write(const uint8_t *buffer, size_t size) {
* @param length Maximum number of bytes to read
* @return Number of bytes actually read, which may be less than requested
*/
uint16_t Adafruit_UBloxDDC::readBytes(uint8_t* buffer, uint16_t length) {
uint16_t Adafruit_UBloxDDC::readBytes(uint8_t *buffer, uint16_t length) {
if (buffer == nullptr || length == 0) {
return 0;
}
@ -176,11 +174,12 @@ uint16_t Adafruit_UBloxDDC::readBytes(uint8_t* buffer, uint16_t length) {
}
// Create a register for the data stream
Adafruit_BusIO_Register dataStreamReg = Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
Adafruit_BusIO_Register dataStreamReg =
Adafruit_BusIO_Register(_i2cDevice, REG_DATA_STREAM, 1);
while (bytesRead < length) {
// Calculate chunk size (I2C has a limit on bytes per transfer)
uint16_t chunkSize = min(length - bytesRead, (uint16_t)32);
uint16_t chunkSize = min((uint16_t)(length - bytesRead), (uint16_t)32);
if (!dataStreamReg.read(&buffer[bytesRead], chunkSize)) {
break;
@ -198,7 +197,7 @@ uint16_t Adafruit_UBloxDDC::readBytes(uint8_t* buffer, uint16_t length) {
* @param maxLength Maximum length of buffer
* @return Number of bytes read into the buffer
*/
uint16_t Adafruit_UBloxDDC::readMessage(uint8_t* buffer, uint16_t maxLength) {
uint16_t Adafruit_UBloxDDC::readMessage(uint8_t *buffer, uint16_t maxLength) {
uint16_t bytesAvailable = available();
if (bytesAvailable == 0) {
@ -215,8 +214,7 @@ uint16_t Adafruit_UBloxDDC::readMessage(uint8_t* buffer, uint16_t maxLength) {
* @param messageLength Pointer to variable to store message length
* @return Pointer to internal buffer containing the message
*/
uint8_t* Adafruit_UBloxDDC::readMessage(uint16_t* messageLength) {
uint8_t *Adafruit_UBloxDDC::readMessage(uint16_t *messageLength) {
*messageLength = readMessage(_buffer, MAX_BUFFER_SIZE);
return _buffer;
}

View file

@ -10,7 +10,7 @@
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Your Name for Project Name.
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*/
@ -18,32 +18,36 @@
#ifndef ADAFRUIT_UBLOXDDC_H
#define ADAFRUIT_UBLOXDDC_H
#include <Arduino.h>
#include <Stream.h>
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#include <Arduino.h>
#include <Stream.h>
/*!
* @brief Arduino library for interfacing with u-blox GPS/RTK modules over I2C
*/
class Adafruit_UBloxDDC : public Stream {
private:
private:
Adafruit_I2CDevice *_i2cDevice; ///< Underlying I2C device
// Register addresses
static const uint8_t REG_DATA_STREAM = 0xFF; ///< Register for reading data stream
static const uint8_t REG_BYTES_AVAILABLE_MSB = 0xFD; ///< MSB of bytes available
static const uint8_t REG_BYTES_AVAILABLE_LSB = 0xFE; ///< LSB of bytes available
static const uint8_t REG_DATA_STREAM =
0xFF; ///< Register for reading data stream
static const uint8_t REG_BYTES_AVAILABLE_MSB =
0xFD; ///< MSB of bytes available
static const uint8_t REG_BYTES_AVAILABLE_LSB =
0xFE; ///< LSB of bytes available
// Buffer for reading messages
static const uint16_t MAX_BUFFER_SIZE = 128; ///< Maximum buffer size for messages
static const uint16_t MAX_BUFFER_SIZE =
128; ///< Maximum buffer size for messages
uint8_t _buffer[MAX_BUFFER_SIZE]; ///< Internal buffer for messages
// Last byte read for peek() implementation
int _lastByte = -1; ///< Last byte read by peek()
bool _hasPeeked = false; ///< Indicates if we have a peeked byte waiting
public:
public:
// Constructor & destructor
Adafruit_UBloxDDC(uint8_t address = 0x42, TwoWire *wire = &Wire);
~Adafruit_UBloxDDC();
@ -60,9 +64,9 @@ class Adafruit_UBloxDDC : public Stream {
virtual size_t write(const uint8_t *buffer, size_t size) override;
// Additional methods
uint16_t readBytes(uint8_t* buffer, uint16_t length);
uint16_t readMessage(uint8_t* buffer, uint16_t maxLength);
uint8_t* readMessage(uint16_t* messageLength);
uint16_t readBytes(uint8_t *buffer, uint16_t length);
uint16_t readMessage(uint8_t *buffer, uint16_t maxLength);
uint8_t *readMessage(uint16_t *messageLength);
};
#endif // ADAFRUIT_UBLOXDDC_H

View file

@ -0,0 +1,58 @@
/*!
* @file Adafruit_uBlox_Ubx_Messages.h
*
* Pre-built UBX message payloads for common tasks
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Brent Rubell for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*/
#ifndef ADAFRUIT_UBLOX_UBX_MESSAGES
#define ADAFRUIT_UBLOX_UBX_MESSAGES
#include <Arduino.h>
// NMEA Message Configuration Commands (CFG-MSG)
// Format: {msgClass, msgID, rate_I2C, rate_UART1, rate_UART2, rate_USB,
// rate_SPI, reserved}
// Enable specific NMEA message sentences to output on the DDC interface
static uint8_t UBX_CFG_MSG_NMEA_GGA_ENABLE[] = {0xF0, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GLL_ENABLE[] = {0xF0, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSA_ENABLE[] = {0xF0, 0x02, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSV_ENABLE[] = {0xF0, 0x03, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_ENABLE[] = {0xF0, 0x04, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_VTG_ENABLE[] = {0xF0, 0x05, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00};
// Disable specific NMEA message sentences from outputting on the DDC interface
static uint8_t UBX_CFG_MSG_NMEA_GGA_DISABLE[] = {0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GLL_DISABLE[] = {0xF0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSA_DISABLE[] = {0xF0, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_GSV_DISABLE[] = {0xF0, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_RMC_DISABLE[] = {0xF0, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
static uint8_t UBX_CFG_MSG_NMEA_VTG_DISABLE[] = {0xF0, 0x05, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
// Navigation Rate Configuration Commands (CFG-RATE)
// Format: {measRate_ms (2 bytes), navRate, timeRef}
static uint8_t UBX_CFG_RATE_1HZ[] = {0xE8, 0x03, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_2HZ[] = {0xF4, 0x01, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_5HZ[] = {0xC8, 0x00, 0x01, 0x00, 0x01, 0x00};
static uint8_t UBX_CFG_RATE_10HZ[] = {0x64, 0x00, 0x01, 0x00, 0x01, 0x00};
#endif // ADAFRUIT_UBLOX_UBX_MESSAGES

View file

@ -7,7 +7,7 @@
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Your Name for Project Name.
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*/
@ -17,7 +17,7 @@
#include <Arduino.h>
// UBX Message Classes
/** UBX protocol message class identifiers. */
typedef enum {
UBX_CLASS_NAV = 0x01, // Navigation Results
UBX_CLASS_RXM = 0x02, // Receiver Manager Messages
@ -36,7 +36,7 @@ typedef enum {
UBX_CLASS_NMEA = 0xF0 // NMEA Standard Messages
} UBXMessageClass;
// UBX CFG Message IDs
/** UBX CFG Message IDs. */
typedef enum {
UBX_CFG_PRT = 0x00, // Port Configuration
UBX_CFG_MSG = 0x01, // Message Configuration
@ -48,7 +48,7 @@ typedef enum {
UBX_CFG_PMS = 0x86 // Power Mode Setup
} UBXCfgMessageId;
// Return values for functions that wait for acknowledgment
/** Return values for functions that wait for acknowledgment. */
typedef enum {
UBX_SEND_SUCCESS = 0, // Message was acknowledged (ACK)
UBX_SEND_NAK, // Message was not acknowledged (NAK)
@ -56,7 +56,7 @@ typedef enum {
UBX_SEND_TIMEOUT // Timed out waiting for ACK/NAK
} UBXSendStatus;
// Port ID enum for different interfaces
/** Port ID enum for different interfaces. */
typedef enum {
UBX_PORT_DDC = 0, // I2C / DDC port
UBX_PORT_UART1 = 1, // UART1 port
@ -65,7 +65,7 @@ typedef enum {
UBX_PORT_SPI = 4 // SPI port
} UBXPortId;
// UART mode flags (Charlen, Parity & Stop bit settings)
/** UART mode flags (Charlen, Parity & Stop bit settings). */
typedef enum {
UBX_UART_MODE_8N1 = 0x000, // 8-bit, no parity, 1 stop bit
UBX_UART_MODE_8E1 = 0x100, // 8-bit, even parity, 1 stop bit
@ -82,26 +82,27 @@ typedef enum {
} UBXUARTMode;
// Protocol flags for inProtoMask and outProtoMask
#define UBX_PROTOCOL_UBX 0x0001 // UBX protocol
#define UBX_PROTOCOL_NMEA 0x0002 // NMEA protocol
#define UBX_PROTOCOL_RTCM 0x0004 // RTCM2 protocol (only for inProtoMask)
#define UBX_PROTOCOL_RTCM3 0x0020 // RTCM3 protocol
#define UBX_PROTOCOL_UBX 0x0001 ///< UBX protocol
#define UBX_PROTOCOL_NMEA 0x0002 ///< NMEA protocol
#define UBX_PROTOCOL_RTCM 0x0004 ///< RTCM2 protocol (only for inProtoMask)
#define UBX_PROTOCOL_RTCM3 0x0020 ///< RTCM3 protocol
// CFG-PRT (Port Configuration) Message
// Total size: 20 bytes
/** UBX CFG-PRT (Port Configuration) message structure. 20 bytes total.
*/
typedef union {
struct {
uint8_t portID; // Port identifier (0=DDC/I2C, 1=UART1, 2=UART2, 3=USB, 4=SPI)
uint8_t reserved1; // Reserved
uint16_t txReady; // TX ready PIN configuration
uint32_t mode; // UART mode (bit field) or Reserved for non-UART ports
uint32_t baudRate; // Baudrate in bits/second (UART only)
uint16_t inProtoMask; // Input protocol mask
uint16_t outProtoMask; // Output protocol mask
uint16_t flags; // Flags bit field
uint16_t reserved2; // Reserved
} fields;
uint8_t raw[20];
uint8_t
portID; ///< Port identifier (0=DDC/I2C, 1=UART1, 2=UART2, 3=USB, 4=SPI)
uint8_t reserved1; ///< Reserved
uint16_t txReady; ///< TX ready PIN configuration
uint32_t mode; ///< UART mode (bit field) or Reserved for non-UART ports
uint32_t baudRate; ///< Baudrate in bits/second (UART only)
uint16_t inProtoMask; ///< Input protocol mask
uint16_t outProtoMask; ///< Output protocol mask
uint16_t flags; ///< Flags bit field
uint16_t reserved2; ///< Reserved
} fields; ///< Fields for CFG-PRT message
uint8_t raw[20]; ///< Raw byte array for CFG-PRT message
} UBX_CFG_PRT_t;
#endif // ADAFRUIT_UBLOX_TYPEDEF_H

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

13
README.md Normal file
View file

@ -0,0 +1,13 @@
# Adafruit uBlox Library [![Build Status](https://github.com/adafruit/Adafruit_uBlox/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_uBlox/actions)
This is a driver library to abstract away the details of communicating with u-blox GPS and RTK modules. It provides a simple interface for sending and receiving data over a generic Stream interface.
This library provides two main classes:
- `Adafruit_UBX`: Interfaces with u-blox GPS/RTK modules using any stream object as an input (UART, DDC, or other) and parses UBX protocol messages.
- `Adafruit_UBloxDDC`: Interface for communicating with u-blox modules over DDC (I2C).
For parsing NMEA sentences, we provide an example for using this library with the [Adafruit_GPS library](https://github.com/adafruit/Adafruit_GPS).
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, all text above must be included in any redistribution

View file

@ -0,0 +1,63 @@
/*!
* @file ublox_ddc.ino
*
* Example sketch demonstrating the use of the Adafruit_UBloxDDC library
* with u-blox GPS/RTK modules over I2C (DDC) interface.
*
* This example simply streams all raw bytes from the GPS module to the
* Serial port so you can see the NMEA sentences in their original format.
*
* Written by Ladyada for Adafruit Industries.
*
* MIT license, all text above must be included in any redistribution
*/
#include <Adafruit_UBloxDDC.h>
// Create Adafruit_UBloxDDC object with default I2C address (0x42)
Adafruit_UBloxDDC gps;
// Buffer for reading chunks of data
const size_t BUFFER_SIZE = 64;
uint8_t buffer[BUFFER_SIZE];
void setup() {
// Initialize serial port for debugging
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect
}
Serial.println("Adafruit UBlox DDC Raw NMEA Stream Example");
// Initialize GPS module
if (gps.begin()) {
Serial.println("GPS module found!");
} else {
Serial.println("Failed to connect to GPS module!");
while (1); // Don't proceed if we couldn't connect to the module
}
Serial.println("Streaming raw data from GPS module...");
Serial.println("------------------------------------");
}
void loop() {
// Check how many bytes are available
int bytesAvailable = gps.available();
if (bytesAvailable > 0) {
// Read up to BUFFER_SIZE bytes at a time
size_t bytesToRead = min(bytesAvailable, (int)BUFFER_SIZE);
size_t bytesRead = gps.readBytes(buffer, bytesToRead);
// Stream the bytes directly to Serial
// This will show raw NMEA sentences
for (size_t i = 0; i < bytesRead; i++) {
Serial.write(buffer[i]);
}
}
// Short delay to prevent overwhelming the serial monitor
delay(10);
}

View file

@ -0,0 +1,192 @@
/*!
* @file ublox_ddc_parse_nmea.ino
*
* Example sketch demonstrating parsing NMEA sentences from a u-blox GPS/RTK module
* using the Adafruit_GPS and Adafruit_UBX libraries.
*
* Written by Brent Rubell for Adafruit Industries.
*
* MIT license, all text above must be included in any redistribution
*/
#include <Adafruit_GPS.h>
#include <Adafruit_UBX.h>
#include <Adafruit_UBloxDDC.h>
// Adafruit_UBloxDDC object with default I2C address (0x42)
Adafruit_UBloxDDC gps;
// Create Adafruit_UBX parser using the DDC object as input stream
Adafruit_UBX ubx(gps);
// Create Adafruit_GPS object for use as a NMEA parser only
Adafruit_GPS NMEA;
// Buffer to store NMEA sentences from the module (may be partial sentences)
const size_t SZ_NMEA_BUFFER = 128;
uint8_t buffer[SZ_NMEA_BUFFER];
uint32_t timer = millis();
/*!
* @brief Sets the NMEA output to only RMC and GGA sentences and waits for an
* acknowledgment. All other common NMEA sentences are disabled to increase
* loop() performance by decreasing the amount of messages output by the UBlox
* module.
* @return Status indicating success, failure, or timeout
*/
UBXSendStatus SetNMEAOutputRMCGGAOnly() {
UBXSendStatus status;
// Disable all common NMEA messages
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_GLL_DISABLE,
sizeof(UBX_CFG_MSG_NMEA_GLL_DISABLE));
if (status != UBX_SEND_SUCCESS)
return status;
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_GSA_DISABLE,
sizeof(UBX_CFG_MSG_NMEA_GSA_DISABLE));
if (status != UBX_SEND_SUCCESS)
return status;
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_GSV_DISABLE,
sizeof(UBX_CFG_MSG_NMEA_GSV_DISABLE));
if (status != UBX_SEND_SUCCESS)
return status;
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_VTG_DISABLE,
sizeof(UBX_CFG_MSG_NMEA_VTG_DISABLE));
if (status != UBX_SEND_SUCCESS)
return status;
// Enable only GGA and RMC messages
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_GGA_ENABLE,
sizeof(UBX_CFG_MSG_NMEA_GGA_ENABLE));
if (status != UBX_SEND_SUCCESS)
return status;
status = ubx.sendMessageWithAck(UBX_CLASS_CFG, UBX_CFG_MSG,
UBX_CFG_MSG_NMEA_RMC_ENABLE,
sizeof(UBX_CFG_MSG_NMEA_RMC_ENABLE));
return status;
}
void setup() {
// Initialize serial port for debugging
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect
}
// Initialize GPS module
if (!gps.begin()) {
Serial.println("Failed to initialize GPS module!");
while (1); // Halt if initialization fails
}
Serial.println("GPS module initialized successfully!");
// Initialize the u-blox parser
if (!ubx.begin()) {
Serial.println("Failed to initialize u-blox parser!");
while (1); // Halt if initialization fails
}
Serial.println("u-blox parser initialized successfully!");
ubx.verbose_debug = 3; // Set debug level to verbose
// Set NMEA output on DDC to RMC and GGA sentences only
UBXSendStatus status = SetNMEAOutputRMCGGAOnly();
if (status != UBX_SEND_SUCCESS) {
Serial.print("Failed to configure NMEA output [status code: ");
Serial.print(status);
Serial.println("]");
while (1); // Halt if setting NMEA output fails
}
}
void loop() {
static char nmeaSentenceBuf[SZ_NMEA_BUFFER];
static size_t nmeaSentenceIdx = 0;
// Check how many bytes are available
int bytesAvailable = gps.available();
if (bytesAvailable > 0) {
// Read up to SZ_NMEA_BUFFER bytes at a time
size_t bytesToRead = min(bytesAvailable, (int)SZ_NMEA_BUFFER);
size_t bytesRead = gps.readBytes(buffer, bytesToRead);
// Build NMEA sentences and parse when complete
for (size_t i = 0; i < bytesRead; i++) {
char c = buffer[i];
// Add to buffer if space available
if (nmeaSentenceIdx < SZ_NMEA_BUFFER - 1) {
nmeaSentenceBuf[nmeaSentenceIdx++] = c;
}
// Check for end of NMEA sentence
if (c == '\n') {
nmeaSentenceBuf[nmeaSentenceIdx] = '\0';
// Parse the NMEA sentence
if (NMEA.parse(nmeaSentenceBuf)) {
// Successfully parsed sentence!
Serial.println(nmeaSentenceBuf);
// approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) {
timer = millis(); // reset the timer
Serial.print("\nTime: ");
if (NMEA.hour < 10) {
Serial.print('0');
}
Serial.print(NMEA.hour, DEC);
Serial.print(':');
if (NMEA.minute < 10) {
Serial.print('0');
}
Serial.print(NMEA.minute, DEC);
Serial.print(':');
if (NMEA.seconds < 10) {
Serial.print('0');
}
Serial.print(NMEA.seconds, DEC);
Serial.print('.');
if (NMEA.milliseconds < 10) {
Serial.print("00");
} else if (NMEA.milliseconds > 9 && NMEA.milliseconds < 100) {
Serial.print("0");
}
Serial.println(NMEA.milliseconds);
Serial.print("Date: ");
Serial.print(NMEA.day, DEC);
Serial.print('/');
Serial.print(NMEA.month, DEC);
Serial.print("/20");
Serial.println(NMEA.year, DEC);
Serial.print("Fix: ");
Serial.print((int)NMEA.fix);
Serial.print(" quality: ");
Serial.println((int)NMEA.fixquality);
if (NMEA.fix) {
Serial.print("Location: ");
Serial.print(NMEA.latitude, 4);
Serial.print(NMEA.lat);
Serial.print(", ");
Serial.print(NMEA.longitude, 4);
Serial.println(NMEA.lon);
Serial.print("Speed (knots): ");
Serial.println(NMEA.speed);
Serial.print("Angle: ");
Serial.println(NMEA.angle);
Serial.print("Altitude: ");
Serial.println(NMEA.altitude);
Serial.print("Satellites: ");
Serial.println((int)NMEA.satellites);
}
}
} else {
Serial.println("Failed to parse sentence.");
}
nmeaSentenceIdx = 0; // Reset index for next sentence
}
}
}
// Short delay to prevent overwhelming the module
delay(10);
}

View file

@ -0,0 +1,151 @@
/*!
* @file ublox_ubxtest.ino
*
* Test sketch to verify switching to UBX protocol mode
* This example uses I2C (DDC) to communicate with a u-blox module.
*
* Written by Ladyada for Adafruit Industries.
*
* MIT license, all text above must be included in any redistribution
*/
#include "Adafruit_UBloxDDC.h"
#include "Adafruit_UBX.h"
#include "Adafruit_uBlox_typedef.h"
// Create Adafruit_UBloxDDC object with default I2C address (0x42)
Adafruit_UBloxDDC ddc;
// Create Adafruit_UBX parser using the DDC object as input stream
Adafruit_UBX ubx(ddc);
// Variables to track message statistics
uint32_t messageCount = 0;
uint32_t lastMsgTime = 0;
bool ubxModeConfirmed = false;
// Callback function for UBX messages
void ubxMessageCallback(uint8_t msgClass, uint8_t msgId, uint16_t payloadLen, uint8_t *payload) {
messageCount++;
lastMsgTime = millis();
// First successful UBX message confirms we're in UBX mode
if (!ubxModeConfirmed) {
ubxModeConfirmed = true;
Serial.println("SUCCESS: UBX mode confirmed! Receiving UBX messages.");
}
// Print message details
Serial.print("UBX Message: Class 0x");
if (msgClass < 0x10) Serial.print("0");
Serial.print(msgClass, HEX);
Serial.print(", ID 0x");
if (msgId < 0x10) Serial.print("0");
Serial.print(msgId, HEX);
Serial.print(", Length: ");
Serial.print(payloadLen);
Serial.println(" bytes");
}
void setup() {
// Initialize serial port for debugging
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect
}
Serial.println("\n\n------------- UBX Mode Test -------------");
Serial.println("This test will try to switch a u-blox module to UBX protocol");
// Initialize GPS module
Serial.print("Connecting to u-blox module via I2C...");
if (ddc.begin()) {
Serial.println(" SUCCESS!");
} else {
Serial.println(" FAILED!");
Serial.println("Check connections and try again.");
while (1); // Don't proceed if we couldn't connect to the module
}
// Show current data format (should be NMEA)
Serial.println("\nCurrent data format (should be NMEA sentences):");
Serial.println("------------------------------------------------");
// Show some raw data
unsigned long startTime = millis();
while (millis() - startTime < 3000) {
if (ddc.available()) {
int c = ddc.read();
if (c != -1) {
Serial.write(c);
}
}
}
Serial.println("\n------------------------------------------------");
// Initialize UBX parser and set debug mode
ubx.begin();
ubx.verbose_debug = 2; // Enable basic debug output
// Set the callback function for UBX messages
ubx.setMessageCallback(ubxMessageCallback);
// Now switch to UBX mode
Serial.println("\nSwitching to UBX-only mode on DDC port...");
UBXSendStatus status = ubx.setUBXOnly(UBX_PORT_DDC, true, 1000);
switch (status) {
case UBX_SEND_SUCCESS:
Serial.println("SUCCESS: UBX configuration command acknowledged!");
break;
case UBX_SEND_NAK:
Serial.println("ERROR: UBX configuration command was rejected by the module.");
break;
case UBX_SEND_FAIL:
Serial.println("ERROR: Failed to send UBX configuration command.");
break;
case UBX_SEND_TIMEOUT:
Serial.println("ERROR: Timeout waiting for acknowledgment.");
break;
}
if (status != UBX_SEND_SUCCESS) {
Serial.println("Continuing anyway to see if we receive any UBX messages...");
}
Serial.println("\nWaiting for UBX messages (timeout: 5 seconds)...");
lastMsgTime = millis();
}
void loop() {
// Check for UBX messages
ubx.checkMessages();
// Display statistics every second
static uint32_t lastStatsTime = 0;
if (millis() - lastStatsTime >= 1000) {
lastStatsTime = millis();
Serial.print("Status: Messages received: ");
Serial.print(messageCount);
// Check for timeout
if (!ubxModeConfirmed && (millis() - lastMsgTime > 5000)) {
Serial.println("\n\nTIMEOUT: No UBX messages received within 5 seconds.");
Serial.println("Possible issues:");
Serial.println("1. Module doesn't support UBX protocol on this port");
Serial.println("2. Configuration command wasn't received properly");
Serial.println("3. Module requires different configuration");
Serial.println("\nTry using verbose_debug = 2 for more details.");
while(1); // Stop execution
}
Serial.println();
}
// Short delay to prevent overwhelming the processor
delay(10);
}

10
library.properties Normal file
View file

@ -0,0 +1,10 @@
name=Adafruit uBlox
version=1.0.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Library for interfacing with u-blox GPS/RTK modules.
paragraph=Library for interfacing with u-blox GPS/RTK modules.
category=Communication
url=https://github.com/adafruit/Adafruit_uBlox/
architectures=*
depends=Adafruit BusIO, Adafruit GPS Library