kriswiner / MPU9150

Arduino sketch for MPU9150 9DoF with AHRS sensor fusion
75 stars 36 forks source link

Magnetometer calibration and heading (yaw) #3

Open pmavros opened 9 years ago

pmavros commented 9 years ago

Hi Kris, Amazing work porting the MARG into a nice arduino sketch!

I have got it to work with the https://www.sparkfun.com/products/11486, but the yaw values don't range 360 degrees as I rotate the sensors on its axis (rotating around itself, flat on the table mag-z) and there is not good response, so I may turn it 90 degrees North and it only registers 10º change. The other two pitch and roll seem to work fine.

How good is the calibration? Is it worth implementing something like this? http://www.camelsoftware.com/firetail/blog/uavs/3-axis-magnetometer-calibration-a-simple-technique-for-hard-soft-errors/

Many thanks, Panos

kriswiner commented 9 years ago

Panos,

The sketch has no calibration for the magnetometer except the manual calibration I might have done for my particular MPU9150. I suggest at least you record the min/max value on all three axes and subtract the average so as to re-center the mag response surface. This is all I did. If you suggest something more sophisticated and automatic and get it to work well I would love to incorporate it into my MPU9x50 and LSM9DS0 sketches.

Kris

From: ΠΜ Sent: Monday, October 13, 2014 12:36 PM To: kriswiner/MPU-9150 Subject: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Hi Kris, Amazing work porting the MARG into a nice arduino sketch!

I have got it to work with the https://www.sparkfun.com/products/11486, but the yaw values don't range 360 degrees as I rotate the sensors on its axis (rotating around itself, flat on the table mag-z) and there is not good response, so I may turn it 90 degrees North and it only registers 10º change. The other two pitch and roll seem to work fine.

How good is the calibration? Is it worth implementing something like this? http://www.camelsoftware.com/firetail/blog/uavs/3-axis-magnetometer-calibration-a-simple-technique-for-hard-soft-errors/

Many thanks, Panos

— Reply to this email directly or view it on GitHub.

pmavros commented 9 years ago

Kris,

will have a thought on that. The link I said has a good solution to remove both hard-iron and soft-iron bias. Also quite quick to implement.

My question holds. the yaw (headings) gives neither a 360º nor a -180º to 180º output but rather a almost random result. I am using the mpu9150 sparkfun SM11486. Also I am confused with which sensor alignment you finally choose as reference the acc or the mag? So which xyz should I use to find north etc?

Finally I had a look on the MPU6050_9Axis_MotionApps41.h and it seems it also has functions to calculate the euler quaternions etc (e.g. MPUgetyawptichroll) - but you are not using those, correct? If that's the case why?

Cheers, Panos

kriswiner commented 9 years ago

Hi Panos,

I am using the x,y,z of the accel/gyro as reference. If you do not calibrate the magnetometer the Euler values of yaw, pitch, and roll can be quite non-sensical. I wrote my own AHRS routines based on open-source Madgwick and Mahoney sensor fusion algorithms. I don’t like the way Invensense programs are structured nor do I like their dependence on a binary blob for the DMP, which they also depend on.

Kris

From: ΠΜ Sent: Tuesday, October 14, 2014 5:41 AM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Kris,

will have a thought on that. The link I said has a good solution to remove both hard-iron and soft-iron bias. Also quite quick to implement.

My question holds. the yaw (headings) gives neither a 360º nor a -180º to 180º output but rather a almost random result. I am using the mpu9150 sparkfun SM11486. Also I am confused with which sensor alignment you finally choose as reference the acc or the mag? So which xyz should I use to find north etc?

Finally I had a look on the MPU6050_9Axis_MotionApps41.h and it seems it also has functions to calculate the euler quaternions etc (e.g. MPUgetyawptichroll) - but you are not using those, correct? If that's the case why?

Cheers, Panos

— Reply to this email directly or view it on GitHub.

akhilmohan4487 commented 9 years ago

Hello Kris,

After implementing Madwick filter, we have the quaternion representing orientation of MPU9150 in global co-ordinate frame. Now if I want to represent the quaternion in the body co-ordinate frame what should I do ? I have tried to implement (qSB = qGB x q*GS where x is a quaternion multiplication) where s -sensor, b- body and G - global coordinate frame, am I right in doing this ?. After this orientation of MPU in body coordinate frame and expressed in the sensor frame (qSB) is converted to euler angles and I plotted the same. But now if am rotating MPU by 180 I should be able to see a corresponding change in the plot, am I right ? (I have some confusion in using quaternions and am trying to figure it out).

Thanks in advance, Akhil

kriswiner commented 9 years ago

Hi Akhil,

I am not sure what you want to do. The quaternion represents the sensor's absolute orientation with respect to an external (yes, global) standard. This is usually True North. What do you mean by the body coordinate frame in this case?

Kris

-----Original Message----- From: Akhil Mohan [mailto:notifications@github.com] Sent: March 12, 2015 7:13 AM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Hello Kris,

After implementing Madwick filter, we have the quaternion representing orientation of MPU9150 in global co-ordinate frame. Now if I want to represent the quaternion in the body co-ordinate frame what should I do ? I have tried to implement (qSB = qGB x q*GS where x is a quaternion multiplication) where s -sensor, b- body and G - global coordinate frame, am I right in doing this ?. After this orientation of MPU in body coordinate frame and expressed in the sensor frame (qSB) is converted to euler angles and I plotted the same. But now if am rotating MPU by 180 I should be able to see a corresponding change in the plot, am I right ? (I have some confusion in using quaternions and am trying to figure it out).

Thanks in advance, Akhil

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-78486619 . https://github.com/notifications/beacon/AGY1qsn3HDq27TfiuRGSIbtV28fnTfhaks5 n0ZZngaJpZM4CuKSq.gif

akhilmohan4487 commented 9 years ago

Hello, I have a wireless board ready where multiple MPU's can be plugged in and the data can be logged on to a PC. Now on the PC i wanted to animate the motion that humans do in real-time. Say, I am attaching the MPU on elbow and forearm and wanted to measure the joint angle, I have to represent the information in the body coordinate frame (the location where MPU is mounted). I am bit uncertain how to do this ? What is your opinion in this regard ?

Thanks for the quick reply. Akhil

kriswiner commented 9 years ago

If you have absolute orientation for each sensor, can you not rather simply calculate the relative angle between, say, the two IMU's x-axes? You have two orientation vectors wrt the same global absloute reference; hwy can you not simply compare these two orientations directly? Why do you need a transform?

akhilmohan4487 commented 9 years ago

Yes, we will get a relative orientation of one segment with other in this way. But the problem is i don't know the value of a at time = 0. This can be known only when you keep your body in a fixed pose. For that, initially the segment under measurement is calibrated.

For calibration - (R)GB = (R)SB x (R)GS (R)GB - orientation info of body wrt global (known for a fixed pose) (R)SB - orientation info of body wrt sensor (R)GS - orientation info of sensor wrt global (Madgwick out data converted in rotation matrix form)

We can do all these algebra in quaterion form and is mathematically and computationally useful.

For me, I am nor sure how do we represent (R)GB (Is it a (I)3x3 matrix at rest) ? I don't know.

kriswiner commented 9 years ago

I am not sure what you are asking. If you know each sensors absolute orientation (i.e., quaternion) wrt a fixed global reference like True North, don't you know everything you need to know?

akhilmohan4487 commented 9 years ago

Hello, I would try my best to explain what I wanted to do. After the Madgwick filter update, I have a quaternion which represents the absolute orientation of sensor wrt a global co-ordinate frame(NED). Now I am attaching my Imu's to forearm(segment1) and upper-arm(segment2). Now I want to express segment kinematics in global frame. For that, I have to perform an initial calibration where the orientation of the sensor module wrt segment and the relative distances are measured.

Using rotation matrix I know that (R)GB = (R)SB x (R)GS. Now how can I do the same using quaternion where I wanted to know qSB given qGB abd qGS ?

I have tried doing qSB = qGB x qGS (where \ corresponds to Quaternion conjugate and x quaternion multiplication). Here qGB = [0.707, 0, 0, -0.707] and which results in singularities and I don't know how to solve this.

Hope this explanation is fine. I am really sorry if I am not able to convey what I want.

Thanks for your patience Kris.

Ecollot commented 9 years ago

Hi Kris, Do you now have a calibration for the magnetometer? Just to know if I need to figure one out myself or not =) Great work by the way, thanks so much! Emilie

kriswiner commented 9 years ago

Here is a mag calibration routine for the MPU9250 which can be adapted for the MPU9150:

void magcalMPU9250(float * dest1) { uint16_t ii = 0, sample_count = 0; int32_t mag_bias[3] = {0, 0, 0}; int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}, mag_temp[3] = {0, 0, 0}; Serial.println("Mag Calibration: Wave device in a figure eight until done!"); delay(4000); sample_count = 64; for(ii = 0; ii < sample_count; ii++) { readMagData(mag_temp); // Read the mag data for (int jj = 0; jj < 3; jj++) { if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; } delay(135); // at 8 Hz ODR, new mag data is available every 125 ms } // Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]); // Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]); // Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]); mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts dest1[0] = (float) mag_bias[0]_mRes_magCalibration[0]; // save mag biases in G for main program dest1[1] = (float) mag_bias[1]_mRes_magCalibration[1]; dest1[2] = (float) mag_bias[2]_mRes_magCalibration[2]; Serial.println("Mag Calibration done!"); }

Ecollot commented 9 years ago

Thanks so much for answering so fast !

Still working with the code, probably got another few questions popping up, but the main one is : you calculate the biases for the accelerometer and gyroscope, but you never use these when considering the raw values in any way it seems. If you do, where do you use these corrections ? And for now, the magnetometer biases are just put in by hand right ?

On 10 April 2015 at 11:13, Kris Winer notifications@github.com wrote:

Here is a mag calibration routine for the MPU9250 which can be adapted for the MPU9150:

void magcalMPU9250(float * dest1) { uint16_t ii = 0, sample_count = 0; int32_t mag_bias[3] = {0, 0, 0}; int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}, mag_temp[3] = {0, 0, 0}; Serial.println("Mag Calibration: Wave device in a figure eight until done!"); delay(4000); sample_count = 64; for(ii = 0; ii < sample_count; ii++) { readMagData(mag_temp); // Read the mag data for (int jj = 0; jj < 3; jj++) { if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; } delay(135); // at 8 Hz ODR, new mag data is available every 125 ms } // Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]); // Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]); // Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]); mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts dest1[0] = (float) mag_bias[0]_mRes_magCalibration[0]; // save mag biases in G for main program dest1[1] = (float) mag_bias[1]_mRes_magCalibration[1]; dest1[2] = (float) mag_bias[2]_mRes_magCalibration[2]; Serial.println("Mag Calibration done!"); }

— Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91378617.

kriswiner commented 9 years ago

I write the accel and gyro biases to user bias registers. These bias values are automatically subtracted from the raw sensor data. You can also choose to not write any values there and manually subtract the accel and gyro biases like the mag biases are done. I sometimes do this because there is a temperature bit in the accel bias register that has to be preserved and I find sometimes the biases applied automatically by using thebias register value are not quite right for the accelerometer, so I often still do this one by hand.

Kris

-----Original Message----- From: Ecollot [mailto:notifications@github.com] Sent: April 9, 2015 7:19 PM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Thanks so much for answering so fast !

Still working with the code, probably got another few questions popping up, but the main one is : you calculate the biases for the accelerometer and gyroscope, but you never use these when considering the raw values in any way it seems. If you do, where do you use these corrections ? And for now, the magnetometer biases are just put in by hand right ?

On 10 April 2015 at 11:13, Kris Winer notifications@github.com wrote:

Here is a mag calibration routine for the MPU9250 which can be adapted for the MPU9150:

void magcalMPU9250(float * dest1) { uint16_t ii = 0, sample_count = 0; int32_t mag_bias[3] = {0, 0, 0}; int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}, mag_temp[3] = {0, 0, 0}; Serial.println("Mag Calibration: Wave device in a figure eight until done!"); delay(4000); sample_count = 64; for(ii = 0; ii < sample_count; ii++) { readMagData(mag_temp); // Read the mag data for (int jj = 0; jj < 3; jj++) { if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; } delay(135); // at 8 Hz ODR, new mag data is available every 125 ms } // Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]); // Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]); // Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]); mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts dest1[0] = (float) mag_bias[0]_mRes_magCalibration[0]; // save mag biases in G for main program dest1[1] = (float) mag_bias[1]_mRes_magCalibration[1]; dest1[2] = (float) mag_bias[2]_mRes_magCalibration[2]; Serial.println("Mag Calibration done!"); }

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91378617.

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91404035 . https://github.com/notifications/beacon/AGY1qj7yBPwEtmTuSvDNUBHBT4Sqsnoxks5 n9yqsgaJpZM4CuKSq.gif

Ecollot commented 9 years ago

Ok, got that. One more thing, how do define the user-environmental x,y,z axis corrections for the magnetometer? Where do these values come from?

On 10 April 2015 at 14:24, Kris Winer notifications@github.com wrote:

I write the accel and gyro biases to user bias registers. These bias values are automatically subtracted from the raw sensor data. You can also choose to not write any values there and manually subtract the accel and gyro biases like the mag biases are done. I sometimes do this because there is a temperature bit in the accel bias register that has to be preserved and I find sometimes the biases applied automatically by using thebias register value are not quite right for the accelerometer, so I often still do this one by hand.

Kris

-----Original Message----- From: Ecollot [mailto:notifications@github.com] Sent: April 9, 2015 7:19 PM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Thanks so much for answering so fast !

Still working with the code, probably got another few questions popping up, but the main one is : you calculate the biases for the accelerometer and gyroscope, but you never use these when considering the raw values in any way it seems. If you do, where do you use these corrections ? And for now, the magnetometer biases are just put in by hand right ?

On 10 April 2015 at 11:13, Kris Winer notifications@github.com wrote:

Here is a mag calibration routine for the MPU9250 which can be adapted for the MPU9150:

void magcalMPU9250(float * dest1) { uint16_t ii = 0, sample_count = 0; int32_t mag_bias[3] = {0, 0, 0}; int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}, mag_temp[3] = {0, 0, 0}; Serial.println("Mag Calibration: Wave device in a figure eight until done!"); delay(4000); sample_count = 64; for(ii = 0; ii < sample_count; ii++) { readMagData(mag_temp); // Read the mag data for (int jj = 0; jj < 3; jj++) { if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; } delay(135); // at 8 Hz ODR, new mag data is available every 125 ms } // Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]); // Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]); // Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]); mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts dest1[0] = (float) mag_bias[0]_mRes_magCalibration[0]; // save mag biases in G for main program dest1[1] = (float) mag_bias[1]_mRes_magCalibration[1]; dest1[2] = (float) mag_bias[2]_mRes_magCalibration[2]; Serial.println("Mag Calibration done!"); }

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91378617.

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91404035 . < https://github.com/notifications/beacon/AGY1qj7yBPwEtmTuSvDNUBHBT4Sqsnoxks5 n9yqsgaJpZM4CuKSq.gif>

— Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91404945.

kriswiner commented 9 years ago

Do you mean the mag biases, as below or what?

The real mag response surface is generally off-center and ellipsoidal, not the centered, spherical ideal. You can record the min.max mag values in the three axis directions to recenter the response surface. More complicated matrix corrections are required to respherize the response surface. The below function just does the recentering. Or do you mean something else?

-----Original Message----- From: Ecollot [mailto:notifications@github.com] Sent: April 9, 2015 8:52 PM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Ok, got that. One more thing, how do define the user-environmental x,y,z axis corrections for the magnetometer? Where do these values come from?

On 10 April 2015 at 14:24, Kris Winer notifications@github.com wrote:

I write the accel and gyro biases to user bias registers. These bias values are automatically subtracted from the raw sensor data. You can also choose to not write any values there and manually subtract the accel and gyro biases like the mag biases are done. I sometimes do this because there is a temperature bit in the accel bias register that has to be preserved and I find sometimes the biases applied automatically by using thebias register value are not quite right for the accelerometer, so I often still do this one by hand.

Kris

-----Original Message----- From: Ecollot [mailto:notifications@github.com] Sent: April 9, 2015 7:19 PM To: kriswiner/MPU-9150 Cc: Kris Winer Subject: Re: [MPU-9150] Magnetometer calibration and heading (yaw) (#3)

Thanks so much for answering so fast !

Still working with the code, probably got another few questions popping up, but the main one is : you calculate the biases for the accelerometer and gyroscope, but you never use these when considering the raw values in any way it seems. If you do, where do you use these corrections ? And for now, the magnetometer biases are just put in by hand right ?

On 10 April 2015 at 11:13, Kris Winer notifications@github.com wrote:

Here is a mag calibration routine for the MPU9250 which can be adapted for the MPU9150:

void magcalMPU9250(float * dest1) { uint16_t ii = 0, sample_count = 0; int32_t mag_bias[3] = {0, 0, 0}; int16_t mag_max[3] = {0, 0, 0}, mag_min[3] = {0, 0, 0}, mag_temp[3] = {0, 0, 0}; Serial.println("Mag Calibration: Wave device in a figure eight until done!"); delay(4000); sample_count = 64; for(ii = 0; ii < sample_count; ii++) { readMagData(mag_temp); // Read the mag data for (int jj = 0; jj < 3; jj++) { if(mag_temp[jj] > mag_max[jj]) mag_max[jj] = mag_temp[jj]; if(mag_temp[jj] < mag_min[jj]) mag_min[jj] = mag_temp[jj]; } delay(135); // at 8 Hz ODR, new mag data is available every 125 ms } // Serial.println("mag x min/max:"); Serial.println(mag_max[0]); Serial.println(mag_min[0]); // Serial.println("mag y min/max:"); Serial.println(mag_max[1]); Serial.println(mag_min[1]); // Serial.println("mag z min/max:"); Serial.println(mag_max[2]); Serial.println(mag_min[2]); mag_bias[0] = (mag_max[0] + mag_min[0])/2; // get average x mag bias in counts mag_bias[1] = (mag_max[1] + mag_min[1])/2; // get average y mag bias in counts mag_bias[2] = (mag_max[2] + mag_min[2])/2; // get average z mag bias in counts dest1[0] = (float) mag_bias[0]_mRes_magCalibration[0]; // save mag biases in G for main program dest1[1] = (float) mag_bias[1]_mRes_magCalibration[1]; dest1[2] = (float) mag_bias[2]_mRes_magCalibration[2]; Serial.println("Mag Calibration done!"); }

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91378617.

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91404035 . <

https://github.com/notifications/beacon/AGY1qj7yBPwEtmTuSvDNUBHBT4Sqsnoxks5 n9yqsgaJpZM4CuKSq.gif>

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91404945.

Reply to this email directly or view it on GitHub https://github.com/kriswiner/MPU-9150/issues/3#issuecomment-91419839 . https://github.com/notifications/beacon/AGY1qgWW-WzFm7GoSYZbGw5MmgMp_I56ks5 n90BCgaJpZM4CuKSq.gif

PatelKishanJ commented 7 years ago

Hello kris,

 I have using atan formula to find magnetic direction.But its working good if Device put in position by which  magnetic- z direction will vertically down.
So,if i change the device position like that magnetic x direction will vertically down.So,below formula to find the direction will be wrong.

heading_dir = 90 - ( atan ( mx / my ) ) * ( 180 / PI ) - 23.5; //here, 23.5 is a declination angle.

So,any idea by which i can find that which direction is vertically down?.

kindly reply.

kriswiner commented 7 years ago

Why don't you want to use 9 DoF sensor fusion for heading estimation? It is a much more accurate solution.

Your approach can only work in some limited circumstances. And then not very well.

PatelKishanJ commented 7 years ago

I have no idea about 9 DoF sensor.Can you explain me,how can i use and how can access and how it is useful?.

PatelKishanJ commented 7 years ago

Actually,I have using IMU/mpu-9250 to detect position of device. In our project,we will attach our device by OBD connector.

But problem is critical for that.Because the OBD connector has attached in different types for different device.So,magnetic direction will changes.

kriswiner commented 7 years ago

9DoF sensor fusion like used here:

https://github.com/kriswiner/MPU-9250/blob/master/MPU9250_MS5637_AHRS_t3.ino

On Fri, May 12, 2017 at 10:13 PM, jenextech notifications@github.com wrote:

Actually,I have using IMU/mpu-9250 to detect position of device. In our project,we will attach our device by OBD connector.

But problem is critical for that.Because the OBD connector has attached in different types for different device.So,magnetic direction will changes.

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

PatelKishanJ commented 7 years ago

so,its for find yaw,pitch and roll...right?

PatelKishanJ commented 7 years ago

I refer code which you told. Actually ,i want to measure direction and its work.But problem is that,device installation-direction is not fix.So,device movement direction will change(false).So,how can i use yaw,pitch and roll reading to measure device's movement with direction?.

kriswiner commented 7 years ago

You need to calibrate your sensors.

On Thu, Jun 1, 2017 at 4:43 AM, jenextech notifications@github.com wrote:

I refer code which you told. Actually ,i want to measure direction and its work.But problem is that,device installation-direction is not fix.So,device movement direction will change(false).So,how can i use yaw,pitch and roll reading to measure device's movement with direction?.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9150/issues/3#issuecomment-305469332, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qryIbDY6BTNgnWMZGkjyUcOITf-gks5r_qPPgaJpZM4CuKSq .

PatelKishanJ commented 7 years ago

imu_direction_issue1

see this image.... it reveals that device put in any direction ,when it start it shows same direction.... then when i rotate device clockwise, direction will in this sequence like NW -> NE -> SE -> SW .... This sequence is same for all 4 positions ....

now,still issues occur.....see as below....

imu_direction_issue2

now if 2 cars stay in opposite direction and both moving clockwise.....then it shows same direction sequence...( NW -> NE -> SE -> SW ) .....

In our condition....car_direction not fixed....device_direction not fixed....so this type of issue happen......

so,how can i use magnetometer data....to detect car movement with direction....

PatelKishanJ commented 7 years ago

i can get completely result from IMU to detect car movement.But it will right when IMU put at fixed position.But in our condition if many cars stay in north direction , but IMU may be attached in car with different type of position.So,if all cars moving in one direction.But it shows different direction.Because of device attached in different style in cars.

kriswiner commented 7 years ago

How do you calibrate the sensors?

On Fri, Jun 2, 2017 at 11:40 PM, jenextech notifications@github.com wrote:

i can get completely result from IMU to detect car movement.But it will right when IMU put at fixed position.But in our condition if many cars stay in north direction , but IMU may be attached in car with different type of position.So,if all cars moving in one direction.But it shows different direction.Because of device attached in different style in cars.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9150/issues/3#issuecomment-305955907, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qgg0SGjiZTy84Zz8e-fj5gljBBm5ks5sAP_hgaJpZM4CuKSq .

PatelKishanJ commented 7 years ago

i show you my code , wherever i have used your code ,i just call that function(not write definition) i have initialize imu and do configure as your code... then i have get raw data of accelerometer and check which axis is pointing to the vertically down. on basis of it,heading direction will fixed.... i have made changes in code.so you can see some are commented....

initMPU9250(); // its your function initial_compensation(); // in this function i have checking that which axis is pointing vertically down.

//see the definition of the above function void initial_compensation() { static int ini_counter,accelCount[3];

do
{
    readByte_jt(MPU9250_ADDRESS,INT_STATUS,data);

    if(data[0] & 0x01)
    {
        readAccelData_jt(accelCount);
        Bias[0] += (float)accelCount[0];
        Bias[1] += (float)accelCount[1];
        Bias[2] += (float)accelCount[2];

        ini_counter++;
    }
}while(ini_counter<10);

Bias[0] /=10;
Bias[1] /=10;
Bias[2] /=10;

/*NOTE :-
 *      Below code is useful to find that which accelero/gyro meter's axis ( X,Y or Z ) is in vertical down direction.
 *      It is necessary.Because formula for finding device location is depend on axis.So,for different vertical down direction-axis,axis in formula will be change.
 */

 mag_dir_x = (Bias[0]/16384) * 9.8;
 mag_dir_y = (Bias[1]/16384) * 9.8;
 mag_dir_z = (Bias[2]/16384) * 9.8;

// while(1) //useful to see data on the terminal... // { // // uart_transmit_string_jt("mag_dir_x = ",12); // uart_transmit_float_jt(mag_dir_x); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[0]); // uart_transmit_char_jt('\n'); // // uart_transmit_string_jt("mag_dir_y = ",12); // uart_transmit_float_jt(mag_dir_y); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[1]); // uart_transmit_char_jt('\n'); // // uart_transmit_string_jt("mag_dir_z = ",12); // uart_transmit_float_jt(mag_dir_z); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[2]); // uart_transmit_char_jt('\n'); // // }

 if( (mag_dir_x > 8) || (mag_dir_x < (-8)) )
 {
     // vertical_down_direction is  accelero/gyro meter x-axis.

     if( mag_dir_x > 8 )
        direction_section = 1;          // +ve X-axis

    else
        direction_section = 2;          // -ve X-axis
}

else if( (mag_dir_y > 8) || (mag_dir_y < (-8)) )
{
    //  vertical_down_dirextion is accelero/gyro meter y-axis.

    if( mag_dir_y > 8 )
        direction_section = 3;          // +ve Y-axis

    else
        direction_section = 4;          // -ve Y-axis
}

else if( (mag_dir_z > 8) || (mag_dir_z < (-8)) )
{
    //  vertical_down_dirextion is accelero/gyro meter z-axis.

    if( mag_dir_z > 8 )
        direction_section = 5;          // +ve Z-axis

    else
        direction_section = 6;          // -ve Z-axis
}

}

initAK8963(); // its also your function

readGyroData_jt(gyroCount); gx = (float)gyroCount[0]/(float)131;// - gyroBias[0]; // get actual gyro value, this depends on scale being set gy = (float)gyroCount[1]/(float)131;// - gyroBias[1]; gz = (float)gyroCount[2]/(float)131;// - gyroBias[2];

// if( ((gx < -2.6) || (gx > 2.6)) || ((gy < -1.2) || (gy > 1.2)) || ((gz < -3.0) || (gz > 3.0)) ) // if( ((gx < -10.0) || (gx > 10.0)) || ((gy < -10.0) || (gy > 10.0)) || ((gz < -5.0) || (gz > 5.0)) )

        if( ((gx < -5.0) || (gx > 5.0)) || ((gy < -5.0) || (gy > 5.0)) || ((gz < -5.0) || (gz > 5.0)) )
            car_moving = TRUE;
        else
            car_moving = FALSE;

        readAccelData_jt(accelCount);
        accelCount[0] -=(int) Bias[0];
        accelCount[1] -=(int) Bias[1];
        accelCount[2] -=(int) Bias[2];
         ax = (float)accelCount[0]/(float)16384;//((float)2/32768);// - accelBias[0];  // get actual g value, this depends on scale being set
         ay = (float)accelCount[1]/(float)16384;// - accelBias[1];
         az = (float)accelCount[2]/(float)16384;// - accelBias[2];
         ax *= 9.8;
         ay *= 9.8;
         az *= 9.8;

         if(ax < 0.3 && ax > -0.3)
             ax=0;
         if(ay < 0.3 && ay > -0.3)
             ay=0;
         if(az < 0.3 && az > -0.3)
             az=0;

readMagData_jt(magCount);

         // Calculate the magnetometer values in milliGauss
             // Include factory calibration per data sheet and user environmental corrections
         mx = (float)magCount[0]*(1/0.6);//*mRes*magCalibration[0] - magbias_1[0];  // get actual magnetometer value, this depends on scale being set
         my = (float)magCount[1]*(1/0.6);//*mRes*magCalibration[1] - magbias_1[1];
         mz = (float)magCount[2]*(1/0.6);//*mRes*magCalibration[2] - magbias_1[2];
         switch_to_acce_gyro_meter_jt();

// if(counter == 0) // { // switch(direction_section) // { // // case 1: side_dir = mx;//mx; // down_dir = mz;//mz; // break; // // case 2: side_dir = mx;//mz; //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different. // down_dir = -mz;//mx; //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different. // break; // // case 3: // if( ((my > 150)&&(mx<250)) && ((mz > -50)&&(mz<160)) ) // { // counter = 1; // break; // } // // else if( ((my > -250)&&(mx < -100)) && ((mz>150)&&(mz<240)) ) // { // counter = 2; // break; // } // // else if( ((my > -380)&&(mx < -300)) && ((mz > -230)&&(mz < -90)) ) // { // counter = 3; // break; // } // // else if( ((my > -140)&&(mx<170)) && ((mz > -240)&&(mz < -400)) ) // { // counter = 4; // break; // } // // case 4: // if( ((my > -430)&&(mx < -280)) && ((mz > 30)&&(mz<210)) ) // { // counter = 1; // break; // } // // else if( ((my > -110)&&(mx < 70)) && ((mz>310)&&(mz<210)) ) // { // counter = 2; // break; // } // // else if( ((my > 120)&&(mx < 200)) && ((mz > -210)&&(mz < -70)) ) // { // counter = 3; // break; // } // // else if( ((my > -330)&&(mx < -150)) && ((mz > -330)&&(mz < -200)) ) // { // counter = 4; // break; // } // // // case 5: // if( ((mx > -100)&&(mx<150)) && ((my>100)&&(my<250)) ) // { // counter = 1; // break; // } // // else if( ((mx > -230)&&(mx < -120)) && ((my > -390)&&(my < -350)) ) // { // counter = 2; // break; // } // // else if( ((mx > -400)&&(mx < -430)) && ((my > -80)&&(my<80)) ) // { // counter = 3; // break; // } // // else if( ((mx > 180)&&(mx<210)) && ((my > -220)&&(my < -140)) ) // { // counter = 4; // break; // } // // case 6: // if( ((mx > -60)&&(mx < 80)) && ((my > -380)&&(my < -290)) ) // { // counter = 1; // break; // } // // else if( ((mx > 140)&&(mx < 190)) && ((my > -100)&&(my < 60)) ) // { // counter = 2; // break; // } // // else if( ((mx > -260)&&(mx < -110)) && ((my > 180)&&(my<210)) ) // { // counter = 3; // break; // } // // else if( ((mx > -420)&&(mx < -360)) && ((my > -270)&&(my < -90)) ) // { // counter = 4; // break; // } // // default: // break; // } // }

switch(direction_section) {

        case 1: side_dir = mx;//mx;
                down_dir = mz;//mz;
                break;

        case 2: side_dir = mx;//mz;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
                down_dir = -mz;//mx;            //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
                break;

        case 3:

// if( counter == 1 ) // { // side_dir = mz; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = -my; //mx; // down_dir = mz; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mz; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = my; //mx; // down_dir = -mz; //my; // // break; // }

            side_dir = my;//mz;
            down_dir = -mz;//my;
            break;

        case 4:

// if( counter == 1 ) // { // side_dir = mz; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = my; //mx; // down_dir = mz; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mz; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = -mz; //my; // // break; // }

            side_dir = my;//my;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
            down_dir = mz;//mz;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
            break;

        case 5:

//// if( (mx>0) && (my>0) ) // if( counter == 1 ) // { // side_dir = mx; //mx; // down_dir = my; //my; // // break; // } //// //// else if( (mx<0) && (my<0) ) // else if( counter == 2 ) // { // side_dir = -mx; //mx; // down_dir = -my; //my; // // break; // } //// else if( (mx<0) && (my>0) ) // else if( counter == 3 ) // { // side_dir = my; //mx; // down_dir = -mx; //my; // // break; // } //// //// else if( (mx>0) && (my<0) ) // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = mx; //my; // // break; // }

                side_dir = mx; //mx;
                down_dir = my; //my;
                break;

        case 6:

// if( counter == 1 ) // { // side_dir = mx; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = my; //mx; // down_dir = mx; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mx; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = -mx; //my; // // break; // }

            side_dir = mx;//my;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
            down_dir = -my;//mx;            //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
            break;

        default:
                break;

    }

    /*NOTE :-
     *      here, 23.5 is a  declination angle,it is changing at every day(means it is difference for all 365 days).
     *
     *      "atan" is the function implemented by programming languages such as C++ for arctan,
     *       and returns values (in radians) in the range: -PI/2 <= atan(x) <= PI/2.
     *
     *      if you want these values in degrees, you must calculate atan(x*180/PI).
     */

    if(down_dir == 0 && side_dir < 0)
        heading_dir = 180 - 23.5;

    else if(down_dir == 0 && side_dir > 0)
        heading_dir = 360 - 23.5;

    else if(down_dir > 0)
    {
        heading_dir = 90 - (atan(side_dir/down_dir))*(180/PI) - 23.5;

        if(heading_dir < 0)
            heading_dir += 360;
    }

    else if(down_dir < 0)
    {
        heading_dir = 270 - (atan(side_dir/down_dir))*(180/PI) - 23.5;

        if(heading_dir > 360)
            heading_dir -= 360;
    }

    char data_1[3]={0};

    if(heading_dir == 0)
        data_1[0]='N';

    else if(heading_dir == 180)
        data_1[0]='S';

    else if(heading_dir > 0 && heading_dir < 90)
    {
        data_1[0]='N';
        data_1[1]='W';
    }

    else if(heading_dir > 90 && heading_dir < 180)
    {
        data_1[0]='S';
        data_1[1]='W';
    }

    else if(heading_dir > 180 && heading_dir < 270)
    {
        data_1[0]='S';
        data_1[1]='E';
    }

    else if(heading_dir > 270 && heading_dir < 360)
    {
        data_1[0]='N';
        data_1[1]='E';
    }

    else
        ;

    heading_dir = 360 - heading_dir;
    find_position_jt();
    dx = (float)distance*cos(heading_dir);
    dy = (float)distance*sin(heading_dir);
    delta_longi = (float)dx/(111320 * cos(LAT));
    delta_lat = (float)dy / 110540;
    F_longi = LONGI +(float)delta_longi;
    F_lat = LAT +(float) delta_lat;

// if( car_moving == TRUE ) { sprintf(data_sensor1,"Heading Direction= %f %s\n",heading_dir, data_1); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); sprintf(data_sensor1,"vx = %f vy = %f vz = %f\n",vx,vy,vz); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); sprintf(data_sensor1,"px = %f py = %f pz = %f\nTime = %fsecs\n distance = %f \n lat = %f long = %f",px,py,pz,t, distance,F_lat,F_longi); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); uart_transmit_string_jt("\n\n",2); } // else // uart_transmit_string_jt("CAR IS STATIONARY\n",18);

kriswiner commented 7 years ago

I don;t see where you are calibrating the sensors.

On Sun, Jun 4, 2017 at 10:11 PM, jenextech notifications@github.com wrote:

i show you my code , wherever i have used your code ,i just call that function(not write definition) i have initialize imu and do configure as your code... then i have get raw data of accelerometer and check which axis is pointing to the vertically down. on basis of it,heading direction will fixed.... i have made changes in code.so you can see some are commented....

initMPU9250(); // its your function initial_compensation(); // in this function i have checking that which axis is pointing vertically down.

//see the definition of the above function void initial_compensation() { static int ini_counter,accelCount[3];

do { readByte_jt(MPU9250_ADDRESS,INT_STATUS,data);

if(data[0] & 0x01) { readAccelData_jt(accelCount); Bias[0] += (float)accelCount[0]; Bias[1] += (float)accelCount[1]; Bias[2] += (float)accelCount[2];

  ini_counter++;

} }while(ini_counter<10);

Bias[0] /=10; Bias[1] /=10; Bias[2] /=10;

/*NOTE :-

  • Below code is useful to find that which accelero/gyro meter's axis ( X,Y or Z ) is in vertical down direction.
  • It is necessary.Because formula for finding device location is depend on axis.So,for different vertical down direction-axis,axis in formula will be change. */

    mag_dir_x = (Bias[0]/16384) 9.8; mag_dir_y = (Bias[1]/16384) 9.8; mag_dir_z = (Bias[2]/16384) * 9.8;

// while(1) //useful to see data on the terminal... // { // // uart_transmit_string_jt("mag_dir_x = ",12); // uart_transmit_float_jt(mag_dir_x); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[0]); // uart_transmit_char_jt('\n'); // // uart_transmit_string_jt("mag_dir_y = ",12); // uart_transmit_float_jt(mag_dir_y); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[1]); // uart_transmit_char_jt('\n'); // // uart_transmit_string_jt("mag_dir_z = ",12); // uart_transmit_float_jt(mag_dir_z); // uart_transmit_char_jt(' '); // uart_transmit_float_jt(Bias[2]); // uart_transmit_char_jt('\n'); // // }

if( (mag_dir_x > 8) || (mag_dir_x < (-8)) ) { // vertical_down_direction is accelero/gyro meter x-axis.

if( mag_dir_x > 8 ) direction_section = 1; // +ve X-axis

else direction_section = 2; // -ve X-axis }

else if( (mag_dir_y > 8) || (mag_dir_y < (-8)) ) { // vertical_down_dirextion is accelero/gyro meter y-axis.

if( mag_dir_y > 8 ) direction_section = 3; // +ve Y-axis

else direction_section = 4; // -ve Y-axis }

else if( (mag_dir_z > 8) || (mag_dir_z < (-8)) ) { // vertical_down_dirextion is accelero/gyro meter z-axis.

if( mag_dir_z > 8 ) direction_section = 5; // +ve Z-axis

else direction_section = 6; // -ve Z-axis }

}

initAK8963(); // its also your function

readGyroData_jt(gyroCount); gx = (float)gyroCount[0]/(float)131;// - gyroBias[0]; // get actual gyro value, this depends on scale being set gy = (float)gyroCount[1]/(float)131;// - gyroBias[1]; gz = (float)gyroCount[2]/(float)131;// - gyroBias[2];

// if( ((gx < -2.6) || (gx > 2.6)) || ((gy < -1.2) || (gy > 1.2)) || ((gz < -3.0) || (gz > 3.0)) ) // if( ((gx < -10.0) || (gx > 10.0)) || ((gy < -10.0) || (gy > 10.0)) || ((gz < -5.0) || (gz > 5.0)) )

  if( ((gx < -5.0) || (gx > 5.0)) || ((gy < -5.0) || (gy > 5.0)) || ((gz < -5.0) || (gz > 5.0)) )
      car_moving = TRUE;
  else
      car_moving = FALSE;

  readAccelData_jt(accelCount);
  accelCount[0] -=(int) Bias[0];
  accelCount[1] -=(int) Bias[1];
  accelCount[2] -=(int) Bias[2];
   ax = (float)accelCount[0]/(float)16384;//((float)2/32768);// - accelBias[0];  // get actual g value, this depends on scale being set
   ay = (float)accelCount[1]/(float)16384;// - accelBias[1];
   az = (float)accelCount[2]/(float)16384;// - accelBias[2];
   ax *= 9.8;
   ay *= 9.8;
   az *= 9.8;

   if(ax < 0.3 && ax > -0.3)
       ax=0;
   if(ay < 0.3 && ay > -0.3)
       ay=0;
   if(az < 0.3 && az > -0.3)
       az=0;

readMagData_jt(magCount);

   // Calculate the magnetometer values in milliGauss
       // Include factory calibration per data sheet and user environmental corrections
   mx = (float)magCount[0]*(1/0.6);//*mRes*magCalibration[0] - magbias_1[0];  // get actual magnetometer value, this depends on scale being set
   my = (float)magCount[1]*(1/0.6);//*mRes*magCalibration[1] - magbias_1[1];
   mz = (float)magCount[2]*(1/0.6);//*mRes*magCalibration[2] - magbias_1[2];
   switch_to_acce_gyro_meter_jt();

// if(counter == 0) // { // switch(direction_section) // { // // case 1: side_dir = mx;//mx; // down_dir = mz;//mz; // break; // // case 2: side_dir = mx;//mz; //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different. // down_dir = -mz;//mx; //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different. // break; // // case 3: // if( ((my > 150)&&(mx<250)) && ((mz > -50)&&(mz<160)) ) // { // counter = 1; // break; // } // // else if( ((my > -250)&&(mx < -100)) && ((mz>150)&&(mz<240)) ) // { // counter = 2; // break; // } // // else if( ((my > -380)&&(mx < -300)) && ((mz > -230)&&(mz < -90)) ) // { // counter = 3; // break; // } // // else if( ((my > -140)&&(mx<170)) && ((mz > -240)&&(mz < -400)) ) // { // counter = 4; // break; // } // // case 4: // if( ((my > -430)&&(mx < -280)) && ((mz > 30)&&(mz<210)) ) // { // counter = 1; // break; // } // // else if( ((my > -110)&&(mx < 70)) && ((mz>310)&&(mz<210)) ) // { // counter = 2; // break; // } // // else if( ((my > 120)&&(mx < 200)) && ((mz > -210)&&(mz < -70)) ) // { // counter = 3; // break; // } // // else if( ((my > -330)&&(mx < -150)) && ((mz > -330)&&(mz < -200)) ) // { // counter = 4; // break; // } // // // case 5: // if( ((mx > -100)&&(mx<150)) && ((my>100)&&(my<250)) ) // { // counter = 1; // break; // } // // else if( ((mx > -230)&&(mx < -120)) && ((my > -390)&&(my < -350)) ) // { // counter = 2; // break; // } // // else if( ((mx > -400)&&(mx < -430)) && ((my > -80)&&(my<80)) ) // { // counter = 3; // break; // } // // else if( ((mx > 180)&&(mx<210)) && ((my > -220)&&(my < -140)) ) // { // counter = 4; // break; // } // // case 6: // if( ((mx > -60)&&(mx < 80)) && ((my > -380)&&(my < -290)) ) // { // counter = 1; // break; // } // // else if( ((mx > 140)&&(mx < 190)) && ((my > -100)&&(my < 60)) ) // { // counter = 2; // break; // } // // else if( ((mx > -260)&&(mx < -110)) && ((my > 180)&&(my<210)) ) // { // counter = 3; // break; // } // // else if( ((mx > -420)&&(mx < -360)) && ((my > -270)&&(my < -90)) ) // { // counter = 4; // break; // } // // default: // break; // } // }

switch(direction_section) {

  case 1: side_dir = mx;//mx;
          down_dir = mz;//mz;
          break;

  case 2: side_dir = mx;//mz;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
          down_dir = -mz;//mx;            //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
          break;

  case 3:

// if( counter == 1 ) // { // side_dir = mz; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = -my; //mx; // down_dir = mz; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mz; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = my; //mx; // down_dir = -mz; //my; // // break; // }

      side_dir = my;//mz;
      down_dir = -mz;//my;
      break;

  case 4:

// if( counter == 1 ) // { // side_dir = mz; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = my; //mx; // down_dir = mz; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mz; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = -mz; //my; // // break; // }

      side_dir = my;//my;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
      down_dir = mz;//mz;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
      break;

  case 5:

//// if( (mx>0) && (my>0) ) // if( counter == 1 ) // { // side_dir = mx; //mx; // down_dir = my; //my; // // break; // } //// //// else if( (mx<0) && (my<0) ) // else if( counter == 2 ) // { // side_dir = -mx; //mx; // down_dir = -my; //my; // // break; // } //// else if( (mx<0) && (my>0) ) // else if( counter == 3 ) // { // side_dir = my; //mx; // down_dir = -mx; //my; // // break; // } //// //// else if( (mx>0) && (my<0) ) // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = mx; //my; // // break; // }

          side_dir = mx; //mx;
          down_dir = my; //my;
          break;

  case 6:

// if( counter == 1 ) // { // side_dir = mx; //mx; // down_dir = -my; //my; // // break; // } // // else if( counter == 2 ) // { // side_dir = my; //mx; // down_dir = mx; //my; // // break; // } // // else if( counter == 3 ) // { // side_dir = -mx; //mx; // down_dir = my; //my; // // break; // } // // else if( counter == 4 ) // { // side_dir = -my; //mx; // down_dir = -mx; //my; // // break; // }

      side_dir = mx;//my;         //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
      down_dir = -my;//mx;            //if here changing sign(-ve),nissan_car/swift_car detect same in direction,but angle may be different.
      break;

  default:
          break;

}

/*NOTE :-

  • here, 23.5 is a declination angle,it is changing at every day(means it is difference for all 365 days).
  • "atan" is the function implemented by programming languages such as C++ for arctan,
  • and returns values (in radians) in the range: -PI/2 <= atan(x) <= PI/2.
  • if you want these values in degrees, you must calculate atan(x180/PI). /

    if(down_dir == 0 && side_dir < 0) heading_dir = 180 - 23.5;

    else if(down_dir == 0 && side_dir > 0) heading_dir = 360 - 23.5;

    else if(down_dir > 0) { heading_dir = 90 - (atan(side_dir/down_dir))*(180/PI) - 23.5;

    if(heading_dir < 0) heading_dir += 360; }

    else if(down_dir < 0) { heading_dir = 270 - (atan(side_dir/down_dir))*(180/PI) - 23.5;

    if(heading_dir > 360) heading_dir -= 360; }

    char data_1[3]={0};

    if(heading_dir == 0) data_1[0]='N';

    else if(heading_dir == 180) data_1[0]='S';

    else if(heading_dir > 0 && heading_dir < 90) { data_1[0]='N'; data_1[1]='W'; }

    else if(heading_dir > 90 && heading_dir < 180) { data_1[0]='S'; data_1[1]='W'; }

    else if(heading_dir > 180 && heading_dir < 270) { data_1[0]='S'; data_1[1]='E'; }

    else if(heading_dir > 270 && heading_dir < 360) { data_1[0]='N'; data_1[1]='E'; }

    else ;

    heading_dir = 360 - heading_dir; find_position_jt(); dx = (float)distancecos(heading_dir); dy = (float)distancesin(heading_dir); delta_longi = (float)dx/(111320 * cos(LAT)); delta_lat = (float)dy / 110540; F_longi = LONGI +(float)delta_longi; F_lat = LAT +(float) delta_lat;

// if( car_moving == TRUE ) { sprintf(data_sensor1,"Heading Direction= %f %s\n",heading_dir, data_1); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); sprintf(data_sensor1,"vx = %f vy = %f vz = %f\n",vx,vy,vz); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); sprintf(data_sensor1,"px = %f py = %f pz = %f\nTime = %fsecs\n distance = %f \n lat = %f long = %f",px,py,pz,t, distance,F_lat,F_longi); uart_transmit_string_jt(data_sensor1,strlen(data_sensor1)); uart_transmit_string_jt("\n\n",2); } // else // uart_transmit_string_jt("CAR IS STATIONARY\n",18);

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

PatelKishanJ commented 7 years ago

for gyrometer....

readGyroData_jt(gyroCount); gx = (float)gyroCount[0]/(float)131;// - gyroBias[0]; // get actual gyro value, this depends on scale being set gy = (float)gyroCount[1]/(float)131;// - gyroBias[1]; gz = (float)gyroCount[2]/(float)131;// - gyroBias[2];

// if( ((gx < -2.6) || (gx > 2.6)) || ((gy < -1.2) || (gy > 1.2)) || ((gz < -3.0) || (gz > 3.0)) ) // if( ((gx < -10.0) || (gx > 10.0)) || ((gy < -10.0) || (gy > 10.0)) || ((gz < -5.0) || (gz > 5.0)) )

        if( ((gx < -5.0) || (gx > 5.0)) || ((gy < -5.0) || (gy > 5.0)) || ((gz < -5.0) || (gz > 5.0)) )
            car_moving = TRUE;
        else
            car_moving = FALSE;

for accelerometer....

        readAccelData_jt(accelCount);
        accelCount[0] -=(int) Bias[0];
        accelCount[1] -=(int) Bias[1];
        accelCount[2] -=(int) Bias[2];
         ax = (float)accelCount[0]/(float)16384;//((float)2/32768);// - accelBias[0];  // get actual g value, this depends on scale being set
         ay = (float)accelCount[1]/(float)16384;// - accelBias[1];
         az = (float)accelCount[2]/(float)16384;// - accelBias[2];
         ax *= 9.8;
         ay *= 9.8;
         az *= 9.8;

if(ax < 0.3 && ax > -0.3) ax=0; if(ay < 0.3 && ay > -0.3) ay=0; if(az < 0.3 && az > -0.3) az=0;

is it?....

kriswiner commented 7 years ago

And where do gyroBias and accelBias come from?

And magnetometer calibration?

On Sun, Jun 4, 2017 at 11:19 PM, jenextech notifications@github.com wrote:

for gyrometer....

readGyroData_jt(gyroCount); gx = (float)gyroCount[0]/(float)131;// - gyroBias[0]; // get actual gyro value, this depends on scale being set gy = (float)gyroCount[1]/(float)131;// - gyroBias[1]; gz = (float)gyroCount[2]/(float)131;// - gyroBias[2];

// if( ((gx < -2.6) || (gx > 2.6)) || ((gy < -1.2) || (gy > 1.2)) || ((gz < -3.0) || (gz > 3.0)) ) // if( ((gx < -10.0) || (gx > 10.0)) || ((gy < -10.0) || (gy > 10.0)) || ((gz < -5.0) || (gz > 5.0)) )

  if( ((gx < -5.0) || (gx > 5.0)) || ((gy < -5.0) || (gy > 5.0)) || ((gz < -5.0) || (gz > 5.0)) )
      car_moving = TRUE;
  else
      car_moving = FALSE;

for accelerometer....

  readAccelData_jt(accelCount);
  accelCount[0] -=(int) Bias[0];
  accelCount[1] -=(int) Bias[1];
  accelCount[2] -=(int) Bias[2];
   ax = (float)accelCount[0]/(float)16384;//((float)2/32768);// - accelBias[0];  // get actual g value, this depends on scale being set
   ay = (float)accelCount[1]/(float)16384;// - accelBias[1];
   az = (float)accelCount[2]/(float)16384;// - accelBias[2];
   ax *= 9.8;
   ay *= 9.8;
   az *= 9.8;

if(ax < 0.3 && ax > -0.3) ax=0; if(ay < 0.3 && ay > -0.3) ay=0; if(az < 0.3 && az > -0.3) az=0;

is it?....

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9150/issues/3#issuecomment-306112429, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qh0bAGBIZ18pxlu1ZT-_ZDo2w-0Bks5sA54MgaJpZM4CuKSq .

PatelKishanJ commented 7 years ago

do { readByte_jt(MPU9250_ADDRESS,INT_STATUS,data);

if(data[0] & 0x01)
{
    readAccelData_jt(accelCount);
    Bias[0] += (float)accelCount[0];
    Bias[1] += (float)accelCount[1];
    Bias[2] += (float)accelCount[2];

    ini_counter++;
}

}while(ini_counter<10);

Bias[0] /=10; Bias[1] /=10; Bias[2] /=10;

Gubbifisken commented 6 years ago

Hello Kris

Thanks for the great work with your lib. I could really use your input.

I have read so many posts, browsed through different examples, tried different things, Madgwick/Mahony updates, +mz, -mz, different calibration methods etc. but nothing yields a usable result for my purpose.

Goal and setup: I am using

I want to use the MPU9250 and compensation to get a north heading, so the I can get a north heading compared to the orientation of the MPU9250. Which axis to use is not important, since I can mount the MPU9250 however I like for my project.

I would really appreciate a complete code example of how to set up, how to calibrate and how to use orientation compensation (when MPU9250 is rotated around x, y, z) to get heading to north (0-360 or -180-180). Please do not just link to other github libs, since I have already tried thess, and tried to implement calibration, magBias etc. and nothing yields anything usable. I have the code up and running, and reading etc. So not a I2C ussue or wiring usse. But yaw makes no sense and is not the same when rorating back to same position over and over again.

Hope to get some input, so I can get my gadget geocache out in the field, for many geocacher to enjoy!

Thanks in advance to anybody giving input Gubbifisken

kriswiner commented 6 years ago

Some comments:

I will assume your code is correct and that your are properly calibrating your sensors.

1) the purple CJMU boards from China are absolute crap and I would never use them; the circuit design is wrong.

2) you need to run the accel and especially gyro at 1 kHz to get best results

3) you need to be able to run the fusion algorithm at 10 x or so the sample rate, so a 16 MHz AVR is not going to cut it. Try a Cortex M4F like this https://www.tindie.com/products/TleraCorp/ladybug-stm32l432-development-board/ one.

4) You want a complete code example but you don't want me to link to a github repository??? This https://github.com/kriswiner/Ladybug/blob/master/MPU9250_MS5637_BasicAHRS2_Ladybug.ino code example is complete and gives very good results for me using the MCU I linked to.

I suspect your basic problem (apart from the crap MPU9250) is your MCU is too pokey. If you want to use a pokey AVR MCU look into this https://www.tindie.com/products/onehorse/ultimate-sensor-fusion-solution/. It works with the pokiest MCUs.

On Sat, Jun 9, 2018 at 6:12 AM, Gubbifisken notifications@github.com wrote:

Hello Kris

Thanks for the great work with your lib. I could really use your input.

I have read so many posts, browsed through different examples, tried different things, Madgwick/Mahony updates, +mz, -mz, different calibration methods etc. but nothing yields a usable result for my purpose.

Goal and setup: I am using

I want to use the MPU9250 and compensation to get a north heading, so the I can get a north heading compared to the orientation of the MPU9250. Which axis to use is not important, since I can mount the MPU9250 however I like for my project.

I would really appreciate a complete code example of how to set up, how to calibrate and how to use orientation compensation (when MPU9250 is rotated around x, y, z) to get heading to north (0-360 or -180-180). Please do not just link to other github libs, since I have already tried thess, and tried to implement calibration, magBias etc. and nothing yields anything usable. I have the code up and running, and reading etc. So not a I2C ussue or wiring usse. But yaw makes no sense and is not the same when rorating back to same position over and over again.

Hope to get some input, so I can get my gadget geocache out in the field, for many geocacher to enjoy!

Thanks in advance to anybody giving input Gibbifisken

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

Gubbifisken commented 6 years ago

Hello Kris Thansk for the super quick reply. What I meant with not github link was that the ones I already have have inconsistencies between them (complete repo but also comments online). An example is that many write about calibration. Hence I wonder why the calibration function (min, maxand avg bias) is not just a part of the libs I have found, and then commeted out (with a comment that one needs to use for finfing specific HW bias for their setup).

I will look into the links you send, and look at upgrading MCU to F4.

I wonder why the Chinese products are that bad. I have a 6050 that works great for my gyro project. I also fly quadcopter with parts from China, and they works well. And here we are talking about a quad spinning with 1200 degrees/s very smooth.

Do you have a suggestion where to get whatever MPU in EU that it workth buying. I need one that can farely give me north heading (making kind of digital compass). A few degrees of is fine and not a problem

Gubbifisken

kriswiner commented 6 years ago

I'd start with the upgrade to your MCU.

On Sat, Jun 9, 2018 at 10:49 AM, Gubbifisken notifications@github.com wrote:

Hello Kris Thansk for the super quick reply. What I meant with not github link was that the ones I already have have inconsistencies between them (complete repo but also comments online). An example is that many write about calibration. Hence I wonder why the calibration function (min, maxand avg bias) is not just a part of the libs I have found, and then commeted out (with a comment that one needs to use for finfing specific HW bias for their setup).

I will look into the links you send, and look at upgrading MCU to F4.

I wonder why the Chinese products are that bad. I have a 6050 that works great for my gyro project. I also fly quadcopter with parts from China, and they works well. And here we are talking about a quad spinning with 1200 degrees/s very smooth.

Do you have a suggestion where to get whatever MPU in EU that it workth buying. I need one that can farely give me north heading (making kind of digital compass). A few degrees of is fine and not a problem

Gubbifisken

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

JabberwockPL commented 6 years ago

Hello,

I seem to have the same issue...

I have been running the calibration routine that was posted above, but I get rather inconsistent results from it and, when the values are pasted into the code, I still get nonsensical yaw results.

kriswiner commented 6 years ago

You are using an MPU9150?

Do you have the sensor values arranged as NED when input into the fusion filter?

On Thu, Sep 6, 2018 at 5:37 AM JabberwockPL notifications@github.com wrote:

Hello,

I seem to have the same issue...

I have been running the calibration routine that was posted above, but I get rather inconsistent results from it and, when the values are pasted into the code, I still get nonsensical yaw results.

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

JabberwockPL commented 6 years ago

Yes, I am using MPU9150.

I am not sure what you mean by NED - I am running the calibration procedure you have given above and am plugging the results (dest[0] to [3]) to magbias[0] to [3], as that is what the original MPU9250 program seems to be doing. The values I have obtained were -42; 79; 35; although they vary from measurement to measurement.

kriswiner commented 6 years ago

Are you calculating quaternions?

On Thu, Sep 6, 2018 at 10:45 AM JabberwockPL notifications@github.com wrote:

Yes, I am using MPU9150.

I am not sure what you mean by NED - I am running the calibration procedure you have given above and am plugging the results (dest[0] to [3]) to magbias[0] to [3], as that is what the original MPU9250 program seems to be doing. The values I have obtained were -42; 79; 35; although they vary from measurement to measurement.

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

JabberwockPL commented 6 years ago

For now I am just testing your code and the only changes I have made are removing the display references, changing the declination data and putting the magbias values manually.

I have run the calibration again and when using the new values it works much better. It is still rather inaccurate for yaw (turning the module about 90 degrees goes from 0 to 160), but I guess additional calibration will help with that.

kriswiner commented 6 years ago

Don't assume sketches in this repository are correct, or appropriate for your application.

" I am not sure what you mean by NED"

This means you choose which edge of your board is going to be North. Then find out which axxel axis point North, then East, and then down. Same for gyro and mag. The provide filter the sensor data in the following order: An, Ae, Ad, Gn, Ge, Gd, Mn, Me, Md) Otherwise you will get nonsense.

On Fri, Sep 7, 2018 at 12:43 AM JabberwockPL notifications@github.com wrote:

For now I am just testing your code and the only changes I have made are removing the display references, changing the declination data and putting the magbias values manually.

I have run the calibration again and when using the new values it works much better. It is still rather inaccurate for yaw (turning the module about 90 degrees goes from 0 to 160), but I guess additional calibration will help with that.

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

dsstewart commented 5 years ago

Hi Kris,

I've seen you mention several times that you should to run the fusion algorithm much more frequently than the sample rate. Can you explain why this is the case? I've been trying to figure out why that is, but so far havn't come up with anything.

kriswiner commented 5 years ago

Madgwick and Mahony algorithms are similar to steepest descent methods and require iteration to asymptote to an accurate solution, just that simple....

On Fri, Nov 2, 2018 at 2:04 PM dsstewart notifications@github.com wrote:

Hi Kris,

I've seen you mention several times that you should to run the fusion algorithm much more frequently than the sample rate. Can you explain why this is the case? I've been trying to figure out why that is, but so far havn't come up with anything.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/kriswiner/MPU9150/issues/3#issuecomment-435505469, or mute the thread https://github.com/notifications/unsubscribe-auth/AGY1qv73-8qxFdIZ5vQosS8MFyfQgrBYks5urLN6gaJpZM4CuKSq .