Speed testing the MPU9150’s functions using a LinkIt ONE

Standard

Background

I am working on a project where I am gathering a lot of data. One of the sources of my data is my 9Dof sensor. Since I am logging at sub-second intervals, I wanted to know how long (the cost of time) each sensor takes to return data, so I make sure to get as many data points, from as many data sources as possible.

I set up this project with the sole intention of determining the cost in milliseconds of the standard example, then try to figure out how to make it faster.

Setup

I grabbed my trusty LinkIt ONE and my 9Dof sensor (MPU9150, connecting over I2C), and looked at the example library. I wanted to get data from each of the sensors as fast as possible, and I will do post-capture processing for heading and orientation. I set my sights on these three programs:

  • getAccel_Data
  • getGyro_Data
  • getCompass_Data

I then made blocks of C to run in a loop:

Serial.print(millis() % 1000);
Serial.print(",Acc1,");
getAccel_Data();
Serial.print(Axyz[0]);
Serial.print(",");
Serial.print(Axyz[1]);
Serial.print(",");
Serial.print(Axyz[2]);
Serial.print(",");
Serial.println(millis() % 1000);


This is my code for checking a single Accelerometer data gathering. I figured all I had to do is try running the same block, with additional runs of “getAccel_Data;” and notations of “”Acc_” so I can to comparisons afterwards. I then take the time difference between the start and end and map it to the sensor read type, and the sensor read count. After that, I subtract the time of the single run to the double and triple run to find how much longer it took for the one or two additional runs.

Accelerometer Tests

Let’s have a look at one set of my results (do note, time is in milliseconds, 1/1000th of a second):

Row Labels Average of Runtime StdDev of Runtime
Acc1 23.307 2.230
Acc2 45.701 3.985
Acc3 68.123 6.254

First thing I see here is that 23.3 + 45.7 does not equal 68.1. This is good, this is what I expect, and am glad to see. My formula for calculating the actual average runtime of getAccel_Data is as follows:

( (Acc2 – Acc1) + (Acc3 – Acc1) ) / 3

This is set up to give a double weight to the difference between Acc3 and Acc1, since there was an additional run compared to Acc2 to Acc1.

Testing All Sensors

I created a few sets of functions besides the stock ones to test out.

  • getAccelGyro_Data: Combined getAccel_Data and getGyro_data, eliminating duplicate runs of accelgyro.getMotion9
  • getDof_Data: Combines getAccelGyro_Data and getCompass_Data
  • getRawDof_Data: getDof_Data without the calculations, just raw values

Ultimately, I let my computer run, and I got 4600 records for each set of sensors. Here’s my results:

Runtime
Function Runs/cycle Average StdDev
getAccel 1 23.307 2.230
getAccel 2 45.701 3.985
getAccel 3 68.123 6.254
getAccelGyro 1 23.364 1.998
getAccelGyro 2 45.844 3.899
getAccelGyro 3 68.235 6.166
getGyro 1 23.303 2.005
getGyro 2 45.729 3.924
getGyro 3 68.192 6.200
getCompass 1 11.231 2.411
getCompass 2 21.774 4.139
getCompass 3 32.368 6.095
getDof 1 33.926 3.493
getDof 2 66.875 7.062
getDof 3 99.803 10.856
getRawDof 1 33.945 3.418
getRawDof 2 66.967 7.083
getRawDof 3 99.951 10.899

From this, I calculated the following:

Function Actual Cycle Cost Overhead Cost
getAccel 22.4038 0.8983
getGyro 22.4380 0.8591
getCompass 10.5597 0.6631
getAccelGyro 22.4504 0.9287
getDof 32.9420 0.9872
getRawDof 33.0094 0.9418

Conclusion

  1. The library should not have “getAccel_data” and “getGyro_data”, rather just combine the two together for optimal performance.
  2. Also, when we look at the ‘getDof” vs. “getRawDof”, by saving the larger values instead of reducing their size before saving, it actually costs time. About 0.0674 milliseconds per cycle.
  3. You save 22.4596 milliseconds per cycle by combining gathering the sensor data into one procedure.
  4. You save 0.0681 milliseconds by running “getDof_data” instead of “getAccelGyro_data” and then “getCompass”.

LinkIt ONE RTC Example Code

Standard

When I was trying out all the different parts of the LinkIt, I wondered if there was an RTC onboard. Loovee told me there was, but that the example was not complete at this point in time.

I took this situation upon myself to make a complete example for anyone else out there who wants to use the LinkIt’s onboard RTC. In this discovery of things, I found that the RTC can be set back to 1/1/2004 if the battery and USB power supply are both disconnected. I made a loop in my code that will turn on the GPS to resync the GMT automatically in the background, the only thing that needs to happen is for the GPS to turn on. This is why in my more complex programs, I didn’t see the resetting behavior.

Here is a screenshot of what it looks like when the GPS has finally synced the time:

LDateTime working demo

And here is the code that runs the whole thing:

#include <LDateTime.h>
#include <LGPS.h>

datetimeInfo t;
unsigned int rtc;
int gps_on=0; //This is used to check if the GPS needs to be turned off

void setup() {
 Serial.begin(115200);
 }

void loop() {
 
 LDateTime.getTime(&t);
 LDateTime.getRtc(&rtc);
 
 Serial.print("Current GMT: ");
 Serial.print(t.mon);
 Serial.print("/");
 Serial.print(t.day);
 Serial.print("/");
 Serial.print(t.year);
 Serial.print(" ");
 Serial.print(t.hour);
 Serial.print(":");
 Serial.print(t.min);
 Serial.print(":");
 Serial.print(t.sec);
 
 Serial.print(" Seconds since 1/1/1970 GMT: ");
 Serial.println(rtc);
 
 //Turning on the GPS syncs up the RTC with the GPS time.
 //If the battery is pulled, the RTC goes back a couple years.

 //Turning on the GPS syncs up the RTC with the GPS time.
 //If the GPS is needed, t.year will be 2004. This will start this loop.
 if ((gps_on != 1) && (t.year < 2010))
 {
 Serial.println("Using GPS to sync GMT. Please wait...");
 LGPS.powerOn();
 gps_on = 1;
 }

 //If the GPS has synced the RTC, the year will be 2015 or greater.
 if ((gps_on == 1) && (t.year >= 2015))
 {
 LGPS.powerOff();
 Serial.println("Synced! Turning off GPS. Please wait...");
 gps_on = 0;
 }
 
 //Wait one second before getting new time.
 delay(1000);
 }