NEO 6Q with Raspberry Pi2B over I2C

0 votes

I am having partial success in reading/writing to a 6Q via I2C from a RPi2 using the built-in interface, i2c_bcm2708 

I can read the NMEA stream, byte-by-byte, with this (abbreviated) code. I don't see bad characters, and it seems to run without lockup:

#include <linux/i2c-dev.h>
fd = open("/dev/i2c-1",O_RDWR);
ioctl(fd, I2C_TIMEOUT, 120 * MSECS_PER_SEC / 10);
ioctl(fd, I2C_SLAVE, 0x42);
for (...) {
   for (...) {
       int i = i2c_smbus_read_byte(fd);
       if (i < 0) error();
       if ((i & 0xff) == 0xff) break;
    }
    usleep(USECS_PER_SEC / 4);
}

Block transfers, with i2c_smbus_read_i2c_block_data() do not seem to work, returning gibberish.  Also if I try to read the number of bytes available from registers 0xfd and 0xfe with i2c_smbus_read_byte_data(fd,reg) I just receive the next character in the NMEA stream.

Trying to read using the I2C_RDWR ioctl does not work, though the first character received is '$', which makes it look like it's almost working.  I tried "echo 1 > /sys/module/i2c_bcm2708/parameters/combined" but that didn't help.

However I have to use the I2C_RDWR ioctl to write to the Ublox. The following code works, for example to disable VTG messages:

string disvtg = "$PUBX,40,VTG,0,0,0,0,0,0*5e\r\n";  // disable VTG

struct i2c_msg rdwr_msgs[1];
struct i2c_rdwr_ioctl_data rdwr_data;

rdwr_msgs[0].addr = 0x42;
rdwr_msgs[0].flags = 0; // write
rdwr_msgs[0].len = disvtg.length();
rdwr_msgs[0].buf = (char*) disvtg.c_str();

rdwr_data.msgs = rdwr_msgs;
rdwr_data.nmsgs = 1;

int res = ioctl(fd, I2C_RDWR, &rdwr_data );

However if I try to write the string byte-by-byte with i2c_smbus_write_byte(fd,b) the disable does not take effect.

I've seen posts where folks have given up, and resorted to bit-banging.

The above, rather unsatisfactory, code may work for my application, but it would be nice if to hear if anyone has found a better solution.

 

by Gordon Maclean asked Jun 14, 2016
by Gordon Maclean edited Jun 15, 2016
389 views
0 votes
Do not have code suggestions but the fact that you are getting next character from NMEA string when trying to read 0xFD or 0xFE registers would mean that pointer is still at 0xFF location.  Something is not getting set right.
by grumpy answered Jun 14, 2016
The problem appears to be related to the clock-stretching problem that is seen when reading some I2C devices from a Pi, with the i2c_bcm2708 module: https://github.com/raspberrypi/linux/issues/254.
I've tried reducing the i2c baudrate from 100K to 32K, and 8K and I then see a correct length value from registers 0xfd and 0xfe, but still a small %-age of bad characters in the NMEA stream.
May be due to long lines or load capacitors.  Check NEO-6 Hardware Integration manual for recommended capacitance and pull-up resistors values.  System got to be balanced on HW side to support higher data rates.
The ublox is on an in-house "HAT" board on the Pi, with short runs.  The Pi  has 1.8 K pull-ups on the clock and data lines. The signals look OK on a scope.
u ever figure this out? I want gps on a project but not a constant uart stream...think more, other sensor detects event, record location. pi's i2c seems to be pretty special ed from what im starting to gather.