PaulStoffregen / MotionCal

Motion Sensor Calibration Tool
http://www.pjrc.com/store/prop_shield.html
74 stars 55 forks source link

Missing ability to calibrate gyroscope & accelerometer #2

Open PaulStoffregen opened 8 years ago

battosai30 commented 7 years ago

Hi,

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

PaulStoffregen commented 7 years ago

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

battosai30 commented 7 years ago

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 :

kswain1 commented 7 years ago

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

battosai30 commented 7 years ago

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 commented 7 years ago

How did you dierectly connect this offsets I don't understand? On Sun, May 7, 2017 at 4:11 AM battosai30 notifications@github.com wrote:

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

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/PaulStoffregen/MotionCal/issues/2#issuecomment-299692160, or mute the thread https://github.com/notifications/unsubscribe-auth/AItw9JFcis-bMMBg8Yxil2BWSbqGafEYks5r3YqngaJpZM4H-qft .

kswain1 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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

TrevorPT commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 1 year ago

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

https://github.com/PaulStoffregen/MotionCal/blob/c24740cd8f8a2ccd5f8aa06be8965ff52b7ee920/gui.cpp#L300-L306