kriswiner/MPU9250

I2C with Arduino Won't find MPU9250

abnoviello23 opened this issue · 41 comments

Hi,
I am trying to use the MPU9250, but no matter what I do, the I2C Scanner I have does not find any I2c addresses. When I call endTransmission(), it returns two, which I believe indicates that it is receiving a NACK and that I need pull-up resistors of some sort. Is this correct?

If so, what does the wiring look like for the pull-up resistors? - no matter where I put them, nothing seems to work.

Thanks for everything!

I have 10K resistors between the SDA and 3V3 and the SCL and 3V3 lines - it still doesn't work.

Here is a picture - I will send you a clearer schematic, draw out in a few minutes.
IMG_1682

Thanks for all the help in advance! - I will have the drawing in less than 5 minutes.

Schematic/Drawing of circuit, since the other picture may be hard to follow.
IMG_1684

There is 3V3 on the arduino - should I just connect NCS to 3V3? Also, I don't have a multimeter to measure the voltage, but there shouldn't be anything other than 3V3. Also, since the drawing wasn't very good, the 10K resistors from SDA and SCL are only connected to 3V3, not ground. Is that correct?

The board itself allows for power input between 2.4V and 3.6V, but has a 3.5 V regulator, too, so 5V input is okay. Info on piece:https://components101.com/processors/mpu9250-9-axis-digital-motion-processor

I will try simply connecting power, gnd, sda, and scl, as well as ncs, without any resistors now.

Here is the picture of the sensor:
IMG_1685

No luck with GND connected to GND, VCC connected to 3V3, SDA to SDA, SCL to SCL, and NCS to 3V3 with no pull-up resistors.

Without a multimeter, would you recommend just trying a variety of resistors? Are the resistors even totally necessary for this sensor - all of the videos I have watched are of people simply connecting 5V on Arduino to VCC on sensor, SDA, SCL, and GND, and everything working just fine (no resistors or anything). What would be your best guess as to why that isn't working for me?

The I2C Scanner found the sensor (same type, different individual one) on another computer and another Arduino, but still fails to find the sensor in the other code, where I actually try to get readings. Any ideas on what might be causing that issue?

Scanner code is the same and the code to get the readings is sample code from the library. This code returns that the status of the sensor is -1 sometimes, but other times it is actually giving readings. The only problem is that the readings are very strange - not correct at all, and the magnetometer's readings go to 0 after about 5 times. Here is the code we are using:
`#include "MPU9250.h"

MPU9250 IMU(Wire,0x68);
int status;

void setup() {
// serial to display data
Serial.begin(9600);
while(!Serial) {}

delay(1000);
// start communication with IMU
status = IMU.begin();
if (status < 0) {
Serial.println("IMU initialization unsuccessful");
Serial.println("Check IMU wiring or try cycling power");
Serial.print("Status: ");
Serial.println(status);
while(1) {}
}
}

void loop() {
// read the sensor
IMU.readSensor();
// display the data
Serial.print("Accelerometer (X, Y, Z): ");
Serial.print(IMU.getAccelX_mss());
Serial.print(" ");
Serial.print(IMU.getAccelY_mss());
Serial.print(" ");
Serial.println(IMU.getAccelZ_mss());

Serial.print("Gyro (X, Y, Z): ");
Serial.print(IMU.getGyroX_rads());
Serial.print(" ");
Serial.print(IMU.getGyroY_rads());
Serial.print(" ");
Serial.println(IMU.getGyroZ_rads());

Serial.print("Magnetometer (X, Y, Z): ");
Serial.print(IMU.getMagX_uT());
Serial.print(" ");
Serial.print(IMU.getMagY_uT());
Serial.print(" ");
Serial.print(IMU.getMagZ_uT());
//D = arctan(yGaussData/xGaussData)∗(180/π)
int dir = atan2(IMU.getMagY_uT(), IMU.getMagX_uT()) * ((180)/ (PI));
Serial.print(" Direction Heading: ");
Serial.println(dir);
Serial.println();
Serial.println();
Serial.println();
delay(1000);
}`

I see a couple of problems with this setup.

  1. the mpu9250 board MUST be powered by 5v. If you want to power it by 3.3v, you need to bypass the voyage regulator (the chip by the 5v/GND pins). The unpopulated 805 footprint beside the regulator can be bridged to do this. Because there will be a voltage drop across the regulator, to get 3.3v out of it, you need to feed it more than 3.3v. I'd say at least 4.5v. If you try powering it with 3.3v without bypassing the regulator, the i2c pins wont be pulled up high enough to trigger the logic high on the 5v microcontroller.

  2. You are connecting to the analog pins of the MCU breakout board -- the labeling on the headers says that SDA/SCL are at the opposite corner of the board by the reset button.

  3. For that particular 9250 board, the ONLY connections you need to make are 5v, GND, SDA, SCL. Optionally, you may also connect INT, which will save you from having to poll the chip for new data. All other pins may be left NOT CONNECTED.

I have issue on my mpu9250/6500 I can't
Detect the mpu9250 via i2c I try somany library all the library showing error
Including micropython
So I cry to write a code acces who am I from address 117 the result except 0×71 but I got same value i provided 117 i falow the datasheet the device address 0x68 A0 logic low
But one thing the temperature and gyro and Accel work fine i Take look the ic it's named MP92 and sumthing and 6007 The breakout board looks same on mpu9250 I saw on online and YouTube videos also mentioned on the board mpu9250/6500 please help me any one face this issue.

Arduino library showing errors not recognise the mpu9250

I try to understand library the who am I want to return 0x71 but I got 0x75

That's why the library showing error i think

On the chip it's mentioned mp92
And sumthing I can't see clearly but looks like same bord IMG_20231029_032529.jpg

IMG_20231029_032540_1.jpg

I try to read who Ami and device address the address on the chip is 0x68 A0 logic low if i pull-up the A0 I got 0x69 temperature,gyro and Accel register working fine but looks like the values are incorrect i reset the chip via power register1 and 8th bit position after reset all registers no longer return anything
But I disconnect and reconnect the module it's back to normal any solution for this

I am actually studying embedded software development last 6 months push my self in to write software from scratch but I am stuck on this

I try to read temperature and gyro with out calibration just for checking if register is working IMG_20231029_040816.jpg

I am working on the code it's not fully finished but I implement sum futures to read 16bit sigen integer from registers and return tuple of xyz i try to move around the sensor the values not I want i know it's not calibrated but the values so match random that's why I say the reading wrong.

I am in India. this thing so match expensive
That's why I try to make work this take my two day salary 😔

i am sorry its typo error signed integer

hear is my method reading sensor raw data from registers and unpack the data in to 16 bit signed integer

import ustruct
from machine import I2C
from micropython import const


class MPU9250:
    # Register Map for Gyroscope and Accelerometer (constant)
    # =============================================================================================
    __SELF_TEST_X_ACCEL: int = const(0x0D)
    __SELF_TEST_Y_ACCEL: int = const(0x0E)
    __SELF_TEST_Z_ACCEL: int = const(0x0F)

    __XG_OFFSET_H: int = const(0x13)
    __XG_OFFSET_L: int = const(0x14)
    __YG_OFFSET_H: int = const(0x15)
    __YG_OFFSET_L: int = const(0x16)
    __ZG_OFFSET_H: int = const(0x17)
    __ZG_OFFSET_L: int = const(0x18)

    __SMPL_RT_DIV: int = const(0x19)
    __CONFIG: int = const(0x1A)
    __GYRO_CONFIG: int = const(0x1B)
    __ACCEL_CONFIG1: int = const(0x1C)
    __ACCEL_CONFIG2: int = const(0x1D)
    __LP_ACCEL_ODR: int = const(0x1E)
    __WOM_THR: int = const(0x1F)
    __FIFO_EN: int = const(0x23)

    __I2C_MST_CTRL: int = const(0x24)
    __I2C_SLV0_ADDR: int = const(0x25)
    __I2C_SLV0_REG: int = const(0x26)
    __I2C_SLV0_CTRL: int = const(0x27)
    __I2C_SLV1_ADDR: int = const(0x28)
    __I2C_SLV1_REG: int = const(0x29)
    __I2C_SLV1_CTRL: int = const(0x2A)
    __I2C_SLV2_ADDR: int = const(0x2B)
    __I2C_SLV2_REG: int = const(0x2C)
    __I2C_SLV2_CTRL: int = const(0x2D)
    __I2C_SLV3_ADDR: int = const(0x2E)
    __I2C_SLV3_REG: int = const(0x2F)
    __I2C_SLV3_CTRL: int = const(0x30)
    __I2C_SLV4_ADDR: int = const(0x31)
    __I2C_SLV4_REG: int = const(0x32)
    __I2C_SLV4_DO: int = const(0x33)
    __I2C_SLV4_CTRL: int = const(0x34)
    __I2C_SLV4_DI: int = const(0x35)
    __I2C_MST_STATUS: int = const(0x36)
    __INT_PIN_CFG: int = const(0x37)
    __INT_ENABLE: int = const(0x38)
    __INT_STATUS: int = const(0x3A)

    __ACCEL_X_OUT_H: int = const(0x3B)
    __ACCEL_X_OUT_L: int = const(0x3C)
    __ACCEL_Y_OUT_H: int = const(0x3D)
    __ACCEL_Y_OUT_L: int = const(0x3E)
    __ACCEL_Z_OUT_H: int = const(0x3F)
    __ACCEL_Z_OUT_L: int = const(0x40)

    __TEMP_OUT_H: int = const(0x41)
    __TEMP_OUT_L: int = const(0x42)

    __GYRO_X_OUT_H: int = const(0x43)
    __GYRO_X_OUT_L: int = const(0x44)
    __GYRO_Y_OUT_H: int = const(0x45)
    __GYRO_Y_OUT_L: int = const(0x46)
    __GYRO_Z_OUT_H: int = const(0x47)
    __GYRO_Z_OUT_L: int = const(0x48)

    __EXT_SENS_DATA_00: int = const(0x49)
    __EXT_SENS_DATA_01: int = const(0x4A)
    __EXT_SENS_DATA_02: int = const(0x4B)
    __EXT_SENS_DATA_03: int = const(0x4C)
    __EXT_SENS_DATA_04: int = const(0x4D)
    __EXT_SENS_DATA_05: int = const(0x4E)
    __EXT_SENS_DATA_06: int = const(0x4F)
    __EXT_SENS_DATA_07: int = const(0x50)
    __EXT_SENS_DATA_08: int = const(0x51)
    __EXT_SENS_DATA_09: int = const(0x52)
    __EXT_SENS_DATA_10: int = const(0x53)
    __EXT_SENS_DATA_11: int = const(0x54)
    __EXT_SENS_DATA_12: int = const(0x55)
    __EXT_SENS_DATA_13: int = const(0x56)
    __EXT_SENS_DATA_14: int = const(0x57)
    __EXT_SENS_DATA_15: int = const(0x58)
    __EXT_SENS_DATA_16: int = const(0x59)
    __EXT_SENS_DATA_17: int = const(0x5A)
    __EXT_SENS_DATA_18: int = const(0x5B)
    __EXT_SENS_DATA_19: int = const(0x5C)
    __EXT_SENS_DATA_20: int = const(0x5D)
    __EXT_SENS_DATA_21: int = const(0x5E)
    __EXT_SENS_DATA_22: int = const(0x5F)
    __EXT_SENS_DATA_23: int = const(0x60)

    __I2C_SLV0_DO: int = const(0x63)
    __I2C_SLV1_DO: int = const(0x64)
    __I2C_SLV2_DO: int = const(0x65)
    __I2C_SLV3_DO: int = const(0x66)
    __I2C_MST_DELAY_CTRL: int = const(0x67)
    __SIGNAL_PATH_RESET: int = const(0x68)
    __MOT_DETECT_CTRL: int = const(0x69)
    __USER_CTRL: int = const(0x6A)
    __PWR_MGMT_1: int = const(0x6B)
    __PWR_MGMT_2: int = const(0x6C)
    __FIFO_COUNT_H: int = const(0x72)
    __FIFO_COUNT_L: int = const(0x73)
    __FIFO_R_W: int = const(0x74)

    __WHO_AM_I: int = const(0x75)

    __XA_OFFSET_H: int = const(0x78)
    __XA_OFFSET_L: int = const(0x7A)
    __YA_OFFSET_H: int = const(0x7B)
    __YA_OFFSET_L: int = const(0x7C)
    __ZA_OFFSET_H: int = const(0x7E)
    __ZA_OFFSET_L: int = const(0x7F)

    def __init__(self, port: I2C = None, address: int = 0x68) -> None:
        if port is None:
            raise ValueError("Oops! I2C object 'port' is missing.")
        if address not in [0x68, 0x69]:
            raise ValueError(f"invalid MPU9250 device address {address}")

        self.__I2C_BUS: I2C = port
        self.__MPU9250_ADDR: int = const(address)

    def __write_to_register(self, write_reg: int, write_data: int) -> None:
        try:
            self.__I2C_BUS.writeto_mem(self.__MPU9250_ADDR, write_reg, bytearray([write_data]))
        except OSError as error:
            if error.args[0] == 5:
                raise RuntimeError("Oops! Communication error with the MPU9250 during the operation. :(")
            else:
                raise RuntimeError(f"Communication error with the MPU9250 during the operation. Error message: {error}")

    def __read_from_register(self, mem_addr: int, num_byte: int) -> bytes:
        try:
            raw_data: bytes = self.__I2C_BUS.readfrom_mem(self.__MPU9250_ADDR, mem_addr, num_byte)
        except OSError as error:
            if error.args[0] == 5:
                raise RuntimeError("Oops! Communication error with the MPU9250 during the operation. :(")
            else:
                raise RuntimeError(f"Communication error with the MPU9250 during the operation. Error message: {error}")
        return raw_data  # The function returns raw data from sensor registers.

    def whoami(self) -> int:
        """
        This function is used to verify the identity of the device. The contents of WHO_AM_I is an 8-bit device
        ID. The default value of the register is 0x71.
        :return: The device ID.
        """
        whoami: bytes = self.__read_from_register(mem_addr=self.__WHO_AM_I, num_byte=1)
        return int.from_bytes(whoami, 'little')

    def gyro_config(self):
        pass

    def accel_config(self):
        pass

    def calibrate(self) -> None:
        pass

    def temperature(self, room_offset: float, sensitivity: float) -> float:
        # Read the raw temperature data from the sensor
        raw_temp: bytes = self.__read_from_register(mem_addr=self.__TEMP_OUT_H, num_byte=2)
        temp_out: tuple = ustruct.unpack("<h", raw_temp)
        # Calculate the temperature in degrees Celsius
        temp_c: float = ((temp_out[0] - room_offset) / sensitivity) + 21
        return temp_c

    def gyroscope(self) -> tuple:
        raw_gyro: bytes = self.__read_from_register(mem_addr=self.__GYRO_X_OUT_H, num_byte=6)
        gyro: tuple = ustruct.unpack("<hhh", raw_gyro)
        return gyro

    def accelerometer(self) -> tuple:
        raw_accel: bytes = self.__read_from_register(mem_addr=self.__ACCEL_X_OUT_H, num_byte=6)
        accel: tuple = ustruct.unpack("<hhh", raw_accel)
        return accel

this is my prototype. Not fully implemented.

the gyroscope function give a request to read_from_register function the function response to the request the response is 16bit signed integers tuple of xyz

i need to know is that who am i all so signed integer is that we want to do 2's compliment for this value?