1

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
  • 111
  • 3
  • Could you clarify. Does the sensor appear on the bus? If so what number? If so have you tried an alternative method of reading the sensor? – joan May 04 '21 at 15:20
  • As I show in my question, the sensor is being picked up because when I do i2cdetect -y 1, it is #68. – SomeoneElse May 04 '21 at 17:53
  • So I just got another sensor just like the one I had and it has the same problem, I'm pretty sure it is a software problem but I am new to using I2C and so, as of yet, I have yet to have worked out what the problem is. – SomeoneElse May 04 '21 at 19:50

2 Answers2

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,665
  • 3
  • 10
  • 24
  • 1
    I'm using the API mentioned in the beginning, which in turn uses the python SMBus2 package ( https://pypi.org/project/smbus2/ ). I might just cut my losses from my time spent debugging this unit and take your suggestion to get something that is just a magnetic sensor because that is really all I think I need for my use case. – SomeoneElse May 04 '21 at 21:10
  • 1
    @SomeoneElse, OMG, I was not aware that you are using smBus2. Actually when I found the limitation of smBus of no bus stretching and therefore no block read/write, and that for Rpi3B+ stretch, there is a Rpi Foundation system bug that you cannot adjust I2C bus speed up or down (contrary to official document) except the flat rate of 100kHz. I was very disappointed and so googled for a turnaround. So I found smBUS2, and I thought that it might save my life. So I evaluated smBUS2, / to continue, ... – tlfong01 May 05 '21 at 00:42
  • 1
    Before I let you know my evaluation results of smBUS2, can you first tell me (1) Why you use smBUS2 and not standard default smBUS? (3) Have you tried other SPI alternatives, such as SPIpy? (3) What was your general feeling or first impress when switching to smBUS2, and how you feel about their mnaual? – tlfong01 May 05 '21 at 00:46
  • 1
    Oh, I'm using smBUS2 because that is what is used by the API I am using ( https://github.com/Intelligent-Vehicle-Perception/MPU-9250-Sensors-Data-Collect ) I am going to try another API, if I can find one that seems complete. I'm fairly new to I2C, so I think I will need to read up more on how it works. The issue is that there is still the chance that it is a physical problem (it could be the connecting wires for example). Anyway thanks for your suggestions! – SomeoneElse May 05 '21 at 02:32
  • 1
    (1) Thank you for your clarification and confirmation on smBUS2. (2) Your IVP(Intelligent-Vechicle-Perception)API wraps on smBUS2 and it is very likely that they also solves any teething problem about smBUS2, but not sure if they are compatible with Rpi4B buster python 3.7.3. (3) Your mpu9050 9-DOF with 4 MEMS sensor on one module is too complicated for newbies to debug. The magnetometer is decoupled from the other 3 sensors, so for newbies I would recommend to start off with the very popular 1-DOF HMC5883L Magnetometer Module for which you can find many Arduino references and tutorials. – tlfong01 May 05 '21 at 03:12
  • 1
    (4) What do you mean by "I have found another sensor but same problem, ..". Do you mean another item of the same model? (5) If you are trying out other vendors's 9-DOF or magnetometer hcips, are they (a) Magnetometer Module HMC5883L, or (b) 9-DOF BNO080? (6) I would recommend HMC5883L, because more people would help you if you are using this popular magneto module. – tlfong01 May 05 '21 at 03:13
  • 1
    I have appended Ref 2 in my reference list an AlliExpress catalog of magnetometers. If you can let me know which alternate magnetomenter you are now testing, I might (no guarantee, though) try to search my junk box for a similar one and test it along with you. I am 90% sure I have tested HMC5883L, some two years ago and found it OK. – tlfong01 May 05 '21 at 03:52
  • 1
    I ordered an Adafruit Triple-axis Magnetometer - LIS3MDL (STEMMA QT / Qwiic). Hopefully this will be more of what I'm looking for. (and thanks for all your help!!!) – SomeoneElse May 06 '21 at 15:15
  • 1
    @SomeoneElse, Just a quick reply. You remind me that some 2 years ago I was also a MEMS sensor newbie, so I did some research on which sensor (gyro, accelero, amgneto) to start off with. You might like to read my research report, as an answer of the following question, and perhaps let me know your comments. My research report is two year out of date. So I need to do some update, hopefully pretty soon. Cheers. Ref (1) Adafruit 9-DOF for Rpi: https://raspberrypi.stackexchange.com/questions/74865/adafruit-9-dof-or-other-accelerometer-magnetometer-gyroscope-sensor-for-raspberr – tlfong01 May 07 '21 at 00:51
  • Your LIS3MDL magneto seems popular. AliExpress MagnetoMeter Catalog (6 pages! :) ) https://www.aliexpress.com/w/wholesale-magnetometer.html. But I am not sure if it is a good choice, though usually only good things can be popular. Perhaps you can google some good reviews and tutorials and share with us, so more magneto newbies (me too!) might join in. Cheers. – tlfong01 May 07 '21 at 03:04
  • PS - I do have BNO080 9-DOF in hand. This is recommended by Mag Pi and used in Rpi's official sensor HAT. You might like to short list it for your current or future projects. – tlfong01 May 07 '21 at 03:07
  • @SomeoneElse, Just now I had a quick google and jumped to this quick conclusion (1) My HMC5883/5983 sensors are discontinued, not sure if replacements are compatible. (2) Your LIS3MDL seems very popular, and cheap (of course there are much more secpensive, but precise alternate devices). So *I would suggest newbies like me and you to try this LIS3MDL sensor, because it is cheap and simple (3-DOF) only *.. – tlfong01 May 07 '21 at 06:25
  • Suggestion. We have diverted too far from your original question. It you would like to try LIS3MDL which you have already in hand, *I would suggest you to ask a new question specifically on LIS3MDL*, so that everybody can start at the same beginning step. Cheers. – tlfong01 May 07 '21 at 06:28
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