0

I am trying to debug why the magnetic sensor of my MPU9250/6500 9-Axis 9 DOF 16 Bit Gyroscope Acceleration Magnetic Sensor IIC/SPI won't connect to my Raspberry Pi 4+, but all the other sensors will. I am using the MPU-9250-Sensors-Data-Collect API which is a wrapper for the SMBUS2 package. Given that there seems to be only one master address and only two wires connecting things, I would think that if the problem was something physical, it would either work or not work, except that this sensor is a multi-chip module consisting of two dies integrated into a single QFN package. I did a bad soldering job on my first one of these sensors and it just wouldn't connect. I got a new one and it is detected by my RPi and works except for the magnetic sensor (the most relevant part of my project).

So. my question is, is this a hardware thing after all, or is there the possibility of it being a software problem?

I can't see any problems with the physical unit:

Photo of my setup

Code

    import sys
    sys.path.append('/home/tor/robot/MPU-9250-Sensors-Data-Collect/MPU-9250-Sensors-Data-Collect/mpu9250_jmdev')
    from registers import *
    from mpu_9250 import MPU9250
    import time
    import logging
    ##################################################
    # Create                                         #
    ##################################################
    mpu = MPU9250(
        address_ak=AK8963_ADDRESS, 
        address_mpu_master=MPU9050_ADDRESS_68, # In 0x68 Address
        address_mpu_slave=None, 
        bus=1, 
        gfs=GFS_1000, 
        afs=AFS_8G, 
        mfs=AK8963_BIT_16, 
        mode=AK8963_MODE_C8HZ)
    ##################################################
    # Configure                                      #
    ##################################################
    mpu.configure() # Apply the settings to the registers.
    ##################################################
    # Show Values                                    #
    ##################################################
    while True:
        print("|.....MPU9250 in 0x68 Address.....|")
        print("Accelerometer", mpu.readAccelerometerMaster())
        print("Gyroscope", mpu.readGyroscopeMaster())
        print("Magnetometer", mpu.readMagnetometerMaster())
        print("Temperature", mpu.readTemperatureMaster())
        print("\n")
        time.sleep(1)

Results

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 97, in configure
    self.configureAK8963(self.mfs, self.mode)
  File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 233, in configureAK8963
    self.writeAK(AK8963_CNTL1, 0x00, 0.1)
  File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 1013, in writeAK
    self.bus.write_byte_data(self.address_ak, register, value)
  File "/usr/local/lib/python3.8/dist-packages/smbus2/smbus2.py", line 458, in write_byte_data
    ioctl(self.fd, I2C_SMBUS, msg)
OSError: [Errno 121] Remote I/O error

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 97, in configure self.configureAK8963(self.mfs, self.mode) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 233, in configureAK8963 self.writeAK(AK8963_CNTL1, 0x00, 0.1) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 1013, in writeAK self.bus.write_byte_data(self.address_ak, register, value) File "/usr/local/lib/python3.8/dist-packages/smbus2/smbus2.py", line 458, in write_byte_data ioctl(self.fd, I2C_SMBUS, msg) OSError: [Errno 121] Remote I/O error

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "sensorTest.py", line 13, in <module> mpu.configure() # Apply the settings to the registers. File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 102, in configure self.configure(retry - 1) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 102, in configure self.configure(retry - 1) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 105, in configure raise err File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 97, in configure self.configureAK8963(self.mfs, self.mode) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 233, in configureAK8963 self.writeAK(AK8963_CNTL1, 0x00, 0.1) File "/usr/local/lib/python3.8/dist-packages/mpu9250_jmdev/mpu_9250.py", line 1013, in writeAK self.bus.write_byte_data(self.address_ak, register, value) File "/usr/local/lib/python3.8/dist-packages/smbus2/smbus2.py", line 458, in write_byte_data ioctl(self.fd, I2C_SMBUS, msg) OSError: [Errno 121] Remote I/O error

If I put try/except blocks around smbus2.py (ioctl(self.fd, I2C_SMBUS, msg)), I can get data for the other three sensors:

|.....MPU9250 in 0x68 Address.....|
Accelerometer [-1.210205078125, -8.0, -8.0]
Gyroscope [43.9453125, -1.373291015625, -21.270751953125]
[OSError(121, 'Remote I/O error'),
 <smbus2d.SMBus object at 0xffff8d0f20a0>,
 12,
 3,
 7,
 None]
Magnetometer [0.0, 0.0, 0.0]
Temperature 24.258753407014705

What the offending function looks like:

    def read_i2c_block_data(self, i2c_addr, register, length, force=None):
        """
        Read a block of byte data from a given register.
    :param i2c_addr: i2c address
    :type i2c_addr: int
    :param register: Start register
    :type register: int
    :param length: Desired block length
    :type length: int
    :param force:
    :type force: Boolean
    :return: List of bytes
    :rtype: list
    &quot;&quot;&quot;
    if length &gt; I2C_SMBUS_BLOCK_MAX:
        raise ValueError(&quot;Desired block length over %d bytes&quot; % I2C_SMBUS_BLOCK_MAX)
    self._set_address(i2c_addr, force=force)
    msg = i2c_smbus_ioctl_data.create(
        read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA
    )
    msg.data.contents.byte = length
    try:
        ioctl(self.fd, I2C_SMBUS, msg)
    except Exception as e:
        if hasattr(e, 'message'):
            print(e.message)
        pprint([e, self, i2c_addr, register, length, force])
    return msg.data.contents.block[1:length + 1]

The sensor is readable, however:

tor@tor:~/robot$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --        

Thanks!

SomeoneElse
  • 109
  • 4

3 Answers3

1

Question

Problem on using smBUS 2 block read/write functions.


Answer

1. Discussion on I2C reading/writing a block of data, smbus and smbus2, etc

Ah, your remind me one important thing. Some two years ago when I tried to use smBus block read/write (in my MCP23017 Micky Mouse toy project), I found the "bus stretch" thing is not implemented, so block read/write won't work.

One quick and dirty workaround is to lower i2c bus speed to as low as 50kHz (as recommended by one MagPi writers.

The same MagPi issue also recommends to use Borsh 9-DOF, not sure if also built in the Rpi's official Sensor Hat.

One other thing is that I don't seem to find you importing smbus. Are you using AdaFruit's libraries? I heard that AdaFruit Circuit Python is not 100% compatible to Rpi, so their might be teething problems not yet solved.

Another suggestion is to use 1-DOF Magneto modules, then at least you won't have three separate I2C devices (and perhaps more?) sitting on the same bus, overloading bus beyond the smbus 400pF limit.


References

(1) Intelligent-Vehicle-Perception - MPU9250 (MPU6500 + AK8963) I2C Driver in Python for Raspbery PI

(2) AliExpress Magnetometer Catalog

(3) LSM303DLHC Ultra-compact high-performance eCompass modu le 3D accelerometer and 3D magnetometer - ST

(4) GY-511 LSM303DLHC 3-DOF Magnetometer / Digital Compass sensor - ¥14

(5) GY-271M 3-DOF Magnetometer (replace HMC5883L HMC5983 GY-282 283 GY-273) - ¥19


Appendices

Appendix A - List of MMES Magnetometer Modules

  1. HMC5883L GY-271/273 Magnetometer Compass Module

  2. LSM303DLHC GY511 Magnetometer Compass Module

  3. HSCDTD008A Magnetometer Compass Module

  4. RM3100 Magnetometer Compass Module


tlfong01
  • 4,847
  • 3
  • 12
  • 24
1

I recently have this problem as well and got the exact error as you do, and it seems that the AK8963_ADDRESS refers to address 0x0c (12), so I changed the address_ak to 0x69 (as the MPU9250 is on 0x69 for me) and it works fine again.

    mpu = MPU9250(
        address_ak=0x69, 
        address_mpu_master=0x69,
        address_mpu_slave=None, 
        bus=1, 
        gfs=GFS_1000, 
        afs=AFS_8G, 
        mfs=AK8963_BIT_16, 
        mode=AK8963_MODE_C8HZ)

My result for i2cdetect -y 1

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- 41 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --     
Joe Siu
  • 11
  • 1
0

I read somewhere that the magnetometer can be accessed via address 0x0c on a slave i2c bus of the mpu9250.

So, first the slave i2c bus of the mpu9250 must be configured.

Fred
  • 1