Setting Bluetooth GPS Receiver to 10hz

If you build a 10hz Bluetooth GPS receiver, as described in my other article, it will default to 1hz. This is of course useless, since the whole point is to get more frequent GPS updates. Here’s how to configure the unit for 10hz.

These instructions apply any GPS modules that use a U-Blox submodule. This includes the Reyax RYN725AI referenced in the kit. It also works with the cheaper Reyax RYN25AI, but the 10hz setting won’t be permanently saved unless you add an EEPROM later.

There are three different ways to do this, in order of easiest to most annoying.

Using the Android App

I wrote up a quick Android app to perform set the unit to 10hz and save the config. If you’re planning to run Harry’s Lap Timer or RaceChrono on Android, this is the easiest method.

The app is available for free in the Google Play Store.

Pair the receiver with your phone for use with Harry’s or RaceChrono. Then, simply run the GPS 10hz Autosetter.

Pick out your bluetooth device from the list and hit Select. Then, hit “Set GPS to 10hz”. That’s it. It will display its progress and let you know if there were any issues. The app will also read the current setting, to ensure it was set correctly.

The app will remember which GPS device you chose the next time you run it. You can use the triple-dot menu in the top right to select a different device.

Select your new GPS receiver from the list

Select your new GPS receiver from the list

Then, hit "Set GPS to 10hz" and let the app do its thing

Then, hit “Set GPS to 10hz” and let the app do its thing

Setting the GPS module rate with Windows

Note: Apparently Windows doesn’t support bluetooth serial ports very well. I had weird issues with this. Long story short, I figured out what u-center is sending and wrote up a python script that uses pyserial to do the same thing. The script is in the next section.

The GPS module unfortunately defaults to a 1hz sample rate, meaning it reports the GPS location once per second. It’s capable of 10hz, however, which is the whole point of this. It can be permanently set to 10hz with a one-time software change using a Windows laptop over Bluetooth.

The first thing to do is power up the fully assembled device. The GPS module will blink as it acquires signal. The bluetooth module will blink red meaning it isn’t connected to anything. On a Windows computer with bluetooth, add a new bluetooth device. Doing this depends on your version of windows, just google it. If you search for devices, you should see HC-06 in the menu. Go ahead and add it. Once you’re done, you may get a pop-up in the system trya that a new com port was added. This is a good thing.

Now you need u-blox u-center: https://www.u-blox.com/en/product/u-center-windows It is free to use.

Connect to a com port

Connect to a com port

Once it loads, click the dropdown to connect a com port. This should be whatever com port you saw added in the last step. If you didn’t see that, try any com port.

View configuration to see the configuration window

View configuration to see the configuration window

If it connects, the box should turn green. (Like in the next picture.) You can then go to View -> Configuration View to pop up the configuration window.

Set "Measurement Period" to 100ms

Set “Measurement Period” to 100ms

In u-center, go to “RATE” in the left-hand box. Then, change “Measurement Period” from 1000 to 100. This will sample every tenth of a second rather than every second, giving us our 10hz or ten-times-per-second rate. Click Send to push this to the GPS receiver.

Click "send" to save the config, ensuring you're saving to all possible devices

Click “send” to save the config, ensuring you’re saving to all possible devices

The above set the new rate temporarily, but we want to save it to EEPROM or flash, and battery-backed RAM so it stays this way permanently. It’s really saving to EEPROM or flash that matters. Which one depends on your chip, but you should be able to select all 4 options, and it should work either way. Scroll up in the left hand pane to “CFG (Configuration)”. Make sure the radio button is on “Save current configuration” and all the Devices are selected as pictured. Then click Send. You should now be ready to hook it up to your phone.

Using the Python script to set it to 10hz

As I mentioned, I was having problems getting windows to connect properly. I went back in Ubuntu and used socat to proxy the serial port to TCP, then used a Windows VM with u-center on it to connect with TCP and make the change. This all annoyed me though, so I recorded what was sent and came up with a script to set the GPS to 10hz and save it. It *appears* to work, but obviously use this code at your own risk. I have tested with exactly two units. It will attempt to save the configuration to Battery Backed Ram, EEPROM, and Flash, so it should work with any of the possible chip setups.

The script is designed to run on Linux with a serial port at /dev/something. If you open the right port, it should work on OSX or Windows also. Also, you really just need to set the bytes in the file in the order presented, so it should be easy to adapt to something else. You need the “pyserial” module as well, available in pip.


#!/usr/bin/python

# Written by James Spadaro
# Copyright Spadaro Technology, LLC 2016
#
# u-blox provides documentation on their protocol that is used below

import serial
import struct
import sys

serialName = raw_input("What serial device? (Example: /dev/rfcomm0): ")
ser = serial.Serial(serialName, timeout=1.0)

# Function to return the current refresh rate
def getRate():
    # Poll the GPS unit for navigation rate settings
    # by sending an empty "poll rate settings" message
    # General format of this message:
    # \xb5\x62 = sync chars
    # \x06 = class CFG
    # \x08 = ID for CFG-RATE message
    # Next two bytes are length of message
    # Message has no contents (because we're polling for rate)
    # Final two bytes are checksums
    print "Sending request to check rate..."
    ser.write("\xb5\x62\x06\x08\x00\x00\x0e\x30")

    # Look for the result to see what the rate is
    # It will be formatted just like above, except with message contents
    # The key message contents are the first two bytes, which are the measure rate
    # in milliseconds
    found = False
    attempts = 0
    while not found:
        if attempts > 10:
            # Try sending the request again every 10 seconds
            print "No response yet, resending request..."
            ser.write("\xb5\x62\x06\x08\x00\x00\x0e\x30")
            attempts = 0
        
        result = ser.read(4096)
        try:
            responseIndex = result.index("\xb5\x62\x06\x08")
            length = struct.unpack("<H", result[responseIndex+4:responseIndex+6])[0]
            if length != 6:
                print("Got a weird response length: {0}".format(length))
                print("Quitting...")
                sys.exit(1)
            
            contents = result[responseIndex+6:responseIndex+6+6]
            updatePeriod = struct.unpack("<H", contents[0:2])[0]
            rate = int((1.0/(float(updatePeriod)/1000.0)))
            return rate
        except ValueError:
            # No response yet
            attempts += 1
            pass

try:
    ser.read(4096)
    rate = getRate()
            
    if rate < 10:
        print("Update rate is {0}hz.  Going to try to fix that...".format(rate))
    else:
        print("Update rate is already {0}hz.  The GPS should already be good to go, not doing anything else.".format(rate))
        ser.close()
        sys.exit(0)

    # Send commands to set to 10hz if necessary
    print("Attempting to set 10hz...")
    ser.write("\xb5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x01\x00\x7a\x12")
    ser.read(4096)
    # Save to EEPROM, both types of flash, and BBR
    print("Sending save config...")
    ser.write("\xb5\x62\x06\x09\x0d\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x17\x31\xbf")
    ser.read(4096)
    
    newRate = getRate()
    if newRate < 10:
        print("New rate is now 10hz, all set.")
    else:
        print("The new rate is only {0}hz, not sure what went wrong?".format(rate))
finally:
    ser.close()

Conclusion

And that’s it. The Windows application allows you to make other configuration changes and get more debug output, but i found it a much bigger pain to use.