Gyro Stabilizer W/ Arduino and Servo

69,158

114

70

Introduction: Gyro Stabilizer W/ Arduino and Servo

About: Software Developer of many things. Builder and tinkerer of more things. Curious of most things.

Pitch:

This is how I managed to use a MPU6050, an Arduino Nano, and two Servos to perform basic planar stabilization, as would be found on camera gimbals and so on. This is a work in progress but the guide provide hardware connections and basic code to implement my initial prototype.

My List of Parts:

1 x 6 DOF MPU-6050 module (http://goo.gl/0uxWkR) from Banggood.com

1 x Arduino Nano

2 x 9g Servos (http://goo.gl/N81jsj) from Banggood.com

2 x 10k Resistors

1 x Breadboard

Jumper wires

USB Battery pack (for independent power) or use USB power from a PC

IMPORTANT: I pay Banggood.com only w/ PayPal. I read that you shouldn't use credit cards there.

Step 1: Step 1: Push Things in and Roll Tape.

1. It took me a long time to convince me that I need 10k Pull-Up Resistors on SCL and SDA pins off MPU-6050 module. But they are vital for the MPU to function properly. Before I added those resistors, my MPU would cause lock-up w/in a minute of power-up. Also pay attention to the #2 and #3 below for complete solution.

(Updated on 1/17/16)

2. Jeff Rowberg @ I2CDevlib.com points out ADO pin must be connected to GND (I2CDevlib.com post).

3. ArsenioDev also points out that baud rate for MPU should be kept at maximum 115200.

4. Thank you for the tips! The tips above completely solved my lock-ups!

5. I'm now running on a DIY Uno w/ ATmega32P-PU w/ clock and two caps and it's running equally great! ATmega by itself only takes about 3ma right now, aside from the MPU and Servo powers.

For wire connections, use the diagram or pictures as a reference. (Also explained in the code)

MPU -> Arduino

VCC -> 5V (this powers the rail and hence the whole system including the servos)

GND -> GND

SCL -> A5

SDA -> A4

INT -> D2 (I have it but not used in current software. I'm polling, not interrupting in this set up)

IMPORTANT: In addition to the wires above, two 10k resistors:

SCL -> 10K resistor (BROWN-BLK-ORANGE-Whatever) -> 5V Rail

SDA -> 10K resistor -> 5V Rail

ADO -> GND (Per Jeff Rowberg @ I2CDevlib.com - See Above)

SERVO 1 -> Arduino

This is the first servo taped (I know it's totally a hack job) on the breadboard, and this is oriented so that it would rotate around the long (or longitudinal or roll) axis. My servos had Brown-Orange-Yellow wires.

BROWN -> GND

ORANGE -> 5V Rail

YELLOW -> D10

SERVO 2 -> Arduino

This is the second servo that is mounted to the servo 1 which controls the pitch axis. Again, it's wrapped even worse than the first one so it's barely visible in the picture.

BROWN -> GND

ORANGE -> 5V Rail

YELLOW -> D11

Step 2: Step 2: Check the Servo Orientation

For the code to work correctly w/o any adjustment, it would help to make sure the servos are oriented the same way as mine. I know the tapes make it terrible to discern. Sorry... If you tape up, or screw everything together and find out that something's turned around, it's no big deal. We'll fix it in the next step.

Step 3: Step 3: Send 1's and 0's to the Arduino Nano

Of course any Arduino should work, but I've been using these Nanos a lot for their affordable price.

Upload the code using the USB cable from your PC. If you have a long cable, you may just leave it alone and let it power the unit. I taped (I know. This is the last one.) a USB power bank underneath the breadboard so I can hold it and feel cool about my sticky mess.

BTW, I have been using the USB brick underneath a breadboard and use USB output to power an Arduino or even connect to a USB-Serial interface (Like an FTDI interface) to power the breadboard and it's been very handy.

It should fire up, and should start it's wake-up dance. It's designed to sweep on both axis to clear the area. If it hits the chassis or things like that, it's possible the mount is too restrictive or servo is mounted backwards.

If a servo seems mounted backwards, you can adjust the code to reverse it's command:

<p>Servo1.write(-mpuPitch + 90);<br>Servo2.write(mpuRoll + 90);</p>

If the command seems to be adding to a change and not correcting it, you may try to reverse the sign of the mpuPitch or mpuRoll. Also, +90 is there because I oriented my servos so that 'normal' horizontal position would be in the middle of the servo range. You may play w/ that value as well depending on your installation.

Step 4: Step 4: Help Me Out Please

I learned a tremendous amount already from everyone w/ their awesome comments on Reddit. (https://goo.gl/lI0ir3)

So please help me make it better and learn lots of other things. I put Kalman Filter and PID on the list of things to read up to improve the command logic. Thank you for reading my first instructable.

P.S. If it does lock up on you, a reset on arduino should get it going again. Sorry.

Arduino All The Things! Contest

Participated in the
Arduino All The Things! Contest

7 People Made This Project!

Recommendations

  • Microcontroller Contest

    Microcontroller Contest
  • Automation Contest

    Automation Contest
  • Make it Glow Contest

    Make it Glow Contest

70 Comments

0
paul.sneed.39
paul.sneed.39

3 years ago

pretty sweet!. I made a sweet gimbal, but I'm having issues with the programming though.

----------------------------------------------------------------------

Archiving built core (caching) in: C:\Users\Paul\AppData\Local\Temp\arduino_cache_716588\core\core_arduino_avr_nano_cpu_atmega328_b327234c182a9507b43cdc52bd64fc97.a

C:\Users\Paul\AppData\Local\Temp\ccCJUtOe.ltrans0.ltrans.o: In function `__static_initialization_and_destruction_0':

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:70: undefined reference to `MPU6050::MPU6050()'

C:\Users\Paul\AppData\Local\Temp\ccCJUtOe.ltrans0.ltrans.o: In function `setup':

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:125: undefined reference to `MPU6050::initialize()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:129: undefined reference to `MPU6050::testConnection()'

C:\Users\Paul\AppData\Local\Temp\ccCJUtOe.ltrans0.ltrans.o: In function `dmpInitialize':

sketch/MPU6050_6Axis_MotionApps20.h:328: undefined reference to `MPU6050::reset()'

sketch/MPU6050_6Axis_MotionApps20.h:339: undefined reference to `MPU6050::setSleepEnabled(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:343: undefined reference to `MPU6050::setMemoryBank(unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:345: undefined reference to `MPU6050::setMemoryStartAddress(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:350: undefined reference to `MPU6050::setMemoryBank(unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:359: undefined reference to `MPU6050::getXGyroOffsetTC()'

sketch/MPU6050_6Axis_MotionApps20.h:360: undefined reference to `MPU6050::getYGyroOffsetTC()'

sketch/MPU6050_6Axis_MotionApps20.h:361: undefined reference to `MPU6050::getZGyroOffsetTC()'

sketch/MPU6050_6Axis_MotionApps20.h:371: undefined reference to `MPU6050::setSlaveAddress(unsigned char, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:373: undefined reference to `MPU6050::setI2CMasterModeEnabled(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:375: undefined reference to `MPU6050::setSlaveAddress(unsigned char, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:377: undefined reference to `MPU6050::resetI2CMaster()'

sketch/MPU6050_6Axis_MotionApps20.h:384: undefined reference to `MPU6050::writeProgMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:391: undefined reference to `MPU6050::writeProgDMPConfigurationSet(unsigned char const*, unsigned int)'

sketch/MPU6050_6Axis_MotionApps20.h:395: undefined reference to `MPU6050::setClockSource(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:398: undefined reference to `MPU6050::setIntEnabled(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:401: undefined reference to `MPU6050::setRate(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:404: undefined reference to `MPU6050::setExternalFrameSync(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:407: undefined reference to `MPU6050::setDLPFMode(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:410: undefined reference to `MPU6050::setFullScaleGyroRange(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:414: undefined reference to `MPU6050::setDMPConfig1(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:416: undefined reference to `MPU6050::setDMPConfig2(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:419: undefined reference to `MPU6050::setOTPBankValid(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:422: undefined reference to `MPU6050::setXGyroOffsetTC(signed char)'

sketch/MPU6050_6Axis_MotionApps20.h:423: undefined reference to `MPU6050::setYGyroOffsetTC(signed char)'

sketch/MPU6050_6Axis_MotionApps20.h:424: undefined reference to `MPU6050::setZGyroOffsetTC(signed char)'

sketch/MPU6050_6Axis_MotionApps20.h:435: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:439: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:442: undefined reference to `MPU6050::resetFIFO()'

sketch/MPU6050_6Axis_MotionApps20.h:445: undefined reference to `MPU6050::getFIFOCount()'

sketch/MPU6050_6Axis_MotionApps20.h:450: undefined reference to `MPU6050::getFIFOBytes(unsigned char*, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:453: undefined reference to `MPU6050::setMotionDetectionThreshold(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:456: undefined reference to `MPU6050::setZeroMotionDetectionThreshold(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:459: undefined reference to `MPU6050::setMotionDetectionDuration(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:462: undefined reference to `MPU6050::setZeroMotionDetectionDuration(unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:465: undefined reference to `MPU6050::resetFIFO()'

sketch/MPU6050_6Axis_MotionApps20.h:468: undefined reference to `MPU6050::setFIFOEnabled(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:471: undefined reference to `MPU6050::setDMPEnabled(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:474: undefined reference to `MPU6050::resetDMP()'

sketch/MPU6050_6Axis_MotionApps20.h:478: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:482: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:486: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:489: undefined reference to `MPU6050::getFIFOCount()'

sketch/MPU6050_6Axis_MotionApps20.h:494: undefined reference to `MPU6050::getFIFOBytes(unsigned char*, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:503: undefined reference to `MPU6050::readMemoryBlock(unsigned char*, unsigned int, unsigned char, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:506: undefined reference to `MPU6050::getFIFOCount()'

sketch/MPU6050_6Axis_MotionApps20.h:512: undefined reference to `MPU6050::getFIFOBytes(unsigned char*, unsigned char)'

sketch/MPU6050_6Axis_MotionApps20.h:521: undefined reference to `MPU6050::writeMemoryBlock(unsigned char const*, unsigned int, unsigned char, unsigned char, bool, bool)'

sketch/MPU6050_6Axis_MotionApps20.h:526: undefined reference to `MPU6050::setDMPEnabled(bool)'

sketch/MPU6050_6Axis_MotionApps20.h:535: undefined reference to `MPU6050::resetFIFO()'

sketch/MPU6050_6Axis_MotionApps20.h:536: undefined reference to `MPU6050::getIntStatus()'

C:\Users\Paul\AppData\Local\Temp\ccCJUtOe.ltrans0.ltrans.o: In function `setup':

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:138: undefined reference to `MPU6050::setXGyroOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:139: undefined reference to `MPU6050::setYGyroOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:140: undefined reference to `MPU6050::setZGyroOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:141: undefined reference to `MPU6050::setXAccelOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:142: undefined reference to `MPU6050::setYAccelOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:143: undefined reference to `MPU6050::setZAccelOffset(int)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:150: undefined reference to `MPU6050::setDMPEnabled(bool)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:154: undefined reference to `MPU6050::getIntStatus()'

C:\Users\Paul\AppData\Local\Temp\ccCJUtOe.ltrans0.ltrans.o: In function `processAccelGyro':

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:193: undefined reference to `MPU6050::getIntStatus()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:196: undefined reference to `MPU6050::getFIFOCount()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:202: undefined reference to `MPU6050::resetFIFO()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:214: undefined reference to `MPU6050::getFIFOBytes(unsigned char*, unsigned char)'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:220: undefined reference to `MPU6050::resetFIFO()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:231: undefined reference to `MPU6050::resetFIFO()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:238: undefined reference to `MPU6050::resetFIFO()'

C:\Users\Paul\Dropbox (Personal)\AppData\Arduino\servo_gimbal\FWBCTKRIJD79BCA/FWBCTKRIJD79BCA.ino:245: undefined reference to `MPU6050::resetFIFO()'

collect2.exe: error: ld returned 1 exit status

exit status 1

Error compiling for board Arduino Nano.

0
RaimiN
RaimiN

Reply 2 years ago

did you solve the problem

1
azarias84
azarias84

Reply 2 years ago

im stuck in the same part, somebody can help us?

asdasd.png
0
hbennett-patriot3
hbennett-patriot3

Reply 6 weeks ago

// 2 servo planar stabilization system
// wp
// Jan 2016
//
// Based on Jeff Rowber's work found at
// https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/MPU6050.cpp
//
// Use at your own risk.
//
// This code is placed under the MIT License (MIT)
//
// Copyright (c) 2016 woojay poynter
// Servo Connection
// BROWN - gnd
// red - 5v
// yellow - d10 (pwm on Sero 1)
// - d11 (servo 2)
// MPU Connection
//
// VCC - 5v
// GND - GND
// SCL - A5 (w/ 10k PuR)
// SDA - A4 (w/ 10k PuR)
// INT - D2 (not used)
#include <Servo.h>
#include <I2Cdev.h>
#include <MPU6050_6Axis_MotionApps20.h>
#include <MPU6050.h> // not necessary if using MotionApps include file
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include <Wire.h>
#endif
#define LED_PIN 13
bool blinkState = true;
Servo Servo1; // First Servo off the chassis
Servo Servo2; // Second Servo off the chassis
int Servo1Pos = 0;
int Servo2Pos = 0;
float mpuPitch = 0;
float mpuRoll = 0;
float mpuYaw = 0;
// define MPU instance
MPU6050 mpu; // class default I2C address is 0x68; specific I2C addresses may be passed as a parameter here
// MPU control/status vars
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 ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
// relative ypr[x] usage based on sensor orientation when mounted, e.g. ypr[PITCH]
#define PITCH 1 // defines the position within ypr[x] variable for PITCH; may vary due to sensor orientation when mounted
#define ROLL 2 // defines the position within ypr[x] variable for ROLL; may vary due to sensor orientation when mounted
#define YAW 0 // defines the position within ypr[x] variable for YAW; may vary due to sensor orientation when mounted
// ================================================================
// === INITIAL SETUP ===
// ================================================================
void setup()
{
Servo1.attach(10); // attaches the servo on D11 to the servo object
Servo2.attach(11); // Second servo on D11
delay(50);
Servo1.write(0);// These are command checks to see if the servos work and
Servo2.write(60);// to help w/ the initial installation.
delay(500);// Make sure these movements are clear from the rest of the chassis.
Servo1.write(180);
Servo2.write(120);
delay(500);
Servo1.write(0);
Servo2.write(90);
delay(500);
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// initialize device
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// load and configure the DMP
Serial.println(F("Initializing DMP"));
devStatus = mpu.dmpInitialize();
// INPUT CALIBRATED OFFSETS HERE; SPECIFIC FOR EACH UNIT AND EACH MOUNTING CONFIGURATION!!!!
mpu.setXGyroOffset(118);
mpu.setYGyroOffset(-44);
mpu.setZGyroOffset(337);
mpu.setXAccelOffset(-651);
mpu.setYAccelOffset(670);
mpu.setZAccelOffset(1895);
// make sure it worked (returns 0 if so)
if (devStatus == 0)
{
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP"));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)"));
mpuIntStatus = mpu.getIntStatus();
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
// ERROR!
// 1 = initial memory load failed, 2 = DMP configuration updates failed (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed code = "));
Serial.println(devStatus);
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
} // setup()
// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop(void)
{
processAccelGyro();
} // loop()
// ================================================================
// === PROCESS ACCEL/GYRO IF AVAILABLE ===
// ================================================================
void processAccelGyro()
{
// Get INT_STATUS byte
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024)
{
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
return;
}
if (mpuIntStatus & 0x02) // otherwise continue processing
{
// check for correct available data length
if (fifoCount < packetSize)
return; // fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
fifoCount -= packetSize;
// flush buffer to prevent overflow
mpu.resetFIFO();
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
mpuPitch = ypr[PITCH] * 180 / M_PI;
mpuRoll = ypr[ROLL] * 180 / M_PI;
mpuYaw = ypr[YAW] * 180 / M_PI;
// flush buffer to prevent overflow
mpu.resetFIFO();
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
// flush buffer to prevent overflow
mpu.resetFIFO();
Servo1.write(-mpuPitch + 90);
Servo2.write(mpuRoll + 90);
//delay(10);
// flush buffer to prevent overflow
mpu.resetFIFO();
} // if (mpuIntStatus & 0x02)
} // processAccelGyro()

@Woojay,
This looks like a pretty fun project. I am on the coding part and none of this section of code seems to work: // 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

I get a error when compiling asking if I mean union instead of quaternion.. can you help?

0
jonatasfernan997
jonatasfernan997

4 months ago

Good afternoon, I am trying to do this project, however when downloading the SERVO_w_GYRO_2.ino file it does not open the arduino ide has a flaw and says it cannot load the sketch could post the code again or assist me in how to solve it?

1
sal54ax
sal54ax

11 months ago

Thanks so much for this! I managed to make a little video of the build:

Your link and nickname are mentioned. Cheers!

0
woojay
woojay

Reply 11 months ago

Awesome! Thank you!

0
mati007
mati007

1 year ago

works fine! Thanks
but is speed adjustable?

0
east102tohere
east102tohere

Question 1 year ago

okay, so after downloading the proper library this is coming up
'class MPU6050' has no member named 'dmpInitialize'

any ideas why?

0
johan.frijhof82
johan.frijhof82

1 year ago

Okay, so I tried everything and it seems to be working. The only problem is that it freezes once in a while. The baudrate is set to 115200, as suggested before.

Has anyone ever fixed this?

0
AliA742
AliA742

Tip 1 year ago

you sir are awesome the project works great.
only thing i was having trouble was adding libraries but a google search and was solved.
[https://github.com/jrowberg/i2cdevlib
(downloads\Compressed\i2cdevlib-master\i2cdevlib-master\Arduino) and in it made zip files of two folders [I2Cdev] [MPU6050] and added them in IDE and it worked.]
[connecting the interrupt pin is necessary]

Screenshot (85).png
0
dizzypizzyizzy
dizzypizzyizzy

Question 1 year ago on Introduction

I uploaded the program, on arduino mega 2560, I installed the servo like in the picture, I used MG996R servos, the two servo's tweek at first then servo1(bottom) always position in at maximum left, then it stop. The serial monitor said MPU connection failed.
what can be th problem sir? hoping for your fast response, I'm a student a a beginner in programing,

*update. I managed to make th MPU connection successfull, but all it still does is tweak the servo's at first then stay idle, even if I tilt the gyro..

55576306_401061737358346_1572053077962260480_n.jpg
0
kashyap0071232000
kashyap0071232000

Question 1 year ago

I uploaded the program and it worked but for a few seconds and then it restarts again plz tell me how to fix this

0
woojay
woojay

Answer 1 year ago

Hello, can you tell me if you have pull up resistors connected to the I2C pins? If they are, and if the arduino is restarting, you may have buffer overflowing from the MPU. In the code, you will see a few 'flush' calls that drains the MPU data. You can try to add more flush calls especially if you are doing a of additional work between each loop.

0
blackie99
blackie99

3 years ago

Great project! I used a Nano and the system adjusts for MPU-6050 pitch and roll orientation changes very accurately! Many thanks to Woojay! Next, I would like to control 3 servos - for pitch, roll and yaw. Does anybody have connection and sketch suggestions for three axes?

Gimbal 2 Servo project.jpg
0
LuizL14
LuizL14

Reply 2 years ago

Good night!
Do you use ESP32? TKS!

0
MaazA10
MaazA10

2 years ago

Really helpful, tweaked my arduino UNO and got the damping of both MG995 near to critical with +-0.2 (assumption of analysis) of tolerance (shaking without moving mpu) .... might get more stable by implementing on something useful.
Thanks :)

0
woojay
woojay

Reply 2 years ago

Awesome! That's great to hear!