IMU9250 + Stepper; Measurement takes long time


Hello everyone! It's my first post here :slight_smile:

Sooo.... I started with usual stuff like "read analog/digital" and then immediately jumped to more interesting things like IMU9250 I2C gyro/accel/magneto-meter. I was experimenting with it a bit using I2C and various libraries available. I have nice readings based on MPU6050 library which I found most appropriate a then I added some LCD output to have some freedom from serial console :slight_smile:

From this point I decided to go with "I will make a camera stabilizer". So there goes a stepper motor (AccelStepper library).

And here I have encountered first interesting class problem :slight_smile:
Metering of IMU position takes quite a time. So stepper move (run()) procedure is not started very often and the engine is moving slowly as an effect.

What would you do to have the engine moving faster to desired position?
I see several options now:

  1. Optimize current libraries
  2. Buy different stepper without gearing and ratio
  3. Build a custom stepper driver with "memory" (keep moving till arduino says to stop)

what you think?

Metering of IMU position takes quite a time.

Reading the IMU is fast. It is whatever you are doing with the data that takes time. Since you didn't bother to post code, even though you posted in the Programming section, and the rules clearly require you to post your code, we can not help you.

Hi :slight_smile:
It's not like I did't bother - I didn't want to go the way of "hey could you fix my code for me" :slight_smile:
I will add the code - It needs some cleaning up before it can be shown to the public :slight_smile:

Steppers aren't used for camera stabilizers much due to the heavy vibration they generate. Gimbal
motors are beautifully smooth by comparison, but a lot harder to drive.

Make sure your LCD calls aren't taking lots of time, BTW. If you use serial, be sure to use the maximum
baud rate you can.

I will add the code - It needs some cleaning up before it can be shown to the public

Oh, come on. We promise not to laugh. Too much.

Hi again,

" Gimbal motors are beautifully smooth by comparison, but a lot harder to drive.".

Hmmmm what kind of engine is used in gimbal?

Hmmmm what kind of engine is used in gimbal?

Gee, that's a tough one. Even Mr. Google was stumped, and could only come up with 448,000 answers.

Oh Yes :slight_smile: google. So it's brushless engine.
I have a stepper and I don't have brushless engine and driver :slight_smile: Anyway - it is not a commercial project and value is in learning so I will stick with my stepper for now.

Hello again,

So I have removed all "non 9250 and non stepper" code.

#include <AccelStepper.h>
#include <MultiStepper.h>

#define motorPin1  3     // IN1 on the ULN2003 driver 1
#define motorPin2  4     // IN2 on the ULN2003 driver 1
#define motorPin3  5     // IN3 on the ULN2003 driver 1
#define motorPin4  6     // IN4 on the ULN2003 driver 1
#include "MPU6050_6Axis_MotionApps20.h"

#include "I2Cdev.h"

AccelStepper stepper1( 4, motorPin1, motorPin3, motorPin2, motorPin4);

MPU6050 mpu;

#define LED_PIN 13
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

//// packet structure for InvenSense teapot demo
//uint8_t teapotPacket[14] = { '

, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' };

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
 mpuInterrupt = true;

void setup() {
 //experimental values here for motor - used different to see what's going on
//  stepper1.moveTo(4000);

// join I2C bus (I2Cdev library doesn't do this automatically)
 TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
 Fastwire::setup(400, true);


delay (1000);
 // load and configure the DMP
 //Serial.println(F("Initializing DMP..."));
 devStatus = mpu.dmpInitialize();

// gyro offsets

if (devStatus == 0) {
   attachInterrupt(0, dmpDataReady, RISING);
   mpuIntStatus = mpu.getIntStatus();
   dmpReady = true;
   packetSize = mpu.dmpGetFIFOPacketSize();
 } else {
   // ERROR!
 pinMode(LED_PIN, OUTPUT);

void loop() {
 if (!dmpReady) return;

mpuInterrupt = false;
 mpuIntStatus = mpu.getIntStatus();

fifoCount = mpu.getFIFOCount();

// check for overflow (this should never happen unless our code is too inefficient)
 if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
 } else if (mpuIntStatus & 0x02) {
   while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
   mpu.getFIFOBytes(fifoBuffer, packetSize);
   fifoCount -= packetSize;

blinkState = !blinkState;
   digitalWrite(LED_PIN, blinkState);

//experimental method here - trying different ways
//  if (stepper1.distanceToGo() == 0) {
//    stepper1.moveTo(stepper1.currentPosition() + 1000);
//  }

Hello again :slight_smile:
So nothing funny in my code?

void loop() {
 if (!dmpReady) return;

This is just wrong. Do whatever you need to do when the dmp IS ready. Do other stuff, like making the steppers step, regardless of whether or the the dmp is ready.

Attached is a revised version of the Example code you are working with This I believe is easier to understand and doesn't have a fifo buffer corruption issue and blocking loop the example code you are working with has.
I've also attached a calibration code that provides offsets for tuning the MPU It is designed for the 9255 but it may work on the 9250. the mpu 6050 calibration code didn't work correctly on the 9255 and so I had to create a different version based on datasheet specs.


PS Same code I use on my balancing bot

MPU6050_Latest_code.ino (7.78 KB)

MPU-9255Cal.ino (44.7 KB)

Oh Guys!

Thank you for that! :slight_smile:

Have a great day!

I briefly scanned the code :slight_smile: Calibration code is beautiful :slight_smile:
I need to leave now for some time alone with my computers :))