Quantcast
Channel: Arduino Forum - Latest topics
Viewing all articles
Browse latest Browse all 15514

Not getting data from AK8963 magnetometer in mpu9250

$
0
0

First post. Sorry if this isn't the right place, but looked for something like Development/Programming Questions, for example, and couldn't find.

Connected an ESP32S3 Dev Board (no pin 22, btw) to an mpu9250 gyro/accel and [supposedly containing] a magnetometer AK8963. The relevant chip in the mpu9250 board is marked MP92 917LD1 2248 or 224B?; tried to find a datasheet for that, but couldn't locate one. This is a cheap chinese board (around 4€).

The code below for configuring the magnetometer hangs when we try to get data from it. It runs until that point:

09:56:52.304 -> ESP-ROM:esp32s3-20210327
09:56:52.304 -> Build:Mar 27 2021
09:56:52.304 -> rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
09:56:52.304 -> SPIWP:0xee
09:56:52.304 -> mode:DIO, clock div:1
09:56:52.304 -> load:0x3fce3808,len:0x44c
09:56:52.304 -> load:0x403c9700,len:0xbe4
09:56:52.304 -> load:0x403cc700,len:0x2a68
09:56:52.304 -> entry 0x403c98d4
09:56:52.355 -> Configure MagnetometerDisable MPU9250 I2C master interface...done.
09:56:52.355 -> Enable MPU9250 interface bypass mux...done.
09:56:52.355 -> Access AK8963 fuse ROM...done.
09:56:52.460 -> Open and point session to AK8963 fuse ROM...done.
09:56:52.460 -> Request 3 bytes of data from fuse ROM (ASAX, ASAY, ASAZ)...

The code is:

/* 
    Test Config Magnetometer in MPU9250

    contains parts from;
    https://www.instructables.com/Tilt-Compensated-Compass/

    https://www.instructables.com/member/lingib/instructables/

*/

// ----- Libraries
#include <Wire.h>

// ----- Gyro
#define MPU9250_I2C_address 0x68                                        // I2C address for MPU9250 
#define MPU9250_I2C_master_enable 0x6A                                  // USER_CTRL[5] = I2C_MST_EN
#define MPU9250_Interface_bypass_mux_enable 0x37                        // INT_PIN_CFG[1]= BYPASS_EN

// ----- Magnetometer
#define AK8963_I2C_address 0x0C                                             // I2C address for AK8963
#define AK8963_cntrl_reg_1 0x0A                                             // CNTL[4]=#bits, CNTL[3:0]=mode
#define AK8963_status_reg_1 0x02                                            // ST1[0]=data ready
#define AK8963_data_ready_mask 0b00000001                                   // Data ready mask
#define AK8963_overflow_mask 0b00001000                                     // Magnetic sensor overflow mask
#define AK8963_data 0x03                                                    // Start address of XYZ data                                                                
#define AK8963_fuse_ROM 0x10                                                // X,Y,Z fuse ROM

bool    Record_data = false;
int     Mag_x_offset = 46,      Mag_y_offset = 190,     Mag_z_offset = -254;   // Hard-iron offsets
float   Mag_x_scale = 1.01,     Mag_y_scale = 0.99,     Mag_z_scale = 1.00;    // Soft-iron scale factors
float   ASAX = 1.17,            ASAY = 1.18,            ASAZ = 1.14;           // (A)sahi (S)ensitivity (A)djustment fuse ROM values.

void setup()
{
  Serial.begin(115200);
  //Wire.begin(21, 20, 400000); // SDA, SCL pins an Frequency
  Wire.begin(21, 20); // SDA, SCL pins
  Wire.setClock(400000);
  Serial.print("Configure Magnetometer");                           // Print text to screen

  // ----- Configure the magnetometer
  configure_magnetometer();
}

void loop()
{


}

// ----------------------------
//  Configure magnetometer
// ----------------------------
void configure_magnetometer()
{
  /*
     The MPU-9250 contains an AK8963 magnetometer and an
     MPU-6050 gyro/accelerometer within the same package.

     To access the AK8963 magnetometer chip The MPU-9250 I2C bus
     must be changed to pass-though mode. To do this we must:
      - disable the MPU-9250 slave I2C and
      - enable the MPU-9250 interface bypass mux
  */
  // ----- Disable MPU9250 I2C master interface
  Serial.print("Disable MPU9250 I2C master interface...");
  Wire.beginTransmission(MPU9250_I2C_address);                      // Open session with MPU9250
  Wire.write(MPU9250_I2C_master_enable);                            // Point USER_CTRL[5] = I2C_MST_EN
  Wire.write(0x00);                                                 // Disable the I2C master interface
  Wire.endTransmission();
  Serial.println("done.");

  // ----- Enable MPU9250 interface bypass mux
  Serial.print("Enable MPU9250 interface bypass mux...");
  Wire.beginTransmission(MPU9250_I2C_address);                      // Open session with MPU9250
  Wire.write(MPU9250_Interface_bypass_mux_enable);                  // Point to INT_PIN_CFG[1] = BYPASS_EN
  Wire.write(0x02);                                                 // Enable the bypass mux
  Wire.endTransmission();
  Serial.println("done.");

  // ----- Access AK8963 fuse ROM
  /* The factory sensitivity readings for the XYZ axes are stored in a fuse ROM.
     To access this data we must change the AK9863 operating mode.
  */
  Serial.print("Access AK8963 fuse ROM...");
  Wire.beginTransmission(AK8963_I2C_address);                       // Open session with AK8963
  Wire.write(AK8963_cntrl_reg_1);                                   // CNTL[3:0] mode bits
  Wire.write(0b00011111);                                           // Output data=16-bits; Access fuse ROM
  Wire.endTransmission();
  Serial.println("done.");
  delay(100);                                                       // Wait for mode change

  // ----- Get factory XYZ sensitivity adjustment values from fuse ROM
  /* There is a formula on page 53 of "MPU-9250, Register Map and Decriptions, Revision 1.4":
      Hadj = H*(((ASA-128)*0.5)/128)+1 where
      H    = measurement data output from data register
      ASA  = sensitivity adjustment value (from fuse ROM)
      Hadj = adjusted measurement data (after applying
  */
  Serial.print("Open and point session to AK8963 fuse ROM...");
  Wire.beginTransmission(AK8963_I2C_address);                       // Open session with AK8963
  Wire.write(AK8963_fuse_ROM);                                      // Point to AK8963 fuse ROM
  Wire.endTransmission();
  Serial.println("done.");

  Serial.print("Request 3 bytes of data from fuse ROM (ASAX, ASAY, ASAZ)...");
  Wire.requestFrom(AK8963_I2C_address, 3);                          // Request 3 bytes of data
  while (Wire.available() < 3);                                     // Wait for the data
  ASAX = (Wire.read() - 128) * 0.5 / 128 + 1;                       // Adjust data
  ASAY = (Wire.read() - 128) * 0.5 / 128 + 1;
  ASAZ = (Wire.read() - 128) * 0.5 / 128 + 1;
  Serial.println("done.");

  // ----- Power down AK8963 while the mode is changed
  /*
     This wasn't necessary for the first mode change as the chip was already powered down
  */
  Serial.print("Power down AK8963 while the mode is changed...");
  Wire.beginTransmission(AK8963_I2C_address);                       // Open session with AK8963
  Wire.write(AK8963_cntrl_reg_1);                                   // Point to mode control register
  Wire.write(0b00000000);                                           // Set mode to power down
  Wire.endTransmission();
  Serial.println("done.");
  delay(100);                                                       // Wait for mode change

  // ----- Set output to mode 2 (16-bit, 100Hz continuous)
  Serial.print("Set output to mode 2 (16-bit, 100Hz continuous)...");
  Wire.beginTransmission(AK8963_I2C_address);                       // Open session with AK8963
  Wire.write(AK8963_cntrl_reg_1);                                   // Point to mode control register
  Wire.write(0b00010110);                                           // Output=16-bits; Measurements = 100Hz continuous
  Wire.endTransmission();
  Serial.println("done.");
  delay(100);                                                       // Wait for mode change
}

7 posts - 3 participants

Read full topic


Viewing all articles
Browse latest Browse all 15514

Trending Articles