I2c issue on Nordic nRF9160-DK

Hello Nordic developers,

I started my new journey with nRF9160 to expand my knowledge in embedded system. So, I got myself nRF9160-DK and started with the course until the I2C section,

When I tried to modify the i2c section to be used with MPU9250 (since I didn't order X-Nucleo expansion board), The write function will always return error -5.

I've spent almost 2 weeks and still stuck.

Here are the steps I made:

I tired 0x68 alone without shifting -> Failed.

Shift to left and write -> Failed.

Changed the sensor to another -> Failed.

Here is my prj.conf:

# STEP 2 - Enable the I2C driver
CONFIG_I2C=y
# STEP 4.2 - Enable floating point format specifiers
CONFIG_CBPRINTF_FP_SUPPORT=y

Overlay:

&i2c2 {
    
    mysensor: mysensor@68{
        compatible = "i2c-device";
        status = "okay";
        reg = < 0x68 >;
    };
};

MPU9250.c :

#include <math.h>
#include "MPU9250.h"

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
/* STEP 3 - Include the header file of the I2C API */
#include <zephyr/drivers/i2c.h>

double accelRange,gyroRange;
uint8_t magBuf[7], magXAdjust, magYAdjust, magZAdjust;
char accelBuf[6],gyroBuf[6];
uint8_t magBuf[7];
int i;
int16_t magXOffset, magYOffset, magZOffset;
//start Accelerometer

#define I2C2_NODE DT_NODELABEL(mysensor)

static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C2_NODE);



int8_t MPU9250_beginAccel(uint8_t mode) {
  
  switch(mode) {
  case ACC_FULL_SCALE_2_G:
    accelRange = 2.0;
    break;
  case ACC_FULL_SCALE_4_G:
    accelRange = 4.0;
    break;
  case ACC_FULL_SCALE_8_G:
    accelRange = 8.0;
    break;
  case ACC_FULL_SCALE_16_G:
    accelRange = 16.0;
    break;
  default:
    return; // Return without writing invalid mode
  }

  if (!device_is_ready(dev_i2c.bus)){return 1;}
  uint8_t data[2]={MPU9250_ADDR_ACCELCONFIG,mode};
  return i2c_write_dt(&dev_i2c, data, 2);
	
}

//start gyroscope
int8_t MPU9250_beginGyro(uint8_t mode) {
  
  switch (mode) {
  case GYRO_FULL_SCALE_250_DPS:
    gyroRange = 250.0;
    break;
  case GYRO_FULL_SCALE_500_DPS:
    gyroRange = 500.0;
    break;
  case GYRO_FULL_SCALE_1000_DPS:
    gyroRange = 1000.0;
    break;
  case GYRO_FULL_SCALE_2000_DPS:
    gyroRange = 2000.0;
    break;
  default:
    return; // Return without writing invalid mode
  }
   if (!device_is_ready(dev_i2c.bus)){return 1;}
    uint8_t data[2]={27,mode};
  return i2c_write_dt(&dev_i2c, data, 2);

}



int8_t MPU9250_accelUpdate(void) {
	
 return i2c_write_read_dt(&dev_i2c, 0x3B,1,accelBuf,6);
	
 
}

float MPU9250_accelGet(uint8_t highIndex, uint8_t lowIndex) {
  int16_t v = ((int16_t) accelBuf[highIndex]) << 8 | accelBuf[lowIndex];
  return ((float) -v) * accelRange / (float) 0x8000; // (float) 0x8000 == 32768.0
}

float MPU9250_accelSqrt(void) {
  return sqrt(pow(MPU9250_accelGet(0, 1), 2) +
              pow(MPU9250_accelGet(2, 3), 2) +
              pow(MPU9250_accelGet(4, 5), 2));
}

float MPU9250_accelX(void) {
  return MPU9250_accelGet(0, 1);
}

float MPU9250_accelY(void) {
  return MPU9250_accelGet(2, 3);
}

float MPU9250_accelZ(void) {
  return MPU9250_accelGet(4, 5);
}


int8_t MPU9250_gyroUpdate(void) {
  return i2c_write_read_dt(&dev_i2c, 0x43,1,gyroBuf,6);
}

float MPU9250_gyroGet(uint8_t highIndex, uint8_t lowIndex) {
  int16_t v = ((int16_t) gyroBuf[highIndex]) << 8 | gyroBuf[lowIndex];
  return ((float) -v) * gyroRange / (float) 0x8000;
}

float MPU9250_gyroX(void) {
  return MPU9250_gyroGet(0, 1);
}

float MPU9250_gyroY(void) {
  return MPU9250_gyroGet(2, 3);
}

float MPU9250_gyroZ(void) {
  return MPU9250_gyroGet(4, 5);
}


header file:

#ifndef __MPU9250__H__
#define __MPU9250__H__

#include "stdint.h"


#define Pi 3.14159

#define ACC_FULL_SCALE_2_G       0x00
#define ACC_FULL_SCALE_4_G       0x08
#define ACC_FULL_SCALE_8_G       0x10
#define ACC_FULL_SCALE_16_G      0x18

#define GYRO_FULL_SCALE_250_DPS  0x00
#define GYRO_FULL_SCALE_500_DPS  0x08
#define GYRO_FULL_SCALE_1000_DPS 0x10
#define GYRO_FULL_SCALE_2000_DPS 0x18


#define MPU9250_ADDR_ACCELCONFIG  0x1C
#define MPU9250_ADDR_INT_PIN_CFG  0x37
#define MPU9250_ADDR_ACCEL_XOUT_H 0x3B
#define MPU9250_ADDR_GYRO_XOUT_H  0x43
#define MPU9250_ADDR_PWR_MGMT_1   0x6B
#define MPU9250_ADDR_WHOAMI       0x75
//accelerartion part 
int8_t MPU9250_beginAccel(uint8_t mode);
float MPU9250_accelX(void);
float MPU9250_accelY(void);
float MPU9250_accelZ(void);
int8_t MPU9250_accelUpdate(void);


//gyro part
int8_t MPU9250_beginGyro(uint8_t mode);
int8_t MPU9250_gyroUpdate(void);
float MPU9250_gyroX(void);
float MPU9250_gyroY(void);
float MPU9250_gyroZ(void);

#endif

main.c 

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
/* STEP 3 - Include the header file of the I2C API */
#include <zephyr/drivers/i2c.h>
/* STEP 4.1 - Include the header file of printk() */
#include <zephyr/sys/printk.h>
#include "MPU9250.h"


int ret;


float ax,ay,az;

void main(void)
{
	ret=MPU9250_beginAccel(ACC_FULL_SCALE_2_G);
	if(ret !=0)
	{
		printk("Failed to intialize with error code %i\r\n",ret);
		return ;
	}

	while (1) 
	{
		ret=MPU9250_accelUpdate();
		if(ret !=0)
		{
			printk("Failed to read with error code %i\r\n",ret);
			return ;
		}

		ax=MPU9250_accelX();
		ay=MPU9250_accelY();
		az=MPU9250_accelZ();
		printk("ax=%0.2f\t ay=%0.2f\t az=%0.2f",ax,ay,az);
		k_msleep(10);
	
	
	}

}

Serial output:

Related