GPS module power management

Be careful switching the GPS on\off. This can generate a reasonably high voltage dip on the processors supply voltage if the power supply is inadequate.

If your powering the test circuit of a 3.3V Pro Mini (for instance) with one of those CP2102 USB-Serial adapters expect the GPS power on to cause the processor to reset.

Its a combination of poor power supply (from the CP2102) and the brown out detect on the processor probably being set at 2.7V.

I do reset the brown out voltage to 1.8V and also uses some resistor and capacitors on the GPS power switching MOSFET to slow the power on\off, these together eliminate the issue.

The last thing you want is a project that resets itself every time the GPS is switched on.

Hi Itmoto. There are literally thousands of transistors that you can choose from. For low power, I'd recommend using a FET as opposed to a bipolar transistor. Also find one with a gate voltage threshold that's much lower than the system voltage of the microcontroller that will control it. You'll want a tight shutoff and turn on for the FET.

Thanks srnet, yes I do not wish it to re-set itself. What you said is slightly over my head as I'm still quite new to this. I am currently powering the project with a 12v 8ah motorcycle battery with 2 mini 360 dc-dc step down buck converters. I am powering a 328p chip and a neo6m from 1 buck stepped down to 5v and the other buck down to 4v powering a Sim800L. Have the Sim800l in sleep mode. Am in the process of introducing the low power sleep library into my code using int0 to Sim800l Ri pin to wake (low) when sms or call received, (struggling badly have to say, should I start a new topic about this as it's a bit off topic?) just wasn't sure what to do about the gps to reduce the consumption. If there's another/better way (my simple brain can understand!) I would be interested in hearing it.


Thanks freaklabs, I know, there are a lot of transistors out there, bit mind boggling! Ok so a FET is best, not sure what you mean with the gate voltage threshold and tight shut off? Will try and research it, will try finding YouTube guide on mosfets!

itmoto:
Thanks srnet, yes I do not wish it to re-set itself. What you said is slightly over my head as I’m still quite new to this.

In essense turning on the power to the GPS with a transistor can reset the ATMEGA328. It may not happen with your circuit, but I have seen it happen with some of mine.

The circuit I use, and the MOSFET I use with a 3.3V Pro Mini will be found in the schematics folder here;

https://github.com/LoRaTracker/Locator2

I have found the IRLML6402 operates very relaibly in this application.

With a UBLOX GPS you can use the software power down, no transistor switch needed, but the current consumption ‘only’ goes down to 35uA as apposed to 0uA with the MOSFET switch.

srnet thanks, I will look into the IRLML6402.
I saw your post about the ublox software power down, it maybe a bit difficult for me, compared to switching a FET on and off from a digital pin. Something else I need to look into!
Had a quick look at your GitHub page, could only see a few bits as viewing from mobile, very impressive, lots of coding

I am trying srnet's method of putting the GPS in the inactive state by sending the RXM-PMREQ message 0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B so it can be hot fixed.

I bought the GPS breakout listed as a NEO-6M but I am unsure it is as listed. It has a XM37-1612 chip see image below (also attached).

I have been trying to find how to send the command/message to the GPS breakout, googling I found a guide on ublox power save modes:

https://ukhas.org.uk/guides:ublox_psm

It had a section on Turning the GPS to backup mode which i think is the same as inactive state? :

// Send a byte array of UBX protocol to the GPS
void sendUBX(uint8_t *MSG, uint8_t len) {
  for(int i=0; i<len; i++) {
    Serial.write(MSG[i]);
  }
  //Serial.println();
}

//Set GPS to backup mode (sets it to never wake up on its own)
 uint8_t GPSoff[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B};
 sendUBX(GPSoff, sizeof(GPSoff)/sizeof(uint8_t));
 
 delay(30000);
 
 //Restart GPS
 uint8_t GPSon[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x37};
 sendUBX(GPSon, sizeof(GPSon)/sizeof(uint8_t));

I tried sending the message GPSoff but could see no change in the consumption?

I am using NeoGPS library to parse the GPS data (thanks to /dev). Is it still possible to send the commands to turn off/reduce the GPS module power while using the library?

Here is the sketch trying to reduce GPS power:

#include <NMEAGPS.h>

#define gpsPort Serial // pin 0 to GPS TX and pin 1 to GPS RX

NMEAGPS GPS;
gps_fix fix; // a structure that contains all the GPS pieces, like lat/lon


//============================ GPS power functions ================================//


// Send a byte array of UBX protocol to the GPS
void sendUBX(uint8_t *MSG, uint8_t len) {
  for (int i = 0; i < len; i++) {
    gpsPort.print(MSG[i]);
    //Serial.write(MSG[i]);
  }
  Serial.println();
}

void GpsOff()
{
  // ---- Set GPS to backup mode (sets it to never wake up on its own)
  uint8_t GPSoff[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B};
  sendUBX(GPSoff, sizeof(GPSoff) / sizeof(uint8_t));
  Serial.println(F("GPS power OFF"));
}


void GpsOn()
{
  // ---- Restart GPS
  uint8_t GPSon[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x37};
  sendUBX(GPSon, sizeof(GPSon) / sizeof(uint8_t));
  Serial.println(F("GPS power ON"));
}

//============================ Setup ======================================//

void setup() {

  Serial.begin(9600);
  Serial.println( F("NeoGPS library + GSM test!") );


  // gpsPort.begin(9600);
  GPS.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC+GGA
  GPS.send_P( &gpsPort, F("PMTK220,1000") ); // 1Hz
  GPS.send_P( &gpsPort, F("PGCMD,33,0") ); // No antenna status

  delay(5000);

  GpsOff();

  delay(10000);

  GpsOn();
}

//=============================== Loop ===================================//

void loop() {

  // if a sentence is received...
  if (GPS.available( gpsPort )) {
    fix = GPS.read(); //  get the latest pieces
    readGPSdata();
  }
}

//=============================== Functions ===============================//

void readGPSdata()
{
  // if a sentence is received...
  // if (GPS.available( gpsPort )) {
  //   fix = GPS.read(); //  get the latest pieces

  if (fix.valid.location) {
    Serial.print( F("We have a fix!") );
  } else
    Serial.print( F("We dont have a fix!") );

  Serial.print( F("\nLocation: ") );
  if (fix.valid.location) {
    Serial.print( fix.latitude(), 6);
    Serial.print( F(", ") );
    Serial.print( fix.longitude(), 6);
  }

  Serial.print( F("\nSatellites: ") );
  if (fix.valid.satellites) {
    Serial.print( fix.satellites );
  }

  Serial.print( F("\nFix: ") );
  if (fix.valid.status) {
    Serial.println(fix.status);
  }
  Serial.println();
}

Going back to the GPS module (XM37-1612 chip) I found a datasheet:

http://www.simplewe.com/wp-content/uploads/2017/04/Simplewe-XM37-1612-Datasheet.pdf

On page 13 it says to send message to put in standby mode so am unsure what will work?

unsigned char StandbyMode[] = {"$PMTK161,0*28\x0D\x0A"};

Thanks so much for any help, it's the very last stage of my project.

Ian.

itmoto:
I bought the GPS breakout listed as a NEO-6M but I am unsure it is as listed. It has a XM37-1612 chip see image below (also attached).

It may have been sold to you as a UBLOX, but what does the datasheet say the chipset actually is ?

The commands I gave, and you found the same one on the UKHAS website, are specifically for UBLOX GPSs, they will not work on other types.

Thanks for the reply.

It says XM37-1612 module runs on the MTK Platform (MediaTek Inc.)

There are lots of GY-NEO6MV2 listed as ublox but using the XM chip.
So just to be clear, modules using this chip are not genuine ublox modules?

If that is the case, I will try sending the message
unsigned char StandbyMode = {"$PMTK161,0*28\x0D\x0A"}; and see if that works.

Would like to know if it's possible to send the message using the neoGPS library?
The message has a $ in it so will the library try to parse it?

Thanks.

In my experience geniune Ublox GPSs are marked with the Ublox logo.

There are however kinown to be fakes out there, especially the 6M type, which although marked as a Ublox GPS do not behave (as in accepting all Ublox commands) as a Ublox GPS.

itmoto:
Would like to know if it's possible to send the message using the neoGPS library?

Sure:

    gps.send_P( &gpsPort, F("PMTK161,0") );

itmoto:
The message has a $ in it so will the library try to parse it?

Only if it receives that sentence. You are sending it, so it never gets parsed. Regardless, NeoGPS would ignore that sentence if it were received.

Thanks srnet, I have just read on the ublox forum there are plenty of fakes out there.
Will have to take care to buy a genuine one if the XM37-1612 standby mode message doesn't work.


Thanks /dev, I will try that message and will see what happens.

The datasheet says sending any byte will wake the GPS module from standby and will return the message {"$PMTK010,002*2D\x0D\x0A"} and start normal operation.
Hopefully NeoGPS will ignore that sentence if it's received as well.

Hopefully NeoGPS will ignore that sentence if it's received as well.

Yes. NeoGPS only parses sentences that you have enabled in NMEAGPS_cfg.h:

#define NMEAGPS_PARSE_GGA
#define NMEAGPS_PARSE_GLL
#define NMEAGPS_PARSE_GSA
#define NMEAGPS_PARSE_GSV
#define NMEAGPS_PARSE_GST
#define NMEAGPS_PARSE_RMC
#define NMEAGPS_PARSE_VTG
#define NMEAGPS_PARSE_ZDA

If the sentence isn't one you can enable, NeoGPS will always ignore it.

I tried this code to send the message:

#include <NMEAGPS.h>
#define gpsPort Serial // pin 0 to GPS TX and pin 1 to GPS RX
NMEAGPS GPS;
gps_fix fix; // a structure that contains all the GPS pieces, like lat/lon


//============================ Setup ======================================//

void setup() {

  Serial.begin(9600);
  Serial.println( F("NeoGPS library + GSM test!") );

  // gpsPort.begin(9600);
  GPS.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC+GGA
  GPS.send_P( &gpsPort, F("PMTK220,1000") ); // 1Hz
  GPS.send_P( &gpsPort, F("PGCMD,33,0") ); // No antenna status
  
  Serial.println();
  delay(5000);

  GPS.send_P( &gpsPort, F("PMTK161,0") );
  
  Serial.println();
  delay(5000);

  GPS.send_P( &gpsPort, F("P") ); // send byte to wake up module
  
  //GPS module will return {"$PMTK010,002*2D\x0D\x0A"} and start normal operation.
}

//=============================== Loop ===================================//

void loop() {
  /*
    // if a sentence is received...
    if (GPS.available( gpsPort )) {
      fix = GPS.read(); //  get the latest pieces
      readGPSdata();
    } */
}

//=============================== Functions ===============================//

void readGPSdata()
{
  // if a sentence is received...
  // if (GPS.available( gpsPort )) {
  //   fix = GPS.read(); //  get the latest pieces

  if (fix.valid.location) {
    Serial.print( F("We have a fix!") );
  } else
    Serial.print( F("We dont have a fix!") );

  Serial.print( F("\nLocation: ") );
  if (fix.valid.location) {
    Serial.print( fix.latitude(), 6);
    Serial.print( F(", ") );
    Serial.print( fix.longitude(), 6);
  }

  Serial.print( F("\nSatellites: ") );
  if (fix.valid.satellites) {
    Serial.print( fix.satellites );
  }

  Serial.print( F("\nFix: ") );
  if (fix.valid.status) {
    Serial.println(fix.status);
  }
  Serial.println();
}

Does this look correct?

Im not getting any reduction in current :slightly_frowning_face:

This is the output from the serial monitor:

NeoGPS library + GSM test!
$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,028
$PMTK220,1000
1F
$PGCMD,33,0*6D

$PMTK161,0*28

$P*50

I have also tried connecting directly to the GPS from the FTDI. The TX from FTDI flashes when I send the message.

I tried sending:

$PMTK161,0*28\x0D\x0A
$PMTK161,0

Still no joy.

I assume that the Arduino TX pin 1 is connected to the GPS RX pin. Otherwise, the GPS device will never receive a command. If it is connected properly, this code might be the problem:

GPS.send_P( &gpsPort, F(“PMTK161,0”) );

Serial.println(); ← this probably cancels the standby command
delay(5000);

GPS.send_P( &gpsPort, F(“P”) ); // send byte to wake up module

It looks like you are sending bytes immediately after the standby command. Anything you send to Serial is sent to gpsPort. They are the same port.

You do not need the extra println, because send_P already sent the CR/LF required by the NMEA standard. It may be waking the device immediately.

Yes, the 328p TX is connected to GPS RX.

Something strange though, on the FTDI, (after I uploaded the code) Im sure I didn't see the TX LED flash when closing and opening the serial monitor at the point the message was sent to the GPS module, which is why I connected the module directly to the FTDI.
When sent the message it did flash the TX but still didn't change the consumption.

I actually tried it without the Serial.println(); (I think) but it still didn't work.

I added the println after to clearly separate the messages, didn't realise that could be enough to wake the module though.

I will remove and retry without the println to confirm.

From snippets I found online (where you have helped others) I didn't realise the GPS.send_p setup commands were for the MTK platform to select the RMC & GGA the HZ rate and the antenna status.

I even changed the rate message from F("PMTK220,1000") ); 1HZ to F("PMTK220,10000") ); 10HZ to see if there was any change. It seemed to stay at the same rate.

Thanks /dev

I even changed the rate message from F("PMTK220,1000") ); 1HZ to F("PMTK220,10000") ); 10HZ

That would change the interval to 0.1Hz, or one update every 10 seconds. The PMTK220 parameter is the number of milliseconds between updates (period, not frequency).

Yes, sorry it is the interval of position fix, this is what i meant to put $PMTK220,100*2F 10HZ (I just wanted to try anything to see if messages were getting through)

I just tried it without the Serial.println and just sent the message once in setup() and Loop() was empty as below:

#include <NMEAGPS.h>
#define gpsPort Serial // pin 0 to GPS TX and pin 1 to GPS RX
NMEAGPS GPS;
gps_fix fix; // a structure that contains all the GPS pieces, like lat/lon


//============================ Setup ======================================//

void setup() {

  Serial.begin(9600);
  Serial.println( F("NeoGPS library + GSM test!") );

  // gpsPort.begin(9600);
  GPS.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC+GGA
  GPS.send_P( &gpsPort, F("PMTK220,1000") ); // 1Hz
  GPS.send_P( &gpsPort, F("PGCMD,33,0") );   // No antenna status

  GPS.send_P( &gpsPort, F("PMTK161,0") );    // change GPS to standby mode
}

//=============================== Loop ===================================//

void loop() {
/*  
    
    // if a sentence is received...
    if (GPS.available( gpsPort )) {
      fix = GPS.read(); //  get the latest pieces
      readGPSdata();
    }
 
*/
}

//=============================== Functions ===============================//

void readGPSdata()
{
  // if a sentence is received...
  // if (GPS.available( gpsPort )) {
  //   fix = GPS.read(); //  get the latest pieces

  if (fix.valid.location) {
    Serial.print( F("We have a fix!") );
  } else
    Serial.print( F("We dont have a fix!") );

  Serial.print( F("\nLocation: ") );
  if (fix.valid.location) {
    Serial.print( fix.latitude(), 6);
    Serial.print( F(", ") );
    Serial.print( fix.longitude(), 6);
  }

  Serial.print( F("\nSatellites: ") );
  if (fix.valid.satellites) {
    Serial.print( fix.satellites );
  }

  Serial.print( F("\nFix: ") );
  if (fix.valid.status) {
    Serial.println(fix.status);
  }
  Serial.println();
}

Still no change.

Am I actually sending the message correctly?

This is the output from serial monitor, it seems the checksums have been added:

NeoGPS library + GSM test!
$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,028
$PMTK220,1000
1F
$PGCMD,33,06D
$PMTK161,0
28

Is there any other message you can think of that I could send to test if the module is receiving messages?

If not I will get another module and maybe use a mosfet for this one.

Update…

I just found out I was sending the correct command after all to enter standby mode but the problem was I failed to leave any delay after sending each command.

I added a delay after each command and now it enters standby mode successfully and the consumption has reduced from 22mA to 1mA!

For anyone that may find it useful, here is the code, for sending (MTK Platform (MediaTek Inc.)) commands that reduce the GPS current, it also uses the NeoGPS library to parse GPS data.
After 10 seconds in standby mode it wakes then outputs location if has a fix.

#include <NMEAGPS.h>
#define gpsPort Serial // pin 0 to GPS TX and pin 1 to GPS RX
NMEAGPS GPS;
gps_fix fix; // a structure that contains all the GPS pieces, like lat/lon


//============================ Setup ======================================//

void setup() {

  Serial.begin(9600);
  Serial.println( F("NeoGPS library & current reduction test!") );

  // gpsPort.begin(9600);
  GPS.send_P( &gpsPort, F("PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC+GGA
  delay(50);
  GPS.send_P( &gpsPort, F("PMTK220,1000") ); // 1Hz
  delay(50);
  GPS.send_P( &gpsPort, F("PGCMD,33,0") );   // No antenna status
  delay(5000);                               // wait 5 seconds before standby mode

  Serial.println( F("") );
  Serial.println( F("In GPS standby mode for 10 seconds...") );
  GPS.send_P( &gpsPort, F("PMTK161,0") );    // send standby mode command to GPS (current = 1.02MA)

  delay(10000);
  Serial.println( F("") );

  //GPS.send_P( &gpsPort, F("P") );          // wake module send a byte (current = 21.9MA)
  Serial.println( F("GPS awake now...") );   // or will wake on Serial.print
  Serial.println( F("") );
}

//=============================== Loop ===================================//

void loop() {

  readGPSdata();
}

//=============================== Functions ===============================//

void readGPSdata()
{
  // if a sentence is received...
  if (GPS.available( gpsPort )) {
    fix = GPS.read(); //  get the latest pieces

    if (fix.valid.location) {
      Serial.print( F("We have a fix!") );
    } else
      Serial.print( F("We dont have a fix!") );

    Serial.print( F("\nLocation: ") );
    if (fix.valid.location) {
      Serial.print( fix.latitude(), 6);
      Serial.print( F(", ") );
      Serial.print( fix.longitude(), 6);
    }

    Serial.print( F("\nSatellites: ") );
    if (fix.valid.satellites) {
      Serial.print( fix.satellites );
    }

    Serial.print( F("\nFix: ") );
    if (fix.valid.status) {
      Serial.println(fix.status);
    }
    Serial.println();
  }
}

Has anyone managed to reduce the current lower than 1mA by sending commands to one of these modules?

itmoto:
I just found out I was sending the correct command after all to enter standby mode but the problem was I failed to leave any delay after sending each command.

I would suggest the failure is not a lack of delay but that your software does not check that the command sent has been correctly acknowledged.

srnet:
I would suggest the failure is not a lack of delay but that your software does not check that the command sent has been correctly acknowledged.

How would you check that the command has been correctly acknowledged?
The datasheet doesn't say it returns anything after sending the standby command?

It does say "Issue any byte to wake up GPS module, the GPS module will return {"$PMTK010,002*2D\x0D\x0A"}and start normal operation."

It also says "User can issue software command to make GPS module go into standby mode that consumes less than 200uA current."

I am measuring 1mA in standby mode. Do you think the regulator is using the 800uA?