Skip to content
This repository was archived by the owner on Jan 28, 2021. It is now read-only.

implemented Power On/Off (UBX-RXM-PMREQ) #116

Merged
merged 6 commits into from
Jul 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions examples/Example22_PowerOff/Example22_PowerOff.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
Powering off a ublox GPS module
By: bjorn
unsurv.org
Date: July 20th, 2020
License: MIT. See license file for more information but you can
basically do whatever you want with this code.

This example shows you how to turn off the ublox module to lower the power consumption.
There are two functions: one just specifies a duration in milliseconds the other also specifies a pin on the GPS device to wake it up with.
By driving a voltage from LOW to HIGH or HIGH to LOW on the chosen module pin you wake the device back up.
Note: Doing so on the INT0 pin when using the regular powerOff(durationInMs) function will wake the device anyway. (tested on SAM-M8Q)
Note: While powered off, you should not query the device for data or it might wake up. This can be used to wake the device but is not recommended.
Works best when also putting your microcontroller to sleep.

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 GPS and a BlackBoard.
To force the device to wake up you need to connect to a pin (for example INT0) seperately on the module.
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 "SparkFun_Ublox_Arduino_Library.h" //http://librarymanager/All#SparkFun_Ublox_GPS
SFE_UBLOX_GPS myGPS;

// define a digital pin capable of driving HIGH and LOW
#define WAKEUP_PIN 5

// Possible GNSS interrupt pins for powerOffWithInterrupt are:
// VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX = uartrx
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0 = extint0 (default)
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT1 = extint1
// VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS = spics
// These values can be or'd (|) together to enable interrupts on multiple pins

void wakeUp() {

Serial.print("-- waking up module via pin " + String(WAKEUP_PIN));
Serial.println(" on your microcontroller --");

digitalWrite(WAKEUP_PIN, LOW);
delay(1000);
digitalWrite(WAKEUP_PIN, HIGH);
delay(1000);
digitalWrite(WAKEUP_PIN, LOW);
}


void setup() {

pinMode(WAKEUP_PIN, OUTPUT);
digitalWrite(WAKEUP_PIN, LOW);

Serial.begin(115200);
while (!Serial); //Wait for user to open terminal
Serial.println("SparkFun Ublox Example");

Wire.begin();

//myGPS.enableDebugging(); // Enable debug messages

if (myGPS.begin() == false) //Connect to the Ublox module using Wire port
{
Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing."));
while (1);
}

// Powering off for 20s, you should see the power consumption drop.
Serial.println("-- Powering off module for 20s --");

myGPS.powerOff(20000);
//myGPS.powerOffWithInterrupt(20000, VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0);

delay(10000);

// After 10 seconds wake the device via the specified pin on your microcontroller and module.
wakeUp();
}

void loop() {
//Do nothing
}
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ setDynamicModel KEYWORD2
getDynamicModel KEYWORD2
powerSaveMode KEYWORD2
getPowerSaveMode KEYWORD2
powerOff KEYWORD2
powerOffWithInterrupt KEYWORD2

configureMessage KEYWORD2
enableMessage KEYWORD2
Expand Down
123 changes: 123 additions & 0 deletions src/SparkFun_Ublox_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2569,6 +2569,129 @@ uint8_t SFE_UBLOX_GPS::getPowerSaveMode(uint16_t maxWait)
return (payloadCfg[1]); // Return the low power mode
}

// Powers off the GPS device for a given duration to reduce power consumption.
// NOTE: Querying the device before the duration is complete, for example by "getLatitude()" will wake it up!
// Returns true if command has not been not acknowledged.
// Returns false if command has not been acknowledged or maxWait = 0.
boolean SFE_UBLOX_GPS::powerOff(uint32_t durationInMs, uint16_t maxWait)
{
// use durationInMs = 0 for infinite duration
if (_printDebug == true)
{
_debugSerial->print(F("Powering off for "));
_debugSerial->print(durationInMs);
_debugSerial->println(" ms");
}

// Power off device using UBX-RXM-PMREQ
packetCfg.cls = UBX_CLASS_RXM; // 0x02
packetCfg.id = UBX_RXM_PMREQ; // 0x41
packetCfg.len = 8;
packetCfg.startingSpot = 0;

// duration
// big endian to little endian, switch byte order
payloadCfg[0] = (durationInMs >> (8*0)) & 0xff;
payloadCfg[1] = (durationInMs >> (8*1)) & 0xff;
payloadCfg[2] = (durationInMs >> (8*2)) & 0xff;
payloadCfg[3] = (durationInMs >> (8*3)) & 0xff;

payloadCfg[4] = 0x02; //Flags : set the backup bit
payloadCfg[5] = 0x00; //Flags
payloadCfg[6] = 0x00; //Flags
payloadCfg[7] = 0x00; //Flags

if (maxWait != 0)
{
// check for "not acknowledged" command
return (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_COMMAND_NACK);
}
else
{
sendCommand(&packetCfg, maxWait);
return false; // can't tell if command not acknowledged if maxWait = 0
}
}

// Powers off the GPS device for a given duration to reduce power consumption.
// While powered off it can be woken up by creating a falling or rising voltage edge on the specified pin.
// NOTE: The GPS seems to be sensitve to signals on the pins while powered off. Works best when Microcontroller is in deepsleep.
// NOTE: Querying the device before the duration is complete, for example by "getLatitude()" will wake it up!
// Returns true if command has not been not acknowledged.
// Returns false if command has not been acknowledged or maxWait = 0.
boolean SFE_UBLOX_GPS::powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources, boolean forceWhileUsb, uint16_t maxWait)
{
// use durationInMs = 0 for infinite duration
if (_printDebug == true)
{
_debugSerial->print(F("Powering off for "));
_debugSerial->print(durationInMs);
_debugSerial->println(" ms");
}

// Power off device using UBX-RXM-PMREQ
packetCfg.cls = UBX_CLASS_RXM; // 0x02
packetCfg.id = UBX_RXM_PMREQ; // 0x41
packetCfg.len = 16;
packetCfg.startingSpot = 0;

payloadCfg[0] = 0x00; // message version

// bytes 1-3 are reserved - and must be set to zero
payloadCfg[1] = 0x00;
payloadCfg[2] = 0x00;
payloadCfg[3] = 0x00;

// duration
// big endian to little endian, switch byte order
payloadCfg[4] = (durationInMs >> (8*0)) & 0xff;
payloadCfg[5] = (durationInMs >> (8*1)) & 0xff;
payloadCfg[6] = (durationInMs >> (8*2)) & 0xff;
payloadCfg[7] = (durationInMs >> (8*3)) & 0xff;

// flags

// disables USB interface when powering off, defaults to true
if (forceWhileUsb)
{
payloadCfg[8] = 0x06; // force | backup
}
else
{
payloadCfg[8] = 0x02; // backup only (leave the force bit clear - module will stay on if USB is connected)
}

payloadCfg[9] = 0x00;
payloadCfg[10] = 0x00;
payloadCfg[11] = 0x00;

// wakeUpSources

// wakeupPin mapping, defaults to VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0

// Possible values are:
// VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT1
// VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS

payloadCfg[12] = (wakeupSources >> (8*0)) & 0xff;
payloadCfg[13] = (wakeupSources >> (8*1)) & 0xff;
payloadCfg[14] = (wakeupSources >> (8*2)) & 0xff;
payloadCfg[15] = (wakeupSources >> (8*3)) & 0xff;

if (maxWait != 0)
{
// check for "not acknowledged" command
return (sendCommand(&packetCfg, maxWait) != SFE_UBLOX_STATUS_COMMAND_NACK);
}
else
{
sendCommand(&packetCfg, maxWait);
return false; // can't tell if command not acknowledged if maxWait = 0
}
}

//Change the dynamic platform model using UBX-CFG-NAV5
//Possible values are:
//PORTABLE,STATIONARY,PEDESTRIAN,AUTOMOTIVE,SEA,
Expand Down
8 changes: 8 additions & 0 deletions src/SparkFun_Ublox_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,12 @@ const uint32_t VAL_CFG_SUBSEC_ANTCONF = 0x00000400; // antConf - antenna config
const uint32_t VAL_CFG_SUBSEC_LOGCONF = 0x00000800; // logConf - logging configuration
const uint32_t VAL_CFG_SUBSEC_FTSCONF = 0x00001000; // ftsConf - FTS configuration (FTS products only)

// Bitfield wakeupSources for UBX_RXM_PMREQ
const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX = 0x00000008; // uartrx
const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0 = 0x00000020; // extint0
const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT1 = 0x00000040; // extint1
const uint32_t VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS = 0x00000080; // spics

enum dynModel // Possible values for the dynamic platform model, which provide more accuract position output for the situation. Description extracted from ZED-F9P Integration Manual
{
DYN_MODEL_PORTABLE = 0, //Applications with low acceleration, e.g. portable devices. Suitable for most situations.
Expand Down Expand Up @@ -641,6 +647,8 @@ class SFE_UBLOX_GPS

boolean powerSaveMode(bool power_save = true, uint16_t maxWait = 1100);
uint8_t getPowerSaveMode(uint16_t maxWait = 1100); // Returns 255 if the sendCommand fails
boolean powerOff(uint32_t durationInMs, uint16_t maxWait = 1100);
boolean powerOffWithInterrupt(uint32_t durationInMs, uint32_t wakeupSources = VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0, boolean forceWhileUsb = true, uint16_t maxWait = 1100);

//Change the dynamic platform model using UBX-CFG-NAV5
boolean setDynamicModel(dynModel newDynamicModel = DYN_MODEL_PORTABLE, uint16_t maxWait = 1100);
Expand Down