kriswiner / MPU9250

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

Question about Yaw heading #25

Closed farneze closed 8 years ago

farneze commented 9 years ago

Hello Kris,

First of all, excellent job with this software! It's really helpful, but I have some question regarding yaw heading. Whenever I move my IMU to a new direction, yaw represents that value correctly, but after a while it returns to the starting direction.

As an example, suppose every coordinate (yaw, pitch, roll) is 0, 0, 0. If I turn the IMU 90 deg fast to the right, yaw changes to 90, 0, 0, but then it slowly returns to 0, 0, 0. Ok, It works as the needle of a compass, but why doesn't it simply continue to point at 90 deg? Pitch and roll works as expected, but why does that happen to yaw?

I've searched for an answer all over google, and I believe that it may be something simple, but the 'click' in my head did not occur. Could you please help me?

Thanks in advance. Arthur

kriswiner commented 9 years ago

Hi Arthur,

Hard to say what the problem could be without more info.

I will assume you are using an MPU9250 controlled with an Arduino or Teensy. Then I would ask if you have calibrated your sensors to remove bias, especially the magnetometer? How have you set up your sample rates? What is the rate of sensor fusion your microcontroller can achieve with the Madgwick or Mahony filter?

Kris

farneze commented 9 years ago

Kris, thanks for your reply. Sorry for not specifying some details, here they are:

I'm using MPU9250 and Teensy 3.1. I didn't change sample rates. So, looking at the code:

Mahony: (I'm at work, so I can't change the filter) Madgwick: 1450 Hz

Changes done to code:

Calibration was done by moving the IMU in an '8' pattern method, but wasn't personalized. As I'm still at work, I'll do it when a get back to home. But I have a video of its values as a cube working on Unity3D. Roll and pitch works fine, but at 14 sec you can see the yaw problem which values correspond to.

https://www.youtube.com/watch?v=8Lw_MjzM0Xs

Thanks again for your time, Arthur

kriswiner commented 9 years ago

Yeah, that is really weird. Your set up look fine, I wonder if you can confirm that at rest you see zero rotation and acceleration (to within 10 mdps and 10 mgs), and 1 g gravity on the z-axis, then for mag you should see something close to the mean mag at your location. For my location, the mean mag is 50, 200, and 450 milliGauss, and after figure eight calibration I usually see something like x = 100, y = 200, and z = 400 milliGauss depending on how thoroughly I do the mag calibration.

After proper calibration, my yaw is steady after changes in heading, you can see some of the results at the MPU6050 Wiki. The only time I see this kind of yaw drift is when the sensors (especially the mag) are uncalibrated).

Kris

farneze commented 8 years ago

Ok, I've calibrated it correctly and it is showing good behaviour, with the exception of when I rotate roll and/or pitch. After I rotate roll and pitch (and maintain those rotations), I try to rotate horizontally (not yaw), but my cube rotate strangely its yaw. It can be seen at 0:13 here:

https://youtu.be/R5f8xa7B88U

It is like yaw, pitch and roll reference are locked and separated from each other... Its like on this video:

https://youtu.be/UpSMNYTVqQI

When I move Psi, it moves alongside the red plane. I believe there is something i'm missing about quaternions and euler conversion, or the madgwick algorithm is not correct.

I've talked to Navid on the first video fo this thread and he said there that you have some problem on this regard. Could you please elaborate on that?

Arthur

farneze commented 8 years ago

Hello, just to close this thread, It now works with Unity. The only exception is that it still has some jitter, as I still haven't ajusted the beta parameter.

To reorient it correctly, all I did was:

So, the command that Unity uses to apply the rotation to the object is:

// x -z y w quatAux.Set (quat[1], -quat[3], quat[2], quat[0]); transform.rotation = quatAux;

I know it is a mess, specially that z exchanged with y... but I hope it helps someone. Soon I'll post the Unity and arduino code, and Matlab script to correct and visualize the magnetometer calibration on youtube as "arthurfarneze".

Best regards

kriswiner commented 8 years ago

This might have something to do with the NED convention assumed by Madgwick. North has to be chosen and then the sensor data fed into the Madgwick function that correspond to the North, East, Down convention. I will post something at github about how to do this in a bit. But if you have this wrong you can get weird results.

-----Original Message----- From: Farneze [mailto:notifications@github.com] Sent: November 13, 2015 6:48 PM To: kriswiner/MPU-9250 Cc: Kris Winer Subject: Re: [MPU-9250] Question about Yaw heading (#25)

Hello, just to close this thread, It now works with Unity. The only exception is that it still has some jitter, as I still haven't ajusted the beta parameter.

To reorient it correctly, all I did was:

So, the command that Unity uses to apply the rotation to the object is:

// x -z y w quatAux.Set (quat[1], -quat[3], quat[2], quat[0]); transform.rotation = quatAux;

I know it is a mess, specially that z exchanged with y... but I hope it helps somehow. Soon I'll post the Unity and arduino code, and Matlab script to correct and visualize the magnetometer calibration.

Best regards

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9250/issues/25#issuecomment-156613700 . https://github.com/notifications/beacon/AGY1qkAyZQn_L4Tb9xKqZGLSIjxFlQZmks5 pFphtgaJpZM4GLil9.gif

farneze commented 8 years ago

Yes, I think that there is more for me to know about quaternions, because Unity was applying the sequence pitch, roll, yaw by the time the videos were uploaded. When I changed from:

quatAux.Set (quat[1], quat[3], quat[2], quat[0]);

to

quatAux.Set (quat[1], -quat[3], quat[2], quat[0]);

unity applied yaw, pitch and roll. How changing just the signal of that element changes the sequence applied by unity? I don't know if I observed wrongly, but I'll search for an answer on the following weeks.

Thanks again for the help, your programs, and instruction texts.

Best regards

kriswiner commented 8 years ago

Take a look at the attached.

Kris

-----Original Message----- From: Farneze [mailto:notifications@github.com] Sent: November 13, 2015 8:50 PM To: kriswiner/MPU-9250 Cc: Kris Winer Subject: Re: [MPU-9250] Question about Yaw heading (#25)

Yes, I think that there is more for me to know about quaternions, because Unity was applying the sequence pitch, roll, yaw by the time the videos were uploaded. When I changed from:

quatAux.Set (quat[1], quat[3], quat[2], quat[0]);

to

quatAux.Set (quat[1], -quat[3], quat[2], quat[0]);

unity applied yaw, pitch and roll. How changing just the signal of that element changes the sequence applied by unity? I don't know if I observed wrongly, but I'll search for an answer on the following weeks.

Thanks again for the help, your programs, and instruction texts.

Best regards

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9250/issues/25#issuecomment-156628182 . https://github.com/notifications/beacon/AGY1qqv825pEttbBm7Xs40iB0R17K99fks5 pFrT9gaJpZM4GLil9.gif

farneze commented 8 years ago

Sorry, but I 've checked my email and there is nothing attached. xD Would you mind to send it directly to my email? (not through github)

arthurfarneze@gmail.com

BR

iywgqt commented 7 years ago

@Farneze thank you, it works well in unity. quatAux.Set (quat[1], -quat[3], quat[2], quat[0]);

mpava commented 7 years ago

Hi Arthur, I have the same issue. The yaw behaves like a compass needle, instead of staying at a yaw orientation you leave it at, it converges back to the same fixed yaw, like a compass needle would. It's very reliable, it always does it. I am using MPU9250. I am not using Kris' code. But I am using Kris' logic for mag calibration. I am using the official Madgwick implementation of the filter. I was thinking the issue is with the order I pass the parameters ax,ay,az,gx,gy,gz,mx,my,mz. I tried all sensible orders and signs without luck. This order works perfectly with the exception of the yaw convergence: ay,-ax,az,gy,-gx,gz,-mx,-my,-mz.

Any thoughts? I also put some more info previously at: https://github.com/kriswiner/MPU-9250/issues/2 thanks

Michael

kriswiner commented 7 years ago

Four possibilities:

1) inadequate calibration--> check calibration

2) improper feed order of data to Madgwick algorithm --> data must be in NED order.

3) insufficient fusion rate--> fusion rate needs to be minimum 4-5x of gyro sample rate, 200 Hz gyro rate means >1 kHz fusion rate

4) faulty sensor --> do not use any product from CJU or MPU9250 from Sparkfun, etc

On Wed, May 3, 2017 at 10:26 AM, mpava notifications@github.com wrote:

Hi Arthur, I have the same issue. The yaw behaves like a compass needle, instead of staying at a yaw orientation you leave it at, it converges back to the same fixed yaw, like a compass needle would. It's very reliable, it always does it. I am using MPU9250. I am not using Kris' code. But I am using Kris' logic for mag calibration. I am using the official Madgwick implementation of the filter. I was thinking the issue is with the order I pass the parameters ax,ay,az,gx,gy,gz,mx,my,mz. I tried all sensible orders and signs without luck. This order works perfectly with the exception of the yaw convergence: ay,-ax,az,gy,-gx,gz,-mx,-my,-mz.

Any thoughts? I also put some more info previously at: #2 https://github.com/kriswiner/MPU-9250/issues/2 thanks

Michael

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU-9250/issues/25#issuecomment-298979086, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qqMbRtaGSE2G2k_IcmLEmPMlgzAZks5r2LjLgaJpZM4GLil9 .

farneze commented 7 years ago

The line I used on my code was to update Madwick: MadQuatUpdateMag(ax, ay, az, gxPI/180.0f, gyPI/180.0f, gz*PI/180.0f, my, mx, -mz);

While on unity i had to use this sequence when setting orientation: quatAux.Set(Q[1], -Q[3], Q[2], Q[0]);

Hope it helps.

Arthur

jubueche commented 6 years ago

You mentioned not to use the MPU 9250 breakout from Sparkfun. I am using it, and indeed it is not working. I am pretty sure that my code is correct, I calibrate it correctly etc. Why is that so?

kriswiner commented 6 years ago

It should work, but it is not well designed and it won;t give very good resuts. Most of the reason is because current-carrying traces are routed directly underneath the MPU9250 package. A no-no.

On Sun, Dec 3, 2017 at 10:53 AM, jubueche notifications@github.com wrote:

You mentioned not to use the MPU 9250 breakout from Sparkfun. I am using it, and indeed it is not working. I am pretty sure that my code is correct, I calibrate it correctly etc. Why is that so?

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

jubueche commented 6 years ago

Ok wow. When I run it in DEBUG mode, I get a frequency of 30 Hz. I am running on the adafruit adalogger which has a ATmega 32u4 . Any idea why this could be the case? I have implemented everything exactly the way you did. I am also experiencing drift in my Yaw. Also I set Wire.setClock(400000) to speed it up a little.

This is my code: https://drive.google.com/file/d/1nDgZZfxojsy4SeMAOMXssapDzrOujrWJ/view?usp=sharing

kriswiner commented 6 years ago

Is the 32u4 a 16 MHz AVR MCU? You'll never get high fusion rates from this. Try something like this:

https://www.tindie.com/products/TleraCorp/ladybug-stm32l432-development-board/

On Sun, Dec 3, 2017 at 11:16 AM, jubueche notifications@github.com wrote:

Ok wow. When I run it in DEBUG mode, I get a frequency of 30 Hz. I am running on the adafruit adalogger which has a ATmega 32u4 . Any idea why this could be the case? I have implemented everything exactly the way you did. I am also experiencing drift in my Yaw. Also I set Wire.setClock(400000) to speed it up a little.

This is my code: https://drive.google.com/file/d/1nDgZZfxojsy4SeMAOMXssapDzrOuj rWJ/view?usp=sharing

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

jubueche commented 6 years ago

Yes it is. Can't I turn down the gyro to 10 Hz? I have a Cortex M0+. Will this be enough? Also, could you tell me more about the problem with the spark fun thing? I will do my own little breakout board using the MPU 9250 and want to avoid everything that could lead to those problems. Also the link you sent me seems really interesting. Is the code I sent you correct? Julian

kriswiner commented 6 years ago

I cannot review your code.

You need to be able to run the fusion filter at 1000 Hz. No AVR or Cortex M0 is going to be able to do this.

You can see the MPU9250 at my Tindie site; it is open source and can compare against your design.

On Sun, Dec 3, 2017 at 12:09 PM, jubueche notifications@github.com wrote:

Yes it is. Can't I turn down the gyro to 10 Hz? I have a Cortex M0+. Will this be enough? Also, could you tell me more about the problem with the spark fun thing? I will do my own little breakout board using the MPU 9250 and want to avoid everything that could lead to those problems. Also the link you sent me seems really interesting. Is the code I sent you correct? Julian

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

jubueche commented 6 years ago

I think yours is using a cortex M4, right? Why do you need a fusion rate that high? I saw videos where people demonstrated their success on a simple Arduino with a sample rate of 100 Hz https://www.youtube.com/watch?v=8EMkoOpSGz4 Why do you think that you need 1000 Hz?

jubueche commented 6 years ago

Wait a minute. I think this one uses the arduino mega, which has 16 MIPS. Maybe that is the reason it performs so well. Damn it. Are you sure? I have my project planned out with the cortex M0+. Is there any way to get precise readings with this chip?

jubueche commented 6 years ago

What if I sample on the chip and process later on a computer? I guess I can sample the gyroscope values etc. at 500 Hz or even more. Shouldnt this work?

kriswiner commented 6 years ago

You can log data and do the fusion on a pc yes.

If you use iterative fusion filters like the Madwick or Mahony filters, you need minimum 4 or 5 iterations per data sample. To capture human movement, you need to run the sensors at 200 Hz or 400 Hz, so you need 1 - 2 kHz fusion rates minimum.

This is only necessary if you want low latency and accurate orientation estimation.

If you don;t care about time lags and large heading errors then an Arduino Pro Mini should be good enough.

On Sun, Dec 3, 2017 at 12:26 PM, jubueche notifications@github.com wrote:

What if I sample on the chip and process later on a computer? I guess I can sample the gyroscope values etc. at 500 Hz or even more. Shouldnt this work?

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

jubueche commented 6 years ago

Ok thats great thank you. I have been trying to get results for 3 straight nights now and it didnt work, so now I know what to do. So is there anything I have to keep in mind if I process it "offline"? Thank you so much you are truly a great engineer

jubueche commented 6 years ago

Oh and btw just to make sure, for the mag calibration, it should be an eight and not a infinity symbol, right? And on sparkfun I saw something like this: myIMU.magbias[0] = +470.; // User environmental x-axis correction in milliGauss TODO axis?? myIMU.magbias[1] = +120.; // User environmental x-axis correction in milliGauss myIMU.magbias[2] = +125.; I assume it is better do to a calibration, right?

kriswiner commented 6 years ago

These are fixed values copied from one of my sketches (Sparkfun is lazy) that apply to one single MPU9250, not all of them! You have to do the calibration for each sensor separately. If you are using these values you will get gargabe.

On Sun, Dec 3, 2017 at 12:41 PM, jubueche notifications@github.com wrote:

Oh and btw just to make sure, for the mag calibration, it should be an eight and not a infinity symbol, right? And on sparkfun I saw something like this: myIMU.magbias[0] = +470.; // User environmental x-axis correction in milliGauss TODO axis?? myIMU.magbias[1] = +120.; // User environmental x-axis correction in milliGauss myIMU.magbias[2] = +125.; I assume it is better do to a calibration, right?

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

jubueche commented 6 years ago

Right, but if I do the calibration multiple times, I dont get the same values. Did you take the mean there?

kriswiner commented 6 years ago

Ofc ourse you won't get exactly the same values.

Use an automated calibration function like found here:

https://github.com/kriswiner/MPU6050/wiki/Simple-and-Effective-Magnetometer-Calibration

or in one of my later sketches.

On Sun, Dec 3, 2017 at 12:47 PM, jubueche notifications@github.com wrote:

Right, but if I do the calibration multiple times, I dont get the same values. Did you take the mean there?

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

jubueche commented 6 years ago

I take it all back. I have tried the scheme and get the same results.

jubueche commented 6 years ago

Yeah not exactly, sure but they differ by ~5 and thats good

kriswiner commented 6 years ago

5/500 is pretty good

On Sun, Dec 3, 2017 at 12:52 PM, jubueche notifications@github.com wrote:

Yeah not exactly, sure but they differ by ~5 and thats good

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

jubueche commented 6 years ago

Is there something I should keep in mind when I run this offline? I am thinking that I store the time for the delta t's and thats it, right? Also what sampling freq do you recommend?

jubueche commented 6 years ago

Ah there was another thing. I attached an interrupt to my SCL pin (2) and it got triggered once. I dont have a pulldown or pullup resistor. Is it important to have that?

kriswiner commented 6 years ago

????

You need pullups on the SDA and SCL lines of the I2C bus, not on an interrupt usually. But why would you atach an interrupt to SCL?

On Sun, Dec 3, 2017 at 1:04 PM, jubueche notifications@github.com wrote:

Ah there was another thing. I attached an interrupt to my SCL pin (2) and it got triggered once. I dont have a pulldown or pullup resistor. Is it important to have that?

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

jubueche commented 6 years ago

Where did you attach the interrupt. I connected my MPU to SCL and SDA of the breakout. Where would you attach the interrupt?

kriswiner commented 6 years ago

Where is the SDA and SCL of the MPU9250 connected then?

On Sun, Dec 3, 2017 at 1:25 PM, jubueche notifications@github.com wrote:

Where did you attach the interrupt. I connected my MPU to SCL and SDA of the breakout. Where would you attach the interrupt?

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

jubueche commented 6 years ago

2 and 3. I tried both. Couldnt I just write these pins to LOW so that the signal pulls it up and generates a RISING interrupt? Should I connect to SCL or SDA, where does the MPU generate the interrupt?

kriswiner commented 6 years ago

????????????

You MUST have external pullups on the SCL and SDA lines, typically 4K7 Ohms. The SDA and SCL lines must be at 3V3 when no signal is present. Activity of the I2C bus is represented by pulling the line low.

You may use the interrupt, I would choose some other interrupt-capable pin, not SDA or SCL.

Maybe review how I2C and interrupts work on some Sparkfun tutorial?

On Sun, Dec 3, 2017 at 1:31 PM, jubueche notifications@github.com wrote:

2 and 3. I tried both. Couldnt I just write these pins to LOW so that the signal pulls it up and generates a RISING interrupt? Should I connect to SCL or SDA, where does the MPU generate the interrupt?

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

jubueche commented 6 years ago

Oh I didnt know that activity on I2C pulls it down.