Gyro Stabilizer W/ Arduino and Servo

47,628

94

56

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.

6 People Made This Project!

Recommendations

  • Metalworking Contest

    Metalworking Contest
  • Water Contest

    Water Contest
  • Fix It! Contest

    Fix It! Contest

56 Discussions

Hi,
Great project, but i have problem with it i use arduino uno, and when i start program it writes mpu failed to connect and arduino external interupt 0 and fifo overflow can you help me

1 more answer

Sorry it's been a while. If it keeps overflowing, you can try to flush the data stream more often than I do. You'll notice that I send a 'flush' command once in a while, and you can try to dump data frequently to reduce overflowing. Hope that helps.

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.

2 replies

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

asdasd.png

This is an awesome tutorial. Question:
Which libraries are needed to run these?
I see the following:
Servo.h
I2Cdev.h
MPU6050_6Axis_MotionApps20.h
MPU6050.h (if relevant)

I know, though, that different people write similar, but not necessarily compatible libraries. Which are the ones, specifically, I should get?

2 replies

did you solve the problem

No, I failed to ever follow through on this project and the questions I had with it.

why is it showing me compilation error in arduino.ide

2 replies

Download libraries from this link and try again

https://github.com/Isaranu/diy-servo-gimbal

after download that it still show the error...it say couldn't find the library so where should I place the file?

hello

i'm using the mpu6050 with a mega ADK, and somehow when i ran the code and using the serial monitor, it always ends up in
"Enabling interrupt detection (Arduino external interrupt 0)"
or
"FIFO OVERFLOW"

did the code doesnt work with an ADK or what? thank you

Works great! just downloaded the coad , did not re flash the mpu or anything! only with current arduino uno i had to use pin DIGITAL 2 and 3 for outputs for servo's :) Thanks! also used the 3.3V from the arduino for the mpu and 5V for servo's straight from the powersupply not the arduino :)

My servos didn't moved (my servos are fine, indeed i see the dance)

in serial monitor it only said "Initializing I2C devices..." the "Testing device connections..." won't appear and so the next message :(

did i do something wrong ?(i followed exactly your instructable, except for the power source)

oo yeah i almost forget to mention, i used uno w/ usb power source. At this point i started to think i dont have enough power, is that true?

many thanks btw, i can use ur code as refence :)

2 replies

I FOUND THE PROBLEM

so i got rid of the pull-up resistor and foila.

my question is, BUT WHY :/

Worked for me as well. Thanx.

very very impressive project.