Due to high demand expect some shipping delays at this time, orders may not ship for 1-2 business days.
0

Binary GPS data over I2C
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Binary GPS data over I2C

by boredsurfr on Thu Apr 15, 2021 11:22 am

I'm trying to read binary GPS data from a Sparkfun chip over I2C on the Clue (the NMEA data do not include speed accuracy, which I need) using Circuitpython. I am using adafruit_gps as a starting point.

The problem I have is that I get a lot of xff (255) bytes.

I am using adafruit_gps.GPS_GtopI2C. Here's the code:
Code: Select all | TOGGLE FULL SIZE
import time
import board
import adafruit_gps
import adafruit_bus_device.i2c_device as i2c_device
import digitalio

i2c = board.I2C()

gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # Use I2C interface

while cnt < 500:
    result = gps.read(1)
    print(result[0], ",", flush=True,end='')    [/quote]


Some example output:
Code: Select all | TOGGLE FULL SIZE
code.py output:
255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,181 ,98 ,1 ,33 ,20 ,0 ,176 ,13 ,223 ,23 ,44 ,0 ,0 ,0 ,249 ,210 ,248 ,255 ,229 ,7 ,4 ,15 ,15 ,14 ,36 ,55 ,78 ,109 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,181 ,98 ,1 ,33 ,20 ,0 ,104 ,25 ,223 ,23 ,44 ,0 ,0 ,0 ,88 ,212 ,248 ,255 ,229 ,7 ,4 ,15 ,15 ,14 ,39 ,55 ,118 ,65 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,181 ,98 ,1 ,33 ,20 ,0 ,32 ,37 ,223 ,23 ,43 ,0 ,0 ,0 ,185 ,213 ,248 ,255 ,229 ,7 ,4 ,15 ,15 ,14 ,42 ,55 ,158 ,18 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,255 ,181 ,98 ,1 ,33 ,20 ,0 ,216 ,48 ,223 ,23 ,43 ,0 ,0 ,0 ,26 ,215 ,
Code done running.

It seems that the read method returns a 255 whenever there are no actual data available. Is there a way around this? I cannot just check for 255 since the binary data may contain that value. A check like "if not char:", as used in GPS_GtopI2C.readline, does not help.
I vaguely recall something about using interrupts for I2C communication (since there is no "available()" function), but could not find a code example. Are there any code example, or any other suggestions?

boredsurfr
 
Posts: 3
Joined: Thu Apr 15, 2021 10:12 am

Re: Binary GPS data over I2C

by boredsurfr on Thu Apr 15, 2021 8:39 pm

According to the u-blox receiver specification, the 255 is what the GPS returns when a read is requested, but no data are available.

According to the specification, it should be possible to write a single byte with the register address xFD, and then get the number of available bytes reading 2 bytes (that's what the Sparkfun C++ library code does). But when trying to write a single byte, the first problem is that the adafruit_gps.write() expects a buffer. When using a bytearray of length one, the code runs, but does not return the number of bytes available; instead, it returns the same bytes as when reading directly (lots of 255s and the occasional UBX sentence).

It seems adafruit_gps is not a decent starting point, anyway, since it is entirely devoted to reading NMEA, and low data rates. It's interesting how def read(self, num_bytes) iterates through num_bytes, reading a single byte at a time. It looks like this could cause a lot of overhead in the communication.

boredsurfr
 
Posts: 3
Joined: Thu Apr 15, 2021 10:12 am

Re: Binary GPS data over I2C

by boredsurfr on Fri Apr 16, 2021 6:44 pm

Here's code that asks the u-blox GPS how many bytes are available, and then reads them:
Code: Select all | TOGGLE FULL SIZE
# Example to query a u-blox GPS over I2C how many bytes are available to read,
# and then read them.
import time
import board
import adafruit_bus_device.i2c_device as i2c_device

i2c = board.I2C()
device = i2c_device.I2CDevice(i2c, 0x42)
cnt = 0

while cnt < 10:
   
    # 0xFD (MSB) and 0xFE (LSB) are the registers that contain number of bytes available
    btArrayOut = bytearray([0xFD])
    registerContent = bytearray(2)

    with device:
        device.write_then_readinto(btArrayOut, registerContent)
   
    bytesAvailable = int.from_bytes(registerContent, 'big')   
    print("Bytes available: = ", bytesAvailable)

    if bytesAvailable > 0:
        numToRead = min(100, bytesAvailable)
        data = bytearray(numToRead)
        with device:
            device.readinto(data)
        print(data)
        cnt = cnt + 1
    else:
        time.sleep(1)

boredsurfr
 
Posts: 3
Joined: Thu Apr 15, 2021 10:12 am

Please be positive and constructive with your questions and comments.