kjgregory kjgregory - 6 months ago 35
Python Question

changing update rate with gpsd and python

I'm using the adafruit ultimate GPS breakout with my Raspberry Pi 2 using python2.7.9, GPSD, and the python-gps package. I'm successfully getting gps updates at 1Hz over the serial port.

This device is supposedly capable of 10Hz updates, which I would like to enable. According to the datasheet (see snippet below), this can be set by serial command.

enter image description here

My problem is that I can't find sufficient documentation for the python-gps module or GPSD that would tell me how I'm supposed to send commands to the GPS over serial with my python script. Can someone point me in the right direction?

Answer

I just picked up a gps from the same family as yours. (MTK) They use $PMTK control strings. Any search for PMTK protocol gives endless resources. The limit is the gps itself.

For a one-off conversion, the standard method is from a root terminal execute echo -e "\$PMTK220,200*2C\r\n" > /dev/ttyAMA0, or wherever the device is attached, for a 5Hz response. The

  • -e flag allows parsing the backslash(s)
  • $ The start of the NMEA sentence
  • P Proprietary message
  • MTK NMEA Data type
  • 220 Packet type
  • 200 Packet data
  • * End of data
  • 2C Checksum
  • \r\n The end of the NMEA sentence

There are scripts and other projects available as well, but all require the gpsd to not be in control of the gps. The gpsd will prevent sending a control string to the gps.

Additionally, if you have the -b flag in /etc/default/gpsd the gpsd will not write to the device when it is attached. It will choose a generic NMEA driver, and will not write any control strings to the gps.

Port speed is not an issue, as long as there is capacity. Someone who counted once said 4800 baud is sufficient for one reading of data in the one second it takes to send the data. It depends on payload, but it works for a rule of thumb. 10Hz might make the 38400 baud default on many systems. I tried it and nothing broke.

You just want to make sure gpsd hasn't negotiated to 9600 baud before you can ramp up the speed, just in case. gpsctl -s XXXX (to set the baud rate at which the GPS emits packets) returns an error for me.

But it appears, gpsd keeps with the 1 second timing, regardless. Even if the gps is capable of faster cycles, even if you have already use another methods to re/set the rate the gpsd needs to be told, go faster

This is where gpsctl -c 0.2 (no sudo) comes into play. It is bundled in the gpsd package.

If there is only one device connected to the gpsd, in the example, gpsctl will change that device to 0.2 second timing cycles. Time in seconds. Yes, you can make it pretty slow, but there's no faking ability. If it can't do it, it won't do it, nor tell you that it hasn't/can't, unless there is a fatal error.

Even without the -bflag in the gpsd default setting, this new gps of mine doesn't stay latched into the higher frequency updates between powerdowns. I must re-issue the command. It might be a bad battery, operator error, or I don't understand this defect is a feature to not latch the gps out of reach for other systems. (A reason for the -b)

This is how you change the response from a gps that uses the gpsd, or how I did.

In answering your question, however, to change the rate of a gps response through the gpsd with Python

import subprocess
subprocess.call(['gpsctl', '-c', '0.2'])  # Digits are the time in seconds.

Try it and see.

To help are two Python gpsd client demonstration scripts to which I have just added a gpsd device report refresh keystroke, (Hit d to refresh and see the numbers from the new setting.)

They are for a Python 2.7-3.5 gpsd python client, when the function finds a home in the demo scripts it will look something like this:

def hertz(hz):
    """Change or enumerate a Faster/Slower gps refresh rate if device is able"""
    from subprocess import call
    inverse = str(1 / hz)
    call((['gpsctl', '-c', inverse]))