Welcome to IMU Section

Using IMU to get the pitch, roll and yaw!

Start scrolling!

Objective

The purpose of this lab is to add the IMU to your robot, start running the Artemis+sensors from a battery, and record a stunt on your RC robot.

  • Get data from the accelerat0r and gyroscope.
  • Calculate corresponding pitch, roll and yaw.
  • Apply Low-Pass Filter to reduce high-frequency noise.
  • Apply compensation filter to get more accurate data.

Task 1

Setup the IMU

We used the code below to calculate pitch, roll and yaw using data from IMU.

                        
    myICM.getAGMT();         // The values are only updated when you call 'getAGMT'
    //    printRawAGMT( myICM.agmt );     // Uncomment this to see the raw values, taken directly from the agmt structure
    //printScaledAGMT(&myICM); // This function takes into account the scale settings from when the measurement was made to calculate the values with units
    //delay(30);

    //calculate the pitch and roll
    //yaw_g = yaw_g + myICM.gyrZ()*dt;


    //delay(10); //ms
    dt = (millis()-last_time)/100000.;
    // Serial.println(millis());
    // Serial.println(last_time);
    last_time = millis();

    pitch_a = atan2(myICM.accY(),myICM.accZ())*180/M_PI;
    pitch_g = pitch_g + myICM.gyrX()*dt;
    pitch = (pitch+myICM.gyrX()*dt)*0.9 + pitch_a*0.1;

    roll_a  = atan2(myICM.accX(),myICM.accZ())*180/M_PI; 
    roll_g = roll_g + myICM.gyrY()*dt; 
    roll = (roll+myICM.gyrY()*dt)*0.9 + roll_a*0.1;

    Xm = myICM.magX();
    Ym = myICM.magY();
    Zm = myICM.magZ();
    x = Ym*cos(roll*M_PI/180) - Zm*sin(roll*M_PI/180);
    y = Xm*cos(pitch*M_PI/180) + Ym*sin(roll*M_PI/180)*sin(pitch*M_PI/180) + Zm*cos(roll*M_PI/180)*sin(pitch*M_PI/180);
    yaw = atan2(y,x)*180/M_PI;
                        
                        

Task 2

Show the output at {-90, 0, 90} degrees pitch and roll. Hint: You can use the surface and edges of your table as guides to ensure 90 degree tilt/roll.

As demonstrated in the figure below, when we make the IMU flat on the table the pitch and roll parameters are all close to zero.

Description of the image

When we turned the IMU along the y-axis for 90 degrees, the pitch data has increased to around 8.6 and the roll data still closed to 0.

Description of the image

Conversely, if we turned the IMU around the y-axis for negative 90 degrees (shown in the figure below), the pitch parameter turned to around -8.6 with roll still close to 0.

Description of the image

Same for the roll, when we turned the IMU along x-axis for 90 degrees, the roll parameter became close to 8.6 and the pitch kept closed to 0.

Description of the image

And the roll data are around -8.6 after we turned the IMU along the inverse direction.

Description of the image

Task 3

The accelerometer is noisy, especially when you run the RC car in its proximity. Record some of this data, and analyze the noise in the frequency spectrum.

The figure below shows the IMU signal in the time domain (upper) and the frequency domain (lower) when we hit the table to make some noise. from the frequency domain, it is noticeable that there are some fluctuations in the part above 50 Hz, which is not the signal frequency that can be generated by operation on the IMU. (Suppose you turn the IMU 50 times per second, that is crazy!)

Description of the image

To reduce the noise signal which has a high frequency, we designed a Low-Pass Filter. This filter can block the high-frequency noise to make the signal more accurate and easier to use in the future steps.

Description of the image

The results after adding the LPF is shown above, which is noticeable that there is little fluctuations in the high-frequency region, most of the signal is in the region from 0Hz to 50Hz, which is what we want from this IMU.

Task 4

Compare your output to the pitch, roll, and yaw values from the accelerometer and the filtered response. Describe how they differ.

As shown in the figure below, in the serial output, the first column is the pitch value calculated from the accelerator and the second column is the pitch value calculaed from the gyroscope value. It is obvious that the accelerator value is larger than the gyroscope value.

Description of the image

Also for the roll value, the data from the accelerator is larger than that from the gyroscope.

Description of the image

Task 5

Try adjusting the sampling frequency to see how it changes the accuracy of your estimated angles.

Here we added a 10ms delay for each purch and roll value. From the figure below we could notice that the data is becoming more inaccurate because the value of pitch and roll fluctuate a lot even when we do not move the IMU.

Description of the image

Task 6

Use a complimentary filter to compute an estimate of pitch and roll which is both accurate and stable. Demonstrate its working range and accuracy, and that it is not susceptible to drift or quick vibrations.

Here attached is the code and result of the complimentary filter, we make our final value 90% from the gyroscope and 10% from the accelerator. This is because in the experiment we found that the time unit of the accelerator and the gyroscope is different. When we use the same time unit for both of the methods, the gyroscope's results are around 10 while the results from the accelerator are over 100.

Description of the image

From the plot in the figure above we can notice that the pitch and roll value become very smooth after implementing the complimentary filter.

Task 7

Similar to Lab 1, collect and store time-stamped IMU data in arrays. Do this in your main loop using flags to start/stop data recording.

Here below is the code instructing how we store and send timestamp and pitch/roll data

Description of the image

Demonstrate that your board can capture at least 5s worth of IMU data and send it over Bluetooth to the computer.

Description of the image

Task 8

Demonstrate that your board can capture at least 5s worth of IMU data and send it over Bluetooth to the computer.

The figure below shows how the arduino is collecting, storing and sending IMU data. It also gives instruction about how our computer could receive the data using callback function in jupyter notebook. And we can notice that the IMU data are fully collected, stored, sent and received since the data printed in the jupyter notebook are also has a 3ms interval.

Description of the image

Here below shows the full results for the 5s data, it could be very long and you may just skip.

This is the end of this Lab!

                            
        time: 242958.0 pitch_acc: 30.364 pitch_gry: 0.976
        time: 242962.0 pitch_acc: 30.258 pitch_gry: 0.976
        time: 242965.0 pitch_acc: 30.357 pitch_gry: 0.976
        time: 242972.0 pitch_acc: 30.284 pitch_gry: 0.976
        time: 242974.0 pitch_acc: 30.67 pitch_gry: 0.976
        time: 242977.0 pitch_acc: 30.856 pitch_gry: 0.976
        time: 242984.0 pitch_acc: 30.417 pitch_gry: 0.976
        time: 242987.0 pitch_acc: 30.3 pitch_gry: 0.976
        time: 242990.0 pitch_acc: 30.181 pitch_gry: 0.976
        time: 242993.0 pitch_acc: 29.662 pitch_gry: 0.976
        time: 242997.0 pitch_acc: 30.500 pitch_gry: 0.976
        time: 243000.0 pitch_acc: 29.956 pitch_gry: 0.976
        time: 243005.0 pitch_acc: 30.33 pitch_gry: 0.976
        time: 243008.0 pitch_acc: 31.151 pitch_gry: 0.976
        time: 243010.0 pitch_acc: 30.326 pitch_gry: 0.976
        time: 243018.0 pitch_acc: 31.248 pitch_gry: 0.976
        time: 243023.0 pitch_acc: 29.649 pitch_gry: 0.976
        time: 243026.0 pitch_acc: 30.378 pitch_gry: 0.976
        time: 243028.0 pitch_acc: 29.409 pitch_gry: 0.976
        time: 243031.0 pitch_acc: 30.149 pitch_gry: 0.976
        time: 243034.0 pitch_acc: 30.518 pitch_gry: 0.976
        time: 243037.0 pitch_acc: 30.595 pitch_gry: 0.976
        time: 243040.0 pitch_acc: 30.188 pitch_gry: 0.976
        time: 243046.0 pitch_acc: 29.753 pitch_gry: 0.976
        time: 243049.0 pitch_acc: 30.25 pitch_gry: 0.976
        time: 243053.0 pitch_acc: 30.666 pitch_gry: 0.976
        time: 243056.0 pitch_acc: 30.289 pitch_gry: 0.976
        time: 243058.0 pitch_acc: 29.830 pitch_gry: 0.976
        time: 243063.0 pitch_acc: 30.98 pitch_gry: 0.976
        time: 243066.0 pitch_acc: 30.649 pitch_gry: 0.976
        time: 243070.0 pitch_acc: 29.424 pitch_gry: 0.976
        time: 243073.0 pitch_acc: 30.271 pitch_gry: 0.976
        time: 243075.0 pitch_acc: 30.522 pitch_gry: 0.976
        time: 243078.0 pitch_acc: 30.402 pitch_gry: 0.976
        time: 243082.0 pitch_acc: 30.642 pitch_gry: 0.976
        time: 243085.0 pitch_acc: 29.851 pitch_gry: 0.976
        time: 243087.0 pitch_acc: 30.538 pitch_gry: 0.976
        time: 243094.0 pitch_acc: 31.125 pitch_gry: 0.976
        time: 243097.0 pitch_acc: 30.276 pitch_gry: 0.976
        time: 243100.0 pitch_acc: 30.550 pitch_gry: 0.976
        time: 243103.0 pitch_acc: 30.599 pitch_gry: 0.976
        time: 243109.0 pitch_acc: 29.744 pitch_gry: 0.976
        time: 243112.0 pitch_acc: 30.568 pitch_gry: 0.975
        time: 243120.0 pitch_acc: 29.429 pitch_gry: 0.975
        time: 243122.0 pitch_acc: 30.123 pitch_gry: 0.975
        time: 243130.0 pitch_acc: 30.36 pitch_gry: 0.975
        time: 243133.0 pitch_acc: 30.62 pitch_gry: 0.975
        time: 243137.0 pitch_acc: 30.516 pitch_gry: 0.975
        time: 243139.0 pitch_acc: 29.822 pitch_gry: 0.975
        time: 243146.0 pitch_acc: 30.815 pitch_gry: 0.975
        time: 243149.0 pitch_acc: 30.336 pitch_gry: 0.975
        time: 243156.0 pitch_acc: 30.662 pitch_gry: 0.975
        time: 243159.0 pitch_acc: 29.666 pitch_gry: 0.975
        time: 243161.0 pitch_acc: 30.922 pitch_gry: 0.975
        time: 243165.0 pitch_acc: 30.204 pitch_gry: 0.975
        time: 243168.0 pitch_acc: 30.218 pitch_gry: 0.975
        time: 243174.0 pitch_acc: 30.213 pitch_gry: 0.975
        time: 243177.0 pitch_acc: 30.605 pitch_gry: 0.975
        time: 243184.0 pitch_acc: 30.181 pitch_gry: 0.975
        time: 243186.0 pitch_acc: 29.950 pitch_gry: 0.975
        time: 243190.0 pitch_acc: 30.197 pitch_gry: 0.975
        time: 243193.0 pitch_acc: 30.792 pitch_gry: 0.975
        time: 243195.0 pitch_acc: 30.999 pitch_gry: 0.975
        time: 243202.0 pitch_acc: 30.531 pitch_gry: 0.975
        time: 243205.0 pitch_acc: 30.60 pitch_gry: 0.975
        time: 243211.0 pitch_acc: 30.357 pitch_gry: 0.975
        time: 243214.0 pitch_acc: 29.684 pitch_gry: 0.975
        time: 243221.0 pitch_acc: 31.52 pitch_gry: 0.975
        time: 243223.0 pitch_acc: 29.848 pitch_gry: 0.975
        time: 243227.0 pitch_acc: 29.731 pitch_gry: 0.975
        time: 243230.0 pitch_acc: 30.577 pitch_gry: 0.975
        time: 243232.0 pitch_acc: 30.532 pitch_gry: 0.975
        time: 243239.0 pitch_acc: 30.38 pitch_gry: 0.975
        time: 243242.0 pitch_acc: 30.981 pitch_gry: 0.975
        time: 243248.0 pitch_acc: 29.861 pitch_gry: 0.975
        time: 243251.0 pitch_acc: 30.279 pitch_gry: 0.974
        time: 243258.0 pitch_acc: 29.997 pitch_gry: 0.975
        time: 243261.0 pitch_acc: 30.463 pitch_gry: 0.975
        time: 243265.0 pitch_acc: 29.449 pitch_gry: 0.975
        time: 243268.0 pitch_acc: 30.594 pitch_gry: 0.974
        time: 243274.0 pitch_acc: 29.614 pitch_gry: 0.975
        time: 243277.0 pitch_acc: 30.951 pitch_gry: 0.975
        time: 243285.0 pitch_acc: 30.618 pitch_gry: 0.975
        time: 243288.0 pitch_acc: 30.214 pitch_gry: 0.975
        time: 243295.0 pitch_acc: 30.193 pitch_gry: 0.975
        time: 243298.0 pitch_acc: 30.65 pitch_gry: 0.975
        time: 243302.0 pitch_acc: 30.301 pitch_gry: 0.975