High speed accelerometer data

3dlinux

Member
Hi there, I have been working for the last few weeks to get high speed readings from accelerometers. So far I could get max 5ms between readings, however it is not enough for me. I have been using SPI and I2C with Arduino Nano 33 IOT, MEGA 2560 (+ few more) and Raspberry PI. I have MPU6050 and ICM-20948 accelerometers and I will get a MPU9020 soon. What is the max frequency that I can get with Teensy 4.1 using the examples/libraries from Arduino IDE using SPI, I2C? Is there anything else that I can try? I am not sure yet what is the max. frequency I need to achieve.
I know there is a lot of details to be worked out, however I would like to get some general information that I can use.

Thanks in advance!
Cristian
 
I2C is a bit slow for high data rates so SPI is the way to go. Also, the MPU9250 allows for higher SPI clock speeds when accessing just the data registers so check that out for your particular devices. I managed to collect 32KSPS gyro and 4KSPS accel data from the MPU9250 on theTeensy3.6 without resorting to DMA.
 
Thank You!
Yesterday I was able to get 1.047ms using Teensy 4.1 and ICM-20948.
Please post the link to "4KSPS accel data" file (Teensy + MPU9250). There are few versions available, however I am not sure which one to use.
 
Hello everyone, After struggling for weeks to get accelerometer data within less than 5 milliseconds between readings, I have suddenly able to get to 25 microseconds. I have no reasons to believe that the data is wrong however, somebody please review the set-up and let me know if you see anything wrong.

Also, I do not know how, but using a laptop with Intel i7 CPU and wireless connection to home router, I was able to break the internet connection. The laptop was connected to the Teensy board using USB cable. Every time I was taking measurements, my daughter, from in a different room, was complaining that the netflix is down and I have to come to fix it.

I am using Teensy 4.1 with LSM6DS3, using the attached Arduino sketch (MultiSPI.ino). According to my calculations the data is recorded at 40KSPS??????


Code:
/
******************************************************************************
MultiSPI.ino

Marshall Taylor @ SparkFun Electronics
May 20, 2015
https://github.com/sparkfun/LSM6DS3_Breakout
https://github.com/sparkfun/SparkFun_LSM6DS3_Arduino

Description:
Example using up to two LSM6DS3s on the same SPI channel, with different CS pins.
If only one sensor is attached, this sketch reports failure on that channel and
runs with the single sensor instead.

Resources:
Uses Wire.h for i2c operation
Uses SPI.h for SPI operation
Either can be omitted if not used

Development environment specifics:
Arduino IDE 1.6.4
Teensy loader 1.23
Hardware connections

***CAUTION -- SPI pins can not be connected directly to 5v IO***

Connect SDA/SDI lines to pin 11 through level shifters (MOSI)
Connect SCL pin lines to pin 13 through level shifters (SCLK)
Connect SDO/SA0 lines to pin 12 through level shifters (MISO)
Connect CS to free pins through level shifters.  This example uses 9 and 10.
Connect GND and ***3.3v*** power to the IMU.  The sensors are not 5v tolerant.

(Multiple SPI devices share pins except for the Chip Select lines which
are unique for each device on the bus.)

This code is released under the [MIT License](http://opensource.org/licenses/MIT).

Please review the LICENSE.md file included with this example. If you have any questions 
or concerns with licensing, please contact techsupport@sparkfun.com.

Distributed as-is; no warranty is given.
******************************************************************************/

////Teensy loader 1.23/////

//I could get 25 micros"


#include "SparkFunLSM6DS3.h"
//#include "Wire.h"
#include "SPI.h"

//Create two instances of the driver class
LSM6DS3 SensorOne( SPI_MODE, 10 );
//LSM6DS3 SensorTwo( SPI_MODE, 9 );

unsigned long time_now;


void setup() {

SPI.beginTransaction(SPISettings(600000000, MSBFIRST, SPI_MODE0));
  
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(1000); //relax...
  Serial.println("Processor came out of reset.\n");
  
  //Call .begin() to configure the IMUs
  if( SensorOne.begin() != 0 )
  {
	  Serial.println("Problem starting the sensor with CS @ Pin 10.");
  }
  else
  {
	  Serial.println("Sensor with CS @ Pin 10 started.");
  }
    //if( SensorTwo.begin() != 0 )
    //{
	  //  Serial.println("Problem starting the sensor with CS @ Pin 9.");
    //}
   // else
   // {
	  //  Serial.println("Sensor with CS @ Pin 9 started.");
   // }
  
}


void loop()
{
  //Get all parameters
  time_now=micros();
  Serial.print(time_now);  
  //Serial.print("\nAccelerometer:\n");
  Serial.print("/t");
  Serial.print(SensorOne.readFloatAccelX(), 4);
  Serial.print("/t");
  Serial.print(SensorOne.readFloatAccelY(), 4);
  Serial.print("/t");
  Serial.print(SensorOne.readFloatAccelZ(), 4);
  Serial.print("/t");

  //Serial.print(" X2 = ");
 // Serial.println(SensorTwo.readFloatAccelX(), 4);
 // Serial.print(" Y2 = ");
 // Serial.println(SensorTwo.readFloatAccelY(), 4);
 // Serial.print(" Z2 = ");
 // Serial.println(SensorTwo.readFloatAccelZ(), 4);
  
  //Serial.print("\nGyroscope:\n");
    //Serial.print(" X1 = ");
   // Serial.println(SensorOne.readFloatGyroX(), 4);
   // Serial.print(" Y1 = ");
   // Serial.println(SensorOne.readFloatGyroY(), 4);
   // Serial.print(" Z1 = ");
   // Serial.println(SensorOne.readFloatGyroZ(), 4);
   // Serial.print(" X2 = ");
   // Serial.println(SensorTwo.readFloatGyroX(), 4);
   // Serial.print(" Y2 = ");
   // Serial.println(SensorTwo.readFloatGyroY(), 4);
   // Serial.print(" Z2 = ");
  //  Serial.println(SensorTwo.readFloatGyroZ(), 4);

   // Serial.print("\nThermometer:\n");
   // Serial.print(" Degrees C = ");
   // Serial.println(SensorTwo.readTempC(), 4);
   // Serial.print(" Degrees F = ");
   // Serial.println(SensorTwo.readTempF(), 4);
  
    //Serial.print("\nSensorOne Bus Errors Reported:\n");
    //Serial.print(" All '1's = ");
   // Serial.println(SensorOne.allOnesCounter);
   // Serial.print(" Non-success = ");
  //  Serial.println(SensorOne.nonSuccessCounter);
  //  Serial.print("SensorTwo Bus Errors Reported:\n");
   // Serial.print(" All '1's = ");
   // Serial.println(SensorTwo.allOnesCounter);
   // Serial.print(" Non-success = ");
   // Serial.println(SensorTwo.nonSuccessCounter);
   Serial.println();
  //delay(1);
}
 

Attachments

  • data.jpg
    data.jpg
    121.7 KB · Views: 148
Last edited:
Been a while since I played with this stuff but if you look at your data it isn't changing.

A quick look at the data sheet brought back memories, but if you want the max data rate you are going to need to adjust the ODRs for the accel/gyro. Think the may you are going to be able to do is 1.66kHz.
 
All of the configuration details are hidden in the library (not shown here) so I have no idea what it is doing. Things like the default ODR.

With a serial data rate of 115Kbps you are not going to output ASCII data at 40KSPS. Perhaps for a short time if the data is buffered.

I see no hint of waiting for the next sample to be available. Just a loop that reads and outputs data as fast as it can.
 
Thanks mjs513! I have locked the accelerometer in place in order not to interfere with anything else. That is the reason the data does not change.


Forgot to mention on my previous post that I have used STEVAL MKI160V1 adapter board for accelerometer, not the LSM6DS3 Breakoutboard from Sparkfun!
 
That is the reason the data does not change.

There is always noise.

The command to read the data registers will always return the value currently stored there even if it hasn't been updated in a long time. If the ODR is 400 and you read it every 25us then you will see 100 copies of each sample.

The correct way to deal with this is to only read the data registers when new data is available. You could check the status register but you would waste a lot of time waiting for a data available flag. The best way is use an interrupt. Followed by reading all of the data registers with a single SPI read registers command.
 
Back
Top