kriswiner / MPU9250

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

Magnetometer issue for EV_MPU-9250 #313

Open straldr opened 5 years ago

straldr commented 5 years ago

Hi Kris,

Thanks for the great code. I have managed to obtain the accelerometer and gyro datas, however my magnetometer datas give out only zero values. When I run the code, I managed to get the output: "AK8963 I AM 48 I should be 48". Furthermore, under the readMagData function, (readByte(AK8963_ADDRESS, AK8963_ST1) gives out 0 value. I am currently using EV_MPU-9250 with Arduino Mega 2560 for my set up.

Here is how I have connected my MPU-9250 and Arduino: MPU-9250 --- Arduino VIN --- 3.3V GND --- GND SDA --- Pin 20 (SDA) SCL --- Pin 21 (SCL)

I am new to Arduino so I have no idea how to approach fixing this problem. Thanks for the help!

kriswiner commented 5 years ago

I am assuming you have something like this in your sketch:

// Configure Interrupts and Bypass Enable // Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared, // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips // can join the I2C bus and all can be controlled by the Arduino as master // writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22); writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x12); // INT is 50 microsecond pulse and any read to clear

That is you need to allow bypass by setting bit 0 of the INT_PIN_CFG register to 1.

Also, you should check what the value of the mRes mag field scalar is. Is it zero? Cn you read the raw mag data register values?

On Fri, Oct 5, 2018 at 11:12 PM straldr notifications@github.com wrote:

Hi Kris,

Thanks for the great code. I have managed to obtain the accelerometer and gyro datas, however my magnetometer datas give out only zero values. When I run the code, I managed to get the output: "AK8963 I AM 48 I should be 48". Furthermore, under the readMagData function, (readByte(AK8963_ADDRESS, AK8963_ST1) gives out 0 value. I am currently using EV_MPU-9250 with Arduino Mega 2560 for my set up.

Here is how I have connected my MPU-9250 and Arduino: MPU-9250 --- Arduino VIN --- 3.3V GND --- GND SDA --- Pin 20 (SDA) SCL --- Pin 21 (SCL)

I am new to Arduino so I have no idea how to approach fixing this problem. Thanks for the help!

— 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/313, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qqKKrbXhb5Ayx4xwyCIMhHWkaavHks5uiEnMgaJpZM4XLNBg .

straldr commented 5 years ago

I am not sure what you mean by the INT_PIN_CFG register and the interrupt pin, but in the code I have this part as well:

// Configure Interrupts and Bypass Enable // Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared, // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips // can join the I2C bus and all can be controlled by the Arduino as master writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22);
writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); // Enable data ready (bit 0) interrupt

As for mRes value, it is 1.50. For mag data register values, I read 0, 0, 0, 0, 0, 0 when I print this:

void readMagData(int16_t * destination) {
uint8_t rawData[7]; // x/y/z gyro register data, ST2 register stored here, must read ST2 at end of data acquisition //if(readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) { // wait for magnetometer data ready bit to be set readBytes(AK8963_ADDRESS, AK8963_XOUT_L, 7, &rawData[0]); // Read the six raw data and ST2 registers sequentially into data array uint8_t c = rawData[6]; // End data read by reading ST2 register Serial.print(rawData[0]); Serial.print(", "); Serial.print(rawData[1]); Serial.print(", "); Serial.print(rawData[2]); Serial.print(", "); Serial.print(rawData[3]); Serial.print(", "); Serial.print(rawData[4]); Serial.print(", "); Serial.println(rawData[5]); if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ; // Data stored as little Endian destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ; } //} }

kriswiner commented 5 years ago

If this function returns zeroes then your sensor is broken.

On Sat, Oct 6, 2018 at 8:35 AM straldr notifications@github.com wrote:

I am not sure what you mean by the INT_PIN_CFG register and the interrupt pin, but in the code I have this part as well:

// Configure Interrupts and Bypass Enable // Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared, // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips // can join the I2C bus and all can be controlled by the Arduino as master writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22); writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); // Enable data ready (bit 0) interrupt

As for mRes value, it is 1.50. For mag data register values, I read 0, 0, 0, 0, 0, 0 when I print this:

void readMagData(int16_t * destination) { uint8_t rawData[7]; // x/y/z gyro register data, ST2 register stored here, must read ST2 at end of data acquisition //if(readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) { // wait for magnetometer data ready bit to be set readBytes(AK8963_ADDRESS, AK8963_XOUT_L, 7, &rawData[0]); // Read the six raw data and ST2 registers sequentially into data array uint8_t c = rawData[6]; // End data read by reading ST2 register Serial.print(rawData[0]); Serial.print(", "); Serial.print(rawData[0]); Serial.print(", "); Serial.print(rawData[1]); Serial.print(", "); Serial.print(rawData[2]); Serial.print(", "); Serial.print(rawData[3]); Serial.print(", "); Serial.print(rawData[4]); Serial.print(", "); Serial.println(rawData[5]); if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ; // Data stored as little Endian destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ; } //} }

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

straldr commented 5 years ago

Currently I am using a borrowed EV_MPU9250 while waiting for the one I have ordered. I will try the sketch on the new one once I receive it. Just to clarify, is there any problem if I connect the 3.3V on Arduino Mega 2560 with the VIN on the MPU9250?

Thanks for the help Kris!

kriswiner commented 5 years ago

Shouldn;t be, as long as you are not using 5 V anywhere.

On Sat, Oct 6, 2018 at 8:51 AM straldr notifications@github.com wrote:

Currently I am using a borrowed EV_MPU9250 while waiting for the one I have ordered. I will try the sketch on the new one once I receive it. Just to clarify, is there any problem if I connect the 3.3V on Arduino Mega 2560 with the VIN on the MPU9250?

Thanks for the help Kris!

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

straldr commented 5 years ago

Hi Kris,

I have received my EV-MPU 9250 and tested the same sketch on it. The raw data from the magnetometer is still all zeros. Is there a difference between a normal MPU9250 and the evaluation board? The board I am using is https://store.invensense.com/ProductDetail/EVMPU9250-TDK-InvenSense/497138/

kriswiner commented 5 years ago

No idea about this device. If you want to send me one I will try to make it work.

What do you get when you read the eight bytes between ST1 and ST2 including the 6 bytes of mag data? What do these eight bytes look like?

On Fri, Oct 19, 2018 at 2:42 AM straldr notifications@github.com wrote:

Hi Kris,

I have received my EV-MPU 9250 and tested the same sketch on it. The raw data from the magnetometer is still all zeros. Is there a difference between a normal MPU9250 and the evaluation board? The board I am using is https://store.invensense.com/ProductDetail/EVMPU9250-TDK-InvenSense/497138/

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

straldr commented 5 years ago

When I read from ST1 to ST2 with the 6 bytes of mag data i get 0 values for all. I will try to contact Invensense to ask about the mag data problem. Thanks for the help kris.

kriswiner commented 5 years ago

I took a quick look at the device and it is quite complicated. It might be necessary to connect/disconnect solder jumpers to get the MPU9250 to work properly, although this seems unlikely. I suspect there is something in the software that you are doing/not doing that is causing the trouble.

Usually, if one can see the AK8963C on the I2C bus at address 0x0C and one can read the WHO_AM_I ==0x48 then one can read data. In order to read data though, one must 1) enable pass through mode bu setting bit 1 of the INT_CFG to 1 and enable continuous mode in the AK8963C registers.

Didi you do all of these things?

You might be better off using an easier to use (and better designed) MPU9250 breakout like this https://www.tindie.com/products/onehorse/mpu9250-teensy-3x-add-on-shields/ one or this https://www.tindie.com/products/TleraCorp/mpu9250-add-ons-for-ladybug/ one.

On Fri, Oct 19, 2018 at 9:14 PM straldr notifications@github.com wrote:

When I read from ST1 to ST2 with the 6 bytes of mag data i get 0 values for all. I will try to contact Invensense to ask about the mag data problem. Thanks for the help kris.

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

straldr commented 5 years ago

Hi Kris, Sorry for the late reply. I have contacted Invensense but all they have sent me are some additional data sheets, so it wasn't of any use.

For the INT_PIN parts I'm assuming its this part: writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22);
writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); The continuous mode for AK8963 is also inside the initAK8963 function: writeByte(AK8963_ADDRESS, AK8963_CNTL, Mscale << 4 | Mmode); where Mmode = 0x02;

I have also read a comment on a forum about an error in the build of AK8963 (https://electronics.stackexchange.com/questions/210295/accessing-magnetometer-results-in-mpu-9250), would this be the source of the problem?

Regardless, if I am not able to fix the problem I will consider to switch to another board. Thanks for the help Kris.

kriswiner commented 5 years ago

Yes, you have to read ST2 (so seven bytes in all) to get continuous mode to work with the AK8963. It works for me either one-shot (triggered), 8 Hz or 100 Hz no problem.

If you have two devices on your board with the same I2C address this will cause no end of problems.

I wouldn't recommend the BNO055 since the Bosch sensors are subpar https://github.com/kriswiner/MPU6050/wiki/9-DoF-Motion-Sensor-Bakeoff for orientation estimation, especially the magnetometer and accel.

For an MPU9250 breakout that will work you can try this https://www.tindie.com/products/onehorse/mpu9250-teensy-3x-add-on-shields/ .

And if you want a motion coprocessor so you can just read Euler angles via I2C you can try this https://www.tindie.com/products/onehorse/ultimate-sensor-fusion-solution-mpu9250/ .

On Mon, Oct 29, 2018 at 2:42 AM straldr notifications@github.com wrote:

Hi Kris, Sorry for the late reply. I have contacted Invensense but all they have sent me are some additional data sheets, so it wasn't of any use.

For the INT_PIN parts I'm assuming its this part: writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22); writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); The continuous mode for AK8963 is also inside the initAK8963 function: writeByte(AK8963_ADDRESS, AK8963_CNTL, Mscale << 4 | Mmode); where Mmode = 0x02;

I have also read a comment on a forum about an error in the build of AK8963 ( https://electronics.stackexchange.com/questions/210295/accessing-magnetometer-results-in-mpu-9250), would this be the source of the problem?

Regardless, if I am not able to fix the problem I will consider to switch to another board. Thanks for the help Kris.

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

straldr commented 5 years ago

Hi Kris,

I would just like to confirm before I purchase the board, but https://www.tindie.com/products/onehorse/mpu9250-teensy-3x-add-on-shields/ would work with Arduino Mega2560 as well right?

kriswiner commented 5 years ago

Well these breakouts are intended to mount onto the Teensy. But if you want to solder wires onto the breakout boards to connect to the Mega then as long as the Mega has 3V3/GND and an I2C bus then, yes, the MPU9250 breakout will work with it.

On Thu, Nov 8, 2018 at 11:28 PM straldr notifications@github.com wrote:

Hi Kris,

I would just like to confirm before I purchase the board, but https://www.tindie.com/products/onehorse/mpu9250-teensy-3x-add-on-shields/ would work with Arduino Mega2560 as well right?

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

straldr commented 5 years ago

Alright I will purchase it then. Thanks for the help Kris!

straldr commented 5 years ago

Hey Kris,

I have received the new board and tested it. It works great! Thanks for the patience and help!

Cheers!

kriswiner commented 5 years ago

Glad to hear everything works. Kris

On Wed, Jan 2, 2019 at 5:02 AM straldr notifications@github.com wrote:

Hey Kris,

I have received the new board and tested it. It works great! Thanks for the patience and help!

Cheers!

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

fafoux commented 4 years ago

Hey straldr, Hey Kris, I would like to know if you had solved your issue with the EVB_MPU9250 from invensense ? I bought this board and now i am able to read all data from Accel and Gyrro but not from the magnetometer AK8963 like you. The i2c communication from my Raspberry pi3 finds the AK8963 at 0x0C. I can read the WHO_AM_I ==0x48 register and then I can write and read the register CNTL1 set in continus mode 0x16. 0x16 => "001 0110" => BIT=1 means 16bits outputs and MODE[3:0]="0110"=Continuous measurement mode 2 = 100Hz Before reading the data register I waiting for DRDY = 1 but that never hapend ! Any suggestions are welcome Thanks for the help !

kriswiner commented 4 years ago

You have to read the status register ST2 every time you read data to make continuous mode work. Try reading all 7 data + status bytes after configuration.

Try one-shot mode and see if that works.

There are a lot of code examples showing how to make this work, and if you can write and read AK8963 registers there is no reason it shouldn;t be working.

On Thu, May 7, 2020 at 7:59 AM fafoux notifications@github.com wrote:

Hey straldr, Hey Kris, I would like to know if you had solved your issue with the EVB_MPU9250 from invensense ? I bought this board and now i am able to read all data from Accel and Gyrro but not from the magnetometer AK8963 like you. The i2c communication from my Raspberry pi3 finds the AK8963 at 0x0C. I can read the WHO_AM_I ==0x48 register and then I can write and read the register CNTL1 set in continus mode 0x16. 0x16 => "001 0110" => BIT=1 means 16bits outputs and MODE[3:0]="0110"=Continuous measurement mode 2 = 100Hz Before reading the data register I waiting for DRDY = 1 but that never hapend ! Any suggestions are welcome Thanks for the help !

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/313#issuecomment-625307840, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABTDLKQXQZQFRQY7QIC7BL3RQLEEFANCNFSM4FZM2BQA .

fafoux commented 4 years ago

Hey Kris, Thanks for your fast reply. I tryed to read all 6 data register 0x03 to 0x08 plus the status bytes @ 0x09 after my configuration in single mode. I got 0x0 for all register (data + status) A part of my code :

Write_byte_data(0x0C , CNTL1 , 0x00) //power down mode Time.sleep(0.01) Write_byte_data(0x0C , CNTL1 , 0x0F) //set read FuseRom mode Time.sleep(0.01) I read ASAX, ASAY and ASAZ and then using the formula from the datasheet, that return 0.5 for all sensitivity adjustment. Write_byte_data(0x0C , CNTL1 , 0x00) //power down mode Time.sleep(0.01) Write_byte_data(0x0C , CNTL1 , 0x11)// set in single measurement mode Time.sleep(0.01) Print( hex(bus_read_byte_data(0x0C , CNTL1)) // that return 0x11 data = read_i2c_block_data(0x0C , 0x03, 7) // read 7 byte from 0x03 to 0x09 Print(hex(data[0]) , hex(data[1]) , hex(data[2]) , hex(data[3]) , hex(data[4]) , hex(data[5]) , hex(data[6]))

Of course the MPU-9250 is set in Bypass Enable by 0x22 in register INT_PIN_CFG and I enable the interput by 0x01 in register INT_ENABLE before the configuration of the AK8963. If i dont do that i saw 0xFF every time due to internal pull-up. My code is based on this one : https://github.com/FaBoPlatform/FaBo9AXIS-MPU9250-Python/blob/master/FaBo9Axis_MPU9250/MPU9250.py See readMagnet() line 242 It is a simple part of your code. I realy dont understand why DRDY stays at "0". Next step i will try a selftest mode and see results.

Thanks for your help i will come back to give you the results.

kriswiner commented 4 years ago

Looks like you are able to write one byte at a time and read one byte at a time but not read multiple bytes. The fuze data is wrong, so you are not properly reading these registers. Try reading one byte at a time until you fix your multibyte read function.

On Fri, May 8, 2020 at 7:20 AM fafoux notifications@github.com wrote:

Hey Kris, Thanks for your fast reply. I tryed to read all 6 data register 0x03 to 0x08 plus the status bytes @ 0x09 after my configuration in single mode. I got 0x0 for all register (data + status) A part of my code :

Write_byte_data(0x0C , CNTL1 , 0x00) //power down mode Time.sleep(0.01) Write_byte_data(0x0C , CNTL1 , 0x0F) //set read FuseRom mode Time.sleep(0.01) I read ASAX, ASAY and ASAZ and then using the formula from the datasheet, that return 0.5 for all sensitivity adjustment. Write_byte_data(0x0C , CNTL1 , 0x00) //power down mode Time.sleep(0.01) Write_byte_data(0x0C , CNTL1 , 0x11)// set in single measurement mode Time.sleep(0.01) Print( hex(bus_read_byte_data(0x0C , CNTL1)) // that return 0x11 data = read_i2c_block_data(0x0C , 0x03, 7) // read 7 byte from 0x03 to 0x09 Print(hex(data[0]) , hex(data[1]) , hex(data[2]) , hex(data[3]) , hex(data[4]) , hex(data[5]) , hex(data[6]))

Of course the MPU-9250 is set in Bypass Enable by 0x22 in register INT_PIN_CFG and I enable the interput by 0x01 in register INT_ENABLE before the configuration of the AK8963. If i dont do that i saw 0xFF every time due to internal pull-up. My code is based on this one : https://github.com/FaBoPlatform/FaBo9AXIS-MPU9250-Python/blob/master/FaBo9Axis_MPU9250/MPU9250.py See readMagnet() line 242 It is a simple part of your code. I realy dont understand why DRDY stays at "0". Next step i will try a selftest mode and see results.

Thanks for your help i will come back to give you the results.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9250/issues/313#issuecomment-625839056, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABTDLKQDK4CSZUAWF345L73RQQIMXANCNFSM4FZM2BQA .