0

Following is my code, I am trying to read accelerometer readings. In the below code I am trying to read the z-axis reading of the accelerator. The output expected is around 1 but the output I get is either 0 or 2. Is it i2c or my logic is wrong. I tried to find a solution but I couldn't find anything relevant. Also, I am avoiding to use a library because I want to learn how the operation actually happens. I am using ESP32 on Arduino IDE and IMU is MPU9250.

    #include <Wire.h>

    #define MPU9250           0x68
    #define PWR_MGMT_1        0x6B
    #define SMPLRT_DIV        0x19
    #define CONFIG            0x1A
    #define ACCEL_CONFIG      0x1C
    #define ACCEL_XOUT_H      0x3B
    #define ACCEL_YOUT_H      0X3D
    #define ACCEL_ZOUT_H      0X3F

    #ifdef _ESP32_HAL_I2C_H_
    #define SDA_PIN 21
    #define SCL_PIN 22
    #endif

    uint8_t size = 1;
    uint16_t final_val;
    float fin;

    uint8_t i2cRead(uint8_t Address, uint8_t Register) {
      uint8_t var;
      Wire.beginTransmission(Address);
      Wire.write(Register);
      uint8_t result = Wire.endTransmission();
      if (result != 0) {
        return result;
      }
      Wire.requestFrom(Address, size);
      while(Wire.available()){
        var = Wire.read();
      }
      return var;
     }

     void i2cWriteByte(uint8_t Address, uint8_t Register, uint8_t Data) {
       Wire.beginTransmission(Address);
       Wire.write(Register);
       Wire.write(Data);
       Wire.endTransmission();
     }

     void MPU_Start()
     {
        i2cWriteByte(MPU9250, SMPLRT_DIV, 0x00);
        delay(10);
        i2cWriteByte(MPU9250, PWR_MGMT_1, 0x00);
        delay(10);
        i2cWriteByte(MPU9250, PWR_MGMT_1, 0x01);
        delay(10);
        i2cWriteByte(MPU9250, CONFIG, 0x00);
        delay(10);
        i2cWriteByte(MPU9250, ACCEL_CONFIG, 0x00);    //2g
        delay(10);
     }

     void MPU_convert()
     { 
        //read_raw_data(ACCEL_XOUT_H);
        //read_raw_data(ACCEL_YOUT_H);
       read_raw_data(ACCEL_ZOUT_H);
     }

     void read_raw_data(uint8_t reg)
     {
        uint8_t high, low;
        high = i2cRead(MPU9250, reg);
        low = i2cRead(MPU9250, reg+1);
        final_val = ((high << 8) | low);
        fin = (final_val/32768)*2;
     }

      void setup() {
      // put your setup code here, to run once:

        Serial.begin(115200);
        while(!Serial);
        #ifdef _ESP32_HAL_I2C_H_
        Wire.begin(SDA_PIN, SCL_PIN); 
        #endif

        MPU_Start();
     }

     void loop() {
      // put your main code here, to run repeatedly:

        MPU_convert();
        Serial.println(fin);
     }
S.G
  • 1
  • 1
  • You never set the register on what you want to get from the device, you just went straight to read the data. – hcheung Dec 16 '21 at 11:37
  • @hcheung I am passing the register - ACCEL_ZOUT_H which is a Read register, to the i2cRead(uint8_t Address, uint8_t Register) function. I do not understand which register to set exactly? – S.G Dec 16 '21 at 11:47
  • 1
    That's for reading, you need to call `Wire.write()` to tell the device to send the data so that you can read it... Read the datasheet. – hcheung Dec 16 '21 at 12:00
  • One more hint, in your `read_raw_data(uint8_t reg)`, the `i2cRead(MPU9250, reg)` read the reg 3F, what `i2cRead(MPU9250, reg+1)` is for? there is no such register as `0x40`. You should consider change the design of your `i2cRead()` to read two bytes instead of one byte as most of the MPU9250 return a uint16_t (i.e. two bytes) instead of one byte. – hcheung Dec 16 '21 at 12:11
  • @hcheung 0x3F is the high bit register address and 0x40 is the low bit register address of ACCEL_ZOUT_H. – S.G Dec 17 '21 at 04:32
  • Fair enough if you want to read byte by byte (in fact for MPU9250, you can address to ACCEL_XOUT_H to read 6 bytes in one i2C truncation). Take a look at your `fin = (final_val/32768)*2;`, it will only return an integer instead of a float. Change it to `fin = (final_val/32768)*2.0;`. – hcheung Dec 18 '21 at 09:27

0 Answers0