Gyro Stabilizer W/ Arduino and Servo

60,628

105

64

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.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

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

6 People Made This Project!

Recommendations

  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

64 Discussions

None
east102tohere

Question 21 days ago

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

any ideas why?

None
johan.frijhof82

2 months 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?

None
AliA742

Tip 5 months 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
None
dizzypizzyizzy

Question 6 months 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
None
kashyap0071232000

Question 7 months 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

1 answer
None
woojaykashyap0071232000

Answer 6 months 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.

None
blackie99

2 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
1 reply
None
MaazA10

9 months 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 :)

1 reply
None
woojayMaazA10

Reply 9 months ago

Awesome! That's great to hear!

None
NuklearNadal

Question 1 year ago on Introduction

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 answer
None
woojayNuklearNadal

Answer 1 year ago

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.

None
paul.sneed.39

2 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.

2 replies
None
azarias84RaimiN

Reply 1 year ago

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

asdasd.png
None
myless8

2 years ago

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?

1 reply