Software is fundamentally flawed


So, after a week of trying to get the XLoBorg accelerometer to respond in fashion dictated by the datasheet for the chip,it turns out that smbus, or rather the Pi's SoC (BM2835) does not support repeated START sequences, making it almost useless for chip control on the i2c bus. There is a good discussion at for the curious.

I tried both the XLoBorg smbus wrapper and the Quick2Wire Python 3 library with similar results. Using the Perl HiPi utility as suggested in the above link, does indeed verify that all is not well. For the very curious, insert the following at line 159of the file:

    #check whoami
    bus.write_byte(addressAccelerometer, 0x0D)
    ret = bus.read_byte(addressAccelerometer)
    if ret != 0x2A:
        Print('Cannot match whoami data byte')

It will fail because the read is apparently done from register 0x00 (the default base) instead of the requested 0x0D,and returns 0xFF instead of the expected 0x2A. Using HiPi gets the correct result for the chip (0x2A) e.g.
pi@raspberrypi ~ $ hipi-i2c read 0 0x1C 0x0D

As an aside,I'm not sure that the lines starting L 151 in will work

    # System state
    register = 0x0B             # SYSMOD
    data = 0x01                 # Awake mode
        bus.write_byte_data(addressAccelerometer, register, data)
        Print('Failed sending SYSMOD!')

as according to the datasheet for the MMA8452Q, that is a read only register. That is my reading of it, and happy to accept I may be wrong, being new to chip programming. HiPi shows no change after a write to that register for comparison. i.e.
pi@raspberrypi ~ $ hipi-i2c write 0 0x1C 0x0B 1
pi@raspberrypi ~ $ hipi-i2c read 0 0x1C 0x0B
pi@raspberrypi ~ $ hipi-i2c write 0 0x1C 0x0B 2
pi@raspberrypi ~ $ hipi-i2c read 0 0x1C 0x0B

Anyway, appears to work, but not necessarily for the reasons the designer thought!

piborg's picture

As you say, the I2C support is a bit lacking on the Raspberry Pi, to get around this for the magnetometer we are reading a larger volume of data then we really need (see line 270 for example).

Is there any particular reason for you wanting to read the WHOAMI register?

As for the SYSMOD register it is indeed a mistake, but since the code has been released to the wild, plus the fact it will not hurt anything (it is just pointless) we decided to leave the code as it was so that we can refer to line numbers when answering questions.

How do you get the HiPi utility installed, it seems like it may be worth updating the code to use HiPi to read/write the bus and the installer package to setup HiPi.

It seems we have a few issues of this sort around the Raspberry Pi, the larger problem for us is the lack of the Kernel module build environment of building drivers in Raspbian, otherwise we might of written our own driver for this (I2C is simple enough).
The trouble is because of writing a driver for LedBorg paired with the lack of the proper Kernel headers / symbol information we have to manually produce a new build each time they make the Kernel incompatible in Raspbian, which has caused a lot of confusion for users...

why read 'whoami'? It's a simple enough additional check to ensure you are communicating with the correct chip particularly in an environment where there may be a multitude of devices present.

I'd taken up your challenge to write a fully functional compass and movement detection unit as per ;-) So my first step was to fully model the chip as much out of wanting to understand how it ticked, as that I wanted to completely abstract the chip to provide an app developer's API (I don't want to have to remember all those byte settings!) Happy to share the code if it helps the cause.

To get HiPi I simply followed the instructions from the provided link on the page ref I gave (or if anyone missed the link it is at I had to update CPAN and then install the LWS::Simple package as hipo installer borked, but despite taking quite a while to build all the dependencies, it was pretty painless.

I'm not a Perl programmer, so not inclined to dig into the code to see how it gets around the problem. However, it strikes me that they must be going through the same SoC chip? So how does their code manage when smbus doesn't? I know not, but worth a ponder.

piborg's picture

I think the problem is probably the drivers rather than the chip itself.

There are two bits of code that seem to be related to low-level I2C access, one in C:
the other in Perl:

both seem to drive the chip by talking to the chipset directly, curiously enough I had another board talking on I2C manually using C code back in the early days before the standard driver was ready, that needed a restart after sending some data and a checksum (see attached excerpt).

Excuse my ignorance, having only been at this a week or so, but is that the kernel 12c driver or the smbus lib that has the problem? Do you know of a place I can look to see if this issue has been raised with the upstream devs? Although probably, I'd be asking the wrong questions!

I found this: which is a Python wrapper for the C library as used by HiPi ( Any experience with it anyone?

piborg's picture

I believe the most likely culprit is the driver, since the library actually has a function with takes a register address to read from which does not work as expected.
It is still possible that the library does something slightly odd having said that.

I've been looking at the XLoBorg and noticed this discussion. Has the underlying C driver been fixed yet?

piborg's picture

I am not actually sure, but it is possible.

Raspbian has had significant changes made since this problem was noted, in particular the latest copies no longer show two I2C bus devices, just the one on the GPIO pins.

If it has not been fixed you could use hipi-i2c to perform the I2C commands instead.
You can use os.popen to run commands and get the output from within Python.

Subscribe to Comments for "Software is fundamentally flawed"