Lab 2 – IMU
Lab 2 – IMU
[Picture of IMU attached]
Objective
The goal of this lab was to integrate the ICM-20948 IMU with the Artemis Nano and start collecting data on the car’s orientation using both accelerometer and gyroscope data. By combining sensor data and applying filters we are supposed to build a stable movement model that can be communicated over bluetooth.
Setting up the IMU
The AD0_VAL in the Basic Sparkfun Example dictates the least significant bit of the UMU’s I2C address and should be set to 1 which is default.
When moving the IMU, acceleration changes along the noted axes on the board, with gravity constantly applying acceleration towards the ground. If only moved in translational directions there are no gyroscope readings. The gyroscope only picks up rotational movements which rotate about the noted axes on the board. Similarly rotational movements do not affect the accelerometer readings apart from the constant gravity.
[Video of IMU moving with data]
To help with visual debugging I added a function which runs in the board setup which flashes the on-board LED three times before entering the main loop function.
Accelerometer
Using the equations from lecture I calculated pitch and roll using the accelerometer data in each axis. The trigonometric formulation uses atan2 to remain numerically stable across quadrants:
pitch = atan2(accX, accZ) * 180/M_PI;
roll = atan2(accY, accZ) * 180/M_PI;
[Video of IMU moving pitch and roll from 90 0 -90 degrees on computer edge]
As shown in the video the accelerometer is able to quickly follow the changes in acceleration and when stabilized accurately display a large acceleration towards the direction of gravity.
A python script was written to both parse and plot the data arrays sent from the Artemis over bluetooth and is illustrated later in this report. The arrays sent for the accelerometer include time, pitch, and roll. An array size of 2000 accurately encompassed 6-8 seconds of data.
The accelerometer showed overall good accuracy in all axes during repeated runs. The bias between a positive axis and a negative one was not substantial nor consistent on reboot so two point calibration was not required.
To test the noise levels of the IMU the car motors were driven in its proximity and vibrations were induced on the testing table. The resulting noise levels were notably high across the whole spectrum once the data was analyzed in the frequency domain.
[Insert image of fft noise]
Looking closely there is a noticeable frequency component from zero (of course) but also the frequencies up to 5Hz. This can be seen most clearly in the Pitch Fast Fourier Transform graph. Thus, 5Hz was set as the cutoff frequency to keep some accelerometer responsiveness while also filtering out the high frequency noise. The following equations from class were then used to find an alpha of 0.0982, corresponding to my sampling rate of 288.66 Hz.
[Insert alpha equation] [insert cutoff frequency equation]
Upon implementing the low pass filter the accelerometer data is substantially less noisy and has a cleaner frequency domain, though some persistent noise still exists.
It is worth noting that the IMU board features an integrated “Digital Motion Processor” that runs its own algorithms on sensor feedback before passing the data to the Artemis board.
Gyroscope
The equations for calculating pitch, roll, and yaw angles from the gyroscope use integration over time following this equation:
dt = (micros()-last_time)/1000000;
angle += gyro_rate * dt;
This was applied to all three gyroscope axes to create the following reading.
[insert raw gyro reading]
The gyroscope provides smooth motion tracking and can handle fast changes well, but because it relies on additive integration any and all small errors increase in size over time. When compared to the accelerometer which does not experience any drifting bias, the accelerometer is much more susceptible to vibrational and environmental noise. Thus, the accelerometer provides long term absolute orientation with the help of gravity and the gyroscope provides smooth tracking and accurate short term tracking.
[insert raw gyro vs accelerometer]
The sampling rate directly impacts the gyroscope integration quality because smaller steps provide higher resolution. When sampling is slow, each update covers a large time delta so any bias or noise encountered in this period is magnified in the sample. On the flip side as sampling is fast, time delta decreases and integration becomes smoother and more stable.
To combine strengths of both sensors I apply a complimentary filter as follows:
angle = (1-alpha)(prev_angle + gyro_delta) + alpha*(accel_angle)
Because my sampling rate is generally high in the range of 250-350 Hz the gyroscope actually provides the most accurate data in the near term and thus I chose to essentially weigh it at 95% with an alpha of 0.05. This means the accelerometer only lightly contributes to the total trend, but consistently counters the long term drift. With this combination the complimentary filter is able to accurately chase both stable and sporadic movements, though it does experience some lag in terms of updating.
[insert stationary comp filter]
While stationary the complimentary filter is able to most accurately model the lack of movement in comparison to both the filtered accelerometer and the raw gyroscope data. While moving it is also able to accurately track the changes, most notably in the roll graph where the primary movement was occurring about the axis.
[insert mobile comp filter]
Sample Data Collection
Loop optimization
In order to increase the sampling rate I removed any delay, print, or busy wait functions to prevent unnecessary time gates. The data is stored in a predefined data array of floats. I chose a size of 2000 elements to appropriately capture over 5 seconds of data with leeway for starting and ending a motion. The IMU data collection and the bluetooth data transmit were both moved into the main loop as opposed to a specific case using data flags. So now the GET_ACC_GYRO case just resets flags as appropriate to enable the data collection in main. With these changes the mean sampling rate became 275Hz and the median was 333.3Hz, an improvement from before. At this point the IMU refresh rate is a limiting factor as the loop to collect data depends on the IMU registering containing new and available data.
In order to store data into the arrays my code first checks to see if there is new available data. If there is, it records the current time in microseconds and uses the previous time to calculate the time delta for the gyroscope integration. Gyroscope pitch roll and yaw are then respectively calculated and then stored into the respective array at the correct index. Simultaneously, the time stamp is saved using milliseconds and the data for the accelerometer’s pitch and roll are calculated and stored respectively. Then the IMU array index is incremented and the loop will wait until the data function is called again and data is available. If the data arrays are full the flag for data collection is lowered and the flag for data transmission is raised handing off responsibilities to a transmit function in the main loop.
The transmit function behaves very similarly to those in previous labs involving clearing the transmit string data, appending new information, and then finally writing the finished value. This occurs in a loop through each index as it is iterated each time and finishes upon completing the array.
[insert final data]
The float type was chosen for the data arrays given that the IMU outputs decimal numbers and because they take up half of the space as a double. This also provided sufficient precision for the car’s needs.
The Artemis Nano has about 384 kB of RAM available and each IMU sample as designed in my lab consists of six values: time, accelerometer pitch, accelerometer roll, gyroscope pitch, gyroscope roll, and gyroscope yaw. Each of these values are stored as 4 byte floats meaning each time sample has 24 bytes of data. At the measured sampling rate of 275Hz, the Artemis could store approximately 60 full seconds of data.
RC Car Stunt
[insert stunt video]
After playing around with the car I discovered that driving the car quickly forward or backward and suddenly switching directions provided reliable torque that could flip the vehicle over to the underside. This is the stunt that I chose to record in my demonstration.