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
}