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: