Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing ability to calibrate gyroscope & accelerometer #2

Open
PaulStoffregen opened this issue Apr 3, 2016 · 17 comments
Open

Missing ability to calibrate gyroscope & accelerometer #2

PaulStoffregen opened this issue Apr 3, 2016 · 17 comments

Comments

@PaulStoffregen
Copy link
Owner

No description provided.

@battosai30
Copy link

Hi,

No update about this point ? Is there any other method to easily calibrate acc and gyro ?

@PaulStoffregen
Copy link
Owner Author

Sorry, can't work on this right now. All my dev cycles are going into a USB Host library at the moment.

@battosai30
Copy link

battosai30 commented Mar 3, 2017

And I'm sure that will be a killing :)

I made a little patch. It's not well written at all be it does the job ...

So, in NXPmotionSense.h add this to public function :

	void setAccelCal(float calA[3]) {
	
	cal[0]=calA[0];
	cal[1]=calA[1];
	cal[2]=calA[2];
	
	}
	
	void setGyroCal(float calG[3]) {
	
	cal[3]=calG[0];
	cal[4]=calG[1];
	cal[5]=calG[2];
	
	}

And in your just declare arrays to store calibration datas :

float calGyro[3] = {-2,-0.7,-0.6};
float calAccel[3] = {0,0,0};

And use setGyroCal() and setAccelCal() AFTER begin() :

  imu.begin();
  imu.setAccelCal(calAccel);
  imu.setGyroCal(calGyro);

Note :

  • as you can see my trick doesn't not store calibration datas in EEPROM.
  • to calibraty gyro, just make a simple code to get a shifting mean value. It's very important to calibrate gyroscope or you will see your sensor rotate all the time ...

@kswain1
Copy link

kswain1 commented May 6, 2017

@battosai30 did you have to change the way the app reads information as well?

@battosai30
Copy link

Not at all. I made an inclinometer on IP (with PropShield + W5200 shield) and I just need to directly correct accel and gyro offsets

@kswain1
Copy link

kswain1 commented May 7, 2017 via email

@kswain1
Copy link

kswain1 commented May 8, 2017

@battosai30 Does this work with the motion cal tool. To display the offsets afterwards. I am confused where can I get the calibration data from? Does it print out serially after using calibrating sensor program?

@battosai30
Copy link

Yes you just have to use the raw example which print out value of each sensor. For gyro, just let it on your table with no movements and note values, the're offsets. It's useful to modify the code to output a mean value. For accel I think I did nothing, accel offsets are not as important as gyro's.

@TrevorPT
Copy link

@battosai30 - Thanks for that! I was just looking at calibration.

Question: once I get the running average gyro values (eg. -9, 5, 2) are these the offset values or do I have to negate them (eg. 9, -5, -2) ?

@battosai30
Copy link

battosai30 commented May 12, 2017

You should get the offset value, as in library we find :

                ax = (float)accel_mag_raw[0] * G_PER_COUNT - cal[0];
		ay = (float)accel_mag_raw[1] * G_PER_COUNT - cal[1];
		az = (float)accel_mag_raw[2] * G_PER_COUNT - cal[2];
		gx = (float)gyro_raw[0] * DEG_PER_SEC_PER_COUNT - cal[3];
		gy = (float)gyro_raw[1] * DEG_PER_SEC_PER_COUNT - cal[4];
		gz = (float)gyro_raw[2] * DEG_PER_SEC_PER_COUNT - cal[5];

@TrevorPT
Copy link

Ah, so obvious. Thanks for the tip, much appreciated!

@TrevorPT
Copy link

I would've thought the offsets would be raw values but from that code I see they must be in g and deg/s respectively, so should be * G_PER_COUNT and * DEG_PER_SEC_PER_COUNT. Unless I'm missing something.

@battosai30
Copy link

If you use readMotionSensor() values are already converted :

	void readMotionSensor(float& ax, float& ay, float& az, float& gx, float& gy, float& gz) {
		if (!newdata) update();
		newdata = 0;
		ax = (float)accel_mag_raw[0] * G_PER_COUNT;
		ay = (float)accel_mag_raw[1] * G_PER_COUNT;
		az = (float)accel_mag_raw[2] * G_PER_COUNT;
		gx = (float)gyro_raw[0] * DEG_PER_SEC_PER_COUNT;
		gy = (float)gyro_raw[1] * DEG_PER_SEC_PER_COUNT;
		gz = (float)gyro_raw[2] * DEG_PER_SEC_PER_COUNT;
	}

@TrevorPT
Copy link

Ah, okay. I was using

void readMotionSensor(int& ax, int& ay, int& az, int& gx, int& gy, int& gz, int& mx, int& my, int& mz)

so was getting raw values like {-9, 5, 2}. To apply them to cal[3]..cal[5] I'd then have to convert them to deg/s. So to expand your code from above I did:

void setGyroCal(float calG[3]) {
	cal[3]=calG[0] * DEG_PER_SEC_PER_COUNT;
	cal[4]=calG[1] * DEG_PER_SEC_PER_COUNT;
	cal[5]=calG[2] * DEG_PER_SEC_PER_COUNT;
}

I see now how I could just use the readMotionSensor(float& ax,... version and obtain converted values. Subtle difference to be aware of when writing the cal routine!

@TrevorPT
Copy link

For reference, here's how I wrote the cal offsets to EEPROM. I could've refined it to write only the gyro offsets but this worked for my purposes. The mag calibration must be run first as it clears both the gyro and accel offsets. I also added clearCal().

class NXPMotionSense {
public:
    ...
    bool writeCal();
    void clearCal() {
        // from NXPMotionSense::begin()
        memset(cal, 0, sizeof(cal));
        cal[9] = 50.0f;
    }
    ...
}
bool NXPMotionSense::writeCal()
{
    uint8_t data[NXP_MOTION_CAL_SIZE];
    // First two bytes are 117,84
    data[0] = 117;
    data[1] = 84;
    // Copy the cal data
    memcpy(data+2, cal, sizeof(cal));

    // Calculate the crc value that will be stored in the last 2 bytes
    uint16_t crc;
    uint8_t i;

    crc = 0xFFFF;
    // Count all values up to but excluding the last 2 bytes
    for (i=0; i<NXP_MOTION_CAL_SIZE-2; i++) {
        crc = _crc16_update(crc, data[i]);
    }

    // Save the crc value in the last 2 bytes
    memcpy(&data[i], &crc, 2);

    return writeCalibration(data);
}

@drf5n
Copy link

drf5n commented Apr 27, 2023

Looks like the gui display update in MotionCal is at these TODOs:

MotionCal/gui.cpp

Lines 300 to 306 in c24740c

for (i=0; i < 3; i++) {
snprintf(buf, sizeof(buf), "%.3f", 0.0f); // TODO...
m_accel[i]->SetLabelText(buf);
}
for (i=0; i < 3; i++) {
snprintf(buf, sizeof(buf), "%.3f", 0.0f); // TODO...
m_gyro[i]->SetLabelText(buf);

@flyboyhunt
Copy link

has anyone found a fix for this? still unable to get the accelerometer and Gyroscope data to print in MotionCal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants