Skip to content
Open
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
124 changes: 58 additions & 66 deletions src/helpers/sensors/EnvironmentSensorManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,15 @@ static RAK12035_SoilMoisture RAK12035;
#endif

#ifdef RAK_WISBLOCK_GPS
static uint32_t gpsResetPin = 0;
static bool i2cGPSFlag = false;
static bool serialGPSFlag = false;
#ifndef TELEM_RAK12500_ADDRESS
#define TELEM_RAK12500_ADDRESS 0x42 //RAK12500 Ublox GPS via i2c
#define TELEM_RAK12500_ADDRESS 0x42 // RAK12500 u-blox ZOE-M8Q GPS via i2c
#endif
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
static SFE_UBLOX_GNSS ublox_GNSS;
static SFE_UBLOX_GNSS ublox_GNSS; // RAK12500 u-blox ZOE-M8Q GPS via UART

class RAK12500LocationProvider : public LocationProvider {
class UbloxLocationProvider : public LocationProvider {
long _lat = 0;
long _lng = 0;
long _alt = 0;
Expand All @@ -190,8 +189,38 @@ class RAK12500LocationProvider : public LocationProvider {
long getTimestamp() override { return _epoch; }
void sendSentence(const char * sentence) override { }
void reset() override { }
void begin() override { }
void stop() override { }
void configure() override {
ublox_GNSS.setI2COutput(COM_TYPE_UBX); // Disable NMEA output (the ublox library can use the more efficient proprietary UBX protocol)
// Configure constellations
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GPS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GALILEO);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GLONASS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_SBAS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_BEIDOU);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_IMES);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_QZSS);

ublox_GNSS.setAopCfg(1); // Enable AssistNow Autonomous for faster positioning
ublox_GNSS.setMeasurementRate(1000); // Take one measurement per second
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
}
void begin() override {
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
}
void stop() override {
#ifdef ETHERNET_ENABLED
MESH_DEBUG_PRINTLN("GPS cannot be disabled as this would also disable Ethernet.");
return;
#endif
#ifdef SKY66122
MESH_DEBUG_PRINTLN("GPS cannot be disabled as this would also disable SKY66122.");
return;
#endif
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, LOW);
return;
}
void loop() override {
if (ublox_GNSS.getGnssFixOk(8)) {
_fix = true;
Expand All @@ -207,7 +236,7 @@ class RAK12500LocationProvider : public LocationProvider {
bool isEnabled() override { return true; }
};

static RAK12500LocationProvider RAK12500_provider;
static UbloxLocationProvider Ublox_provider;
#endif

// ============================================================
Expand Down Expand Up @@ -760,6 +789,7 @@ void EnvironmentSensorManager::initBasicGPS() {

if (gps_detected) {
MESH_DEBUG_PRINTLN("GPS detected");
_location->configure();
#ifdef PERSISTANT_GPS
gps_active = true;
return;
Expand All @@ -775,7 +805,6 @@ void EnvironmentSensorManager::initBasicGPS() {
// or make a new location provider ...
#ifdef RAK_WISBLOCK_GPS
void EnvironmentSensorManager::rakGPSInit(){

Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX);

#ifdef GPS_BAUD_RATE
Expand All @@ -784,14 +813,14 @@ void EnvironmentSensorManager::rakGPSInit(){
Serial1.begin(9600);
#endif

//search for the correct IO standby pin depending on socket used
if(gpsIsAwake(WB_IO2)){
}
else if(gpsIsAwake(WB_IO4)){
}
else if(gpsIsAwake(WB_IO5)){
}
else{
#ifdef PIN_3V3_EN

@IoTThinks IoTThinks Aug 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for RAK3401 with 1W with required PIN_3V3_EN at start, most of the RAK boards should have PIN_3V3_EN as INPUT to save power.
This is same as start_gps() too.

And we only need to set it HIGH as this is Power switch, not a GPS RESET.

Please change this:

  #ifdef PIN_3V3_EN
  digitalWrite(PIN_3V3_EN,LOW);
  delay(1000);
  digitalWrite(PIN_3V3_EN,HIGH);
  delay(2000);
  #endif

to this

  #ifdef PIN_3V3_EN
  pinMode(PIN_3V3_EN, OUTPUT);
  digitalWrite(PIN_3V3_EN, HIGH);
  delay(500);
  #endif

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for RAK3401 with 1W with required PIN_3V3_EN at start, most of the RAK boards should have PIN_3V3_EN as INPUT to save power.

And RAK Ethernet (RAK13800) ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And RAK Ethernet (RAK13800) ?

I have no idea.
However, putting pinMode(PIN_3V3_EN, OUTPUT); in front is better than without it.
We can call it as many times without impact.

If the boards have PIN_3V3_EN as INPUT such as RA4631 and may be other RAK-based boards, digitalWrite(PIN_3V3_EN,HIGH); will not be effective.

We can see in start_gps(), we also call pinMode(PIN_3V3_EN, OUTPUT); before digitalWrite(PIN_3V3_EN,HIGH);

@YoshiWalsh YoshiWalsh Aug 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you link documentation that states that keeping PIN_3V3_EN as INPUT saves power? My understanding is that setting the pin as HIGH shouldn't take power because it's pulled high by default.

re: removing the code to pulse PIN_3V3_EN low for 1s at startup, that code appears to be recommended by RAK so I'm hesitant to remove it. I think it ensures that the GPS is in a consistent state when our code initialises.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. You can check the code for T096 and see initVariantShutdown.

RAK boards are no magic, but NRF52 boards. They follow the same rules.

  1. You can check the code for RAK4631 and other RAK-based boards, then imaging what digitalWrite does without pinMode OUT?

Currently, RAK4631 doesnot have pinMode for 3v3 en.

Assume you can turn off LoRa for RAK3401, try to remove pin Mode OUT for 3v3 en.
Then try to bring up GPS via Uart.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, we have to put pinMode OUT.
RAK4631 does not have it.

You can keep the delay or you can explore what are best values.

RAK is a hardware vendor. Their code is sample and on safest side only.

digitalWrite(PIN_3V3_EN,LOW);
delay(1000);
digitalWrite(PIN_3V3_EN,HIGH);
delay(2000);
#endif

if(!gpsIsAwake()){
MESH_DEBUG_PRINTLN("No GPS found");
gps_active = false;
gps_detected = false;
Expand All @@ -805,88 +834,51 @@ void EnvironmentSensorManager::rakGPSInit(){
#endif
}

bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){

#if defined(ETHERNET_ENABLED) && defined(RAK_BOARD)
if (ioPin == WB_IO2) {
// WB_IO2 powers the Ethernet module on RAK baseboards.
return false;
}
#endif

//set initial waking state
pinMode(ioPin,OUTPUT);
digitalWrite(ioPin,LOW);
delay(500);
digitalWrite(ioPin,HIGH);
delay(500);

bool EnvironmentSensorManager::gpsIsAwake(){
//Try to init RAK12500 on I2C
if (ublox_GNSS.begin(Wire) == true){
MESH_DEBUG_PRINTLN("RAK12500 GPS init correctly with pin %i",ioPin);
ublox_GNSS.setI2COutput(COM_TYPE_UBX);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GPS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GALILEO);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GLONASS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_SBAS);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_BEIDOU);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_IMES);
ublox_GNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_QZSS);
ublox_GNSS.setMeasurementRate(1000);
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
gpsResetPin = ioPin;
MESH_DEBUG_PRINTLN("RAK12500 I2C GPS init");
i2cGPSFlag = true;
gps_active = true;
gps_detected = true;

_location = &RAK12500_provider;
_location = &Ublox_provider;

_location->begin();
_location->configure();

return true;
} else if (Serial1.available()) {
MESH_DEBUG_PRINTLN("Serial GPS init correctly and is turned on");
#ifdef PIN_GPS_EN
if(PIN_GPS_EN){
gpsResetPin = PIN_GPS_EN;
}
#endif
MESH_DEBUG_PRINTLN("Serial GPS init correctly");
serialGPSFlag = true;
gps_active = true;
gps_detected = true;

_location->configure();
return true;
}

pinMode(ioPin, INPUT);
MESH_DEBUG_PRINTLN("GPS did not init with this IO pin... try the next");
return false;
}
#endif

void EnvironmentSensorManager::start_gps() {
gps_active = true;
#ifdef RAK_WISBLOCK_GPS
pinMode(gpsResetPin, OUTPUT);
digitalWrite(gpsResetPin, HIGH);
return;
#endif

_location->begin();
_location->reset();

#ifndef PIN_GPS_EN
#if !defined(PIN_GPS_EN) && !defined(RAK_WISBLOCK_GPS)
MESH_DEBUG_PRINTLN("Start GPS is N/A on this board. Actual GPS state unchanged");
#endif
#endif
}

void EnvironmentSensorManager::stop_gps() {
gps_active = false;
#ifdef RAK_WISBLOCK_GPS
pinMode(gpsResetPin, OUTPUT);
digitalWrite(gpsResetPin, LOW);
return;
#endif

_location->stop();

#ifndef PIN_GPS_EN
#if !defined(PIN_GPS_EN) && !defined(RAK_WISBLOCK_GPS)
MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged");
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/sensors/EnvironmentSensorManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class EnvironmentSensorManager : public SensorManager {
void initBasicGPS();
#ifdef RAK_BOARD
void rakGPSInit();
bool gpsIsAwake(uint8_t ioPin);
bool gpsIsAwake();
#endif
#endif

Expand Down
1 change: 1 addition & 0 deletions src/helpers/sensors/LocationProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class LocationProvider {
virtual long getTimestamp() = 0;
virtual void sendSentence(const char * sentence);
virtual void reset() = 0;
virtual void configure() = 0;
virtual void begin() = 0;
virtual void stop() = 0;
virtual void loop() = 0;
Expand Down
8 changes: 8 additions & 0 deletions src/helpers/sensors/MicroNMEALocationProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ public :
if (_peripher_power) _peripher_power->release();
}

void configure() override {
// Attempt to use proprietary NMEA sentences to configure GPS
// Unsupported sentences will be ignored

// Quectel L76K
sendSentence("$PCAS04,7"); // Set constellation - GPS + BeiDou + GLONASS
}

void begin() override {
claim();
if (_pin_en != -1) {
Expand Down
59 changes: 39 additions & 20 deletions variants/gat562_30s_mesh_kit/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,44 @@ extern "C"
{
#endif // __cplusplus

/*
/*
* WisBlock Base GPIO definitions
*/
static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B
static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B
static const uint8_t WB_IO3 = 21; // SLOT_C
static const uint8_t WB_IO4 = 4; // SLOT_C
static const uint8_t WB_IO5 = 9; // SLOT_D
static const uint8_t WB_IO6 = 10; // SLOT_D
static const uint8_t WB_SW1 = 33; // IO_SLOT
static const uint8_t WB_A0 = 5; // IO_SLOT
static const uint8_t WB_A1 = 31; // IO_SLOT
static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
static const uint8_t WB_SPI_CS = 26; // IO_SLOT
static const uint8_t WB_SPI_CLK = 3; // IO_SLOT
static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT
#define PIN_WB_IO1 (17) // SLOT_A P.12 / SLOT_B P.10
#define PIN_WB_IO2 (34) // SLOT_A P.10 / SLOT_B P.12
#define PIN_WB_IO3 (21) // SLOT_C P.12
#define PIN_WB_IO4 (4) // SLOT_C P.10
#define PIN_WB_IO5 (9) // SLOT_D P.12
#define PIN_WB_IO6 (10) // SLOT_D P.10
#define PIN_WB_SW1 (33) // IO_SLOT
#define PIN_WB_A0 (5) // IO_SLOT
#define PIN_WB_A1 (31) // IO_SLOT
#define PIN_WB_I2C1_SDA (13) // SENSOR_SLOT IO_SLOT
#define PIN_WB_I2C1_SCL (14) // SENSOR_SLOT IO_SLOT
#define PIN_WB_I2C2_SDA (24) // IO_SLOT
#define PIN_WB_I2C2_SCL (25) // IO_SLOT
#define PIN_WB_SPI_CS (26) // IO_SLOT
#define PIN_WB_SPI_CLK (3) // IO_SLOT
#define PIN_WB_SPI_MISO (29) // IO_SLOT
#define PIN_WB_SPI_MOSI (30) // IO_SLOT

static const uint8_t WB_IO1 = PIN_WB_IO1;
static const uint8_t WB_IO2 = PIN_WB_IO2;
static const uint8_t WB_IO3 = PIN_WB_IO3;
static const uint8_t WB_IO4 = PIN_WB_IO4;
static const uint8_t WB_IO5 = PIN_WB_IO5;
static const uint8_t WB_IO6 = PIN_WB_IO6;
static const uint8_t WB_SW1 = PIN_WB_SW1;
static const uint8_t WB_A0 = PIN_WB_A0;
static const uint8_t WB_A1 = PIN_WB_A1;
static const uint8_t WB_I2C1_SDA = PIN_WB_I2C1_SDA;
static const uint8_t WB_I2C1_SCL = PIN_WB_I2C1_SCL;
static const uint8_t WB_I2C2_SDA = PIN_WB_I2C2_SDA;
static const uint8_t WB_I2C2_SCL = PIN_WB_I2C2_SCL;
static const uint8_t WB_SPI_CS = PIN_WB_SPI_CS;
static const uint8_t WB_SPI_CLK = PIN_WB_SPI_CLK;
static const uint8_t WB_SPI_MISO = PIN_WB_SPI_MISO;
static const uint8_t WB_SPI_MOSI = PIN_WB_SPI_MOSI;

// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
Expand Down Expand Up @@ -144,6 +162,9 @@ extern "C"

static const uint8_t AREF = PIN_AREF;

// enables 3.3V periphery like GPS sensors and Ethernet modules
#define PIN_3V3_EN PIN_WB_IO2

/*
* Serial interfaces
*/
Expand Down Expand Up @@ -216,8 +237,6 @@ extern "C"
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_TX PIN_SERIAL1_RX
#define PIN_GPS_RX PIN_SERIAL1_TX
#define PIN_GPS_EN (33)
#define PIN_GPS_PPS (17)

#ifdef __cplusplus
}
Expand Down
57 changes: 37 additions & 20 deletions variants/gat562_mesh_evb_pro/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,44 @@ extern "C"
{
#endif // __cplusplus

/*
/*
* WisBlock Base GPIO definitions
*/
static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B
static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B
static const uint8_t WB_IO3 = 21; // SLOT_C
static const uint8_t WB_IO4 = 4; // SLOT_C
static const uint8_t WB_IO5 = 9; // SLOT_D
static const uint8_t WB_IO6 = 10; // SLOT_D
static const uint8_t WB_SW1 = 33; // IO_SLOT
static const uint8_t WB_A0 = 5; // IO_SLOT
static const uint8_t WB_A1 = 31; // IO_SLOT
static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
static const uint8_t WB_SPI_CS = 26; // IO_SLOT
static const uint8_t WB_SPI_CLK = 3; // IO_SLOT
static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT
#define PIN_WB_IO1 (17) // SLOT_A P.12 / SLOT_B P.10
#define PIN_WB_IO2 (34) // SLOT_A P.10 / SLOT_B P.12
#define PIN_WB_IO3 (21) // SLOT_C P.12
#define PIN_WB_IO4 (4) // SLOT_C P.10
#define PIN_WB_IO5 (9) // SLOT_D P.12
#define PIN_WB_IO6 (10) // SLOT_D P.10
#define PIN_WB_SW1 (33) // IO_SLOT
#define PIN_WB_A0 (5) // IO_SLOT
#define PIN_WB_A1 (31) // IO_SLOT
#define PIN_WB_I2C1_SDA (13) // SENSOR_SLOT IO_SLOT
#define PIN_WB_I2C1_SCL (14) // SENSOR_SLOT IO_SLOT
#define PIN_WB_I2C2_SDA (24) // IO_SLOT
#define PIN_WB_I2C2_SCL (25) // IO_SLOT
#define PIN_WB_SPI_CS (26) // IO_SLOT
#define PIN_WB_SPI_CLK (3) // IO_SLOT
#define PIN_WB_SPI_MISO (29) // IO_SLOT
#define PIN_WB_SPI_MOSI (30) // IO_SLOT

static const uint8_t WB_IO1 = PIN_WB_IO1;
static const uint8_t WB_IO2 = PIN_WB_IO2;
static const uint8_t WB_IO3 = PIN_WB_IO3;
static const uint8_t WB_IO4 = PIN_WB_IO4;
static const uint8_t WB_IO5 = PIN_WB_IO5;
static const uint8_t WB_IO6 = PIN_WB_IO6;
static const uint8_t WB_SW1 = PIN_WB_SW1;
static const uint8_t WB_A0 = PIN_WB_A0;
static const uint8_t WB_A1 = PIN_WB_A1;
static const uint8_t WB_I2C1_SDA = PIN_WB_I2C1_SDA;
static const uint8_t WB_I2C1_SCL = PIN_WB_I2C1_SCL;
static const uint8_t WB_I2C2_SDA = PIN_WB_I2C2_SDA;
static const uint8_t WB_I2C2_SCL = PIN_WB_I2C2_SCL;
static const uint8_t WB_SPI_CS = PIN_WB_SPI_CS;
static const uint8_t WB_SPI_CLK = PIN_WB_SPI_CLK;
static const uint8_t WB_SPI_MISO = PIN_WB_SPI_MISO;
static const uint8_t WB_SPI_MOSI = PIN_WB_SPI_MOSI;

// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
Expand Down Expand Up @@ -202,8 +220,7 @@ extern "C"
#define GPS_THREAD_INTERVAL 50
#define PIN_GPS_TX PIN_SERIAL1_RX
#define PIN_GPS_RX PIN_SERIAL1_TX
#define PIN_GPS_EN (33)
#define PIN_GPS_PPS (17)
#define PIN_GPS_EN PIN_WB_IO2

#ifdef __cplusplus
}
Expand Down
Loading