kriswiner / MPU9250

Arduino sketches for MPU9250 9DoF with AHRS sensor fusion
1.04k stars 471 forks source link

Accessing MPU9250's magnetometer via SPI #367

Open Qammar-25 opened 5 years ago

Qammar-25 commented 5 years ago

Hi Kriswiner,

I am using MPU9250 to get accelerometer and gyroscope readings via SPI. However, i am unable to sort out how can i access the magnetometer through SPI? Any help regarding the issue will be appreciated.

kriswiner commented 5 years ago

You could treat the AK8963 as an I2C slave to the MPU9250 and read mag data directly from MPU9250 registers with SPI like in this https://github.com/kriswiner/MPU9250/tree/master/AK8963_as_slave example. Not here I am using I2C to read MPU9250 registers but you can replace this with SPI and it should work just fine.

On Fri, May 10, 2019 at 12:49 AM Qammar-25 notifications@github.com wrote:

Hi,

I am using MPU9250 to get accelerometer and gyroscope readings via SPI. However, i am unable to sort out how can i access the magnetometer through SPI? Any help regarding the issue will be appreciated.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKTRXQ3ILRDSOGR6L33PUUSKDANCNFSM4HMAWB5A .

Qammar-25 commented 5 years ago

Thank you Kris. I successfully read the Who Am I register by making AK8963 as an I2C slave (SLAVE 4) of MPU9250. However, now i want to read magnetometer values for which i want to configure my CNTL1 register for continuous measurement mode 2. I am trying to write to this register but when i read it back it shows 0x00. Why i cannot write to this register?

kriswiner commented 5 years ago

No idea. Are you using the MPU9250 methods to write to the slave sensor via the MPU9250 registers?

On Mon, May 13, 2019 at 3:46 AM Qammar-25 notifications@github.com wrote:

Thank you Kris. I successfully read the Who Am I register by making AK8963 as an I2C slave (SLAVE 4) of MPU9250. However, now i want to read magnetometer values for which i want to configure my CNTL1 register for continuous measurement mode 2. I am trying to write to this register but when i read it back it shows 0x00. Why i cannot write to this register?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367#issuecomment-491772870, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKQYTN5VCQI4JLJJSRLPVFBILANCNFSM4HMAWB5A .

Qammar-25 commented 5 years ago

Yes

kriswiner commented 5 years ago

You should be able to write and read back register data, no idea why it doesn't work.

On Mon, May 13, 2019 at 8:43 PM Qammar-25 notifications@github.com wrote:

Yes

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367?email_source=notifications&email_token=ABTDLKXBCIWZQ7R55NOCLVTPVIYOBA5CNFSM4HMAWB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVKFUGQ#issuecomment-492067354, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKUGLRESRE4B3H5NQ2TPVIYOBANCNFSM4HMAWB5A .

Qammar-25 commented 5 years ago

The datasheet says it is a read-only register.

kriswiner commented 5 years ago

Well, then of course you can't write to it.

On Mon, May 13, 2019 at 9:06 PM Qammar-25 notifications@github.com wrote:

The datasheet says it is a read-only register.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367?email_source=notifications&email_token=ABTDLKU42XOMREDPS23426TPVI3F3A5CNFSM4HMAWB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVKGO6I#issuecomment-492070777, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKTK5WWPAGB5AKE5LMDPVI3F3ANCNFSM4HMAWB5A .

Qammar-25 commented 5 years ago

How can i set the continuous measurement mode?

kriswiner commented 5 years ago

Most of the AK8963C registers can be written to. You have to write the correct configuration to the appropriate register as in the sketch I linked to.

On Mon, May 13, 2019 at 9:53 PM Qammar-25 notifications@github.com wrote:

How can i set the continuous measurement mode?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367?email_source=notifications&email_token=ABTDLKQ3ZC22EQILOAZ3TBDPVJAUNA5CNFSM4HMAWB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVKIH6A#issuecomment-492078072, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKWBYVWCQ3IJ7GWSN4DPVJAUNANCNFSM4HMAWB5A .

kriswiner commented 5 years ago

Like this:

void MPU9250::initAK8963Slave(uint8_t Mscale, uint8_t Mmode, float * magCalibration) { // First extract the factory calibration for each magnetometer axis uint8_t rawData[3]; // x/y/z gyro calibration data stored here

writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS); // Set the I2C slave address of AK8963 and set for write. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL2); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_DO, 0x01); // Reset AK8963 writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and write 1 byte

writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS); // Set the I2C slave address of AK8963 and set for write. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_DO, 0x00); // Power down magnetometer writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and write 1 byte delay(50); writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS); // Set the I2C slave address of AK8963 and set for write. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_DO, 0x0F); // Enter fuze mode writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and write 1 byte delay(50);

writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS | 0x80); // Set the I2C slave address of AK8963 and set for read. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_ASAX); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x83); // Enable I2C and read 3 bytes delay(50); readBytes(MPU9250_ADDRESS, EXT_SENS_DATA_00, 3, &rawData[0]); // Read the x-, y-, and z-axis calibration values magCalibration[0] = (float)(rawData[0] - 128)/256.0f + 1.0f; // Return x-axis sensitivity adjustment values, etc. magCalibration[1] = (float)(rawData[1] - 128)/256.0f + 1.0f; magCalibration[2] = (float)(rawData[2] - 128)/256.0f + 1.0f; _magCalibration[0] = magCalibration[0]; _magCalibration[1] = magCalibration[1]; _magCalibration[2] = magCalibration[2]; _Mmode = Mmode;

writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS); // Set the I2C slave address of AK8963 and set for write. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_DO, 0x00); // Power down magnetometer writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and transfer 1 byte delay(50);

writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS); // Set the I2C slave address of AK8963 and set for write. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL); // I2C slave 0 register address from where to begin data transfer // Configure the magnetometer for continuous read and highest resolution // set Mscale bit 4 to 1 (0) to enable 16 (14) bit resolution in CNTL register, // and enable continuous mode data acquisition Mmode (bits [3:0]), 0010 for 8 Hz and 0110 for 100 Hz sample rates writeByte(MPU9250_ADDRESS, I2C_SLV0_DO, Mscale << 4 | Mmode); // Set magnetometer data resolution and sample ODR writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and transfer 1 byte delay(50); writeByte(MPU9250_ADDRESS, I2C_SLV0_ADDR, AK8963_ADDRESS | 0x80); // Set the I2C slave address of AK8963 and set for read. writeByte(MPU9250_ADDRESS, I2C_SLV0_REG, AK8963_CNTL); // I2C slave 0 register address from where to begin data transfer writeByte(MPU9250_ADDRESS, I2C_SLV0_CTRL, 0x81); // Enable I2C and transfer 1 byte delay(50); }

On Mon, May 13, 2019 at 11:21 PM Tlera Corporation tleracorp@gmail.com wrote:

Most of the AK8963C registers can be written to. You have to write the correct configuration to the appropriate register as in the sketch I linked to.

On Mon, May 13, 2019 at 9:53 PM Qammar-25 notifications@github.com wrote:

How can i set the continuous measurement mode?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367?email_source=notifications&email_token=ABTDLKQ3ZC22EQILOAZ3TBDPVJAUNA5CNFSM4HMAWB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVKIH6A#issuecomment-492078072, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKWBYVWCQ3IJ7GWSN4DPVJAUNANCNFSM4HMAWB5A .

Qammar-25 commented 5 years ago

Thank you for your help Kris. I have resolved the issue which was in the sequence of sending commands. The DO register of slave 4 should have been written first before enabling the slave. I was doing the other way around.

Qammar-25 commented 5 years ago

I can read and write to registers now. However, when i enter fuse mode to access Axial Sensitivity Adjustment Values, all three registers return me zero. Are these values correct?

kriswiner commented 5 years ago

No these values should be 1 +, like 1.10 or 1.05, etc

On Tue, May 21, 2019 at 2:41 AM Qammar-25 notifications@github.com wrote:

I can read and write to registers now. However, when i enter fuse mode to access Axial Sensitivity Adjustment Values, all three registers return me zero. Are these values correct?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/367?email_source=notifications&email_token=ABTDLKS66G3C6RTEFLLOCU3PWO7S5A5CNFSM4HMAWB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV3LJ3Q#issuecomment-494318830, or mute the thread https://github.com/notifications/unsubscribe-auth/ABTDLKXY7SI2LDHZFHN2GX3PWO7S5ANCNFSM4HMAWB5A .

PJiaHeng commented 4 years ago

Hello, kriswiner. I have an issue of MPU9250 magnetometer. I use your example code as follow: https://github.com/kriswiner/MPU9250/tree/master/AK8963_as_slave.

MPU9250 is working smoothly at the beginning(Interface: SPI). But a few moment later, the magnetometer data doesn’t change anymore.It needs to cut down the power of MPU9250 to fix it. The values of register(I2C_MST_STATUS) and register(INT_STATUS) are 0x01 and 0x09 respectively, it means salve0 receives a nack signal(I use slave0 access to magnetometer). In my view, the communication between MPU9250 and AK8963 is break. So, I deduce that AK8963 has been shutdown. But I can’t understand why the magnetometer has this problem and have no idea that how to fix it.

I’ve been nagged with this issue for weeks. Can you give me any advice?

Thanks.