In 2007, I helped with this other self-balancing scooter build at the MIT Edgerton Center, and since then we've gotten many interesting questions by email about how it works. Baseline self-balancing functionality is actually surprisingly simple, and maybe the purpose of this Instructable is to take this simplicity to the extreme. To that end, I present: Seg...stick.
Segstick is a self-balancing...well, literally some kind of broomstick I found in the MITERS workshop. It is powered directly by two DeWalt cordless drills chucked to two 6" wheels. The controller is an Arduino. Additional supporting devices include an Inertial Measurement Unit (IMU) from Sparkfun and two motor drivers from Pololu.
Is it the best DIY self-balancing vehicle ever? No, not even close. But it only took about two days to build, and it is stripped down to the bare necessities. Thus, I hope to point out the modules and concepts involved in making any self-balancing vehicle rather than the specifics of this one. To start with, some physics...
Remove these ads by
Signing UpStep 1: Physics says it's easier to build a full-size self-balancing thing.
For one, the mechanical time constant of a small self-balancing robot is faster. Imagine the difference between trying to balance a broomstick on your finger and trying to balance a pencil on your finger. The controller for a small robot has to be that much faster to keep up with the physical system.
Additionally, a human rider takes some of the burden off the electronic controller, since the human mind is a pretty good controller too. For example, the accelerometers used on self-balancing platforms can't distinguish between standing still and moving at a constant velocity, but a human rider can. The human rider can adjust by leaning forwards or backwards to speed up or slow down.
So, this Instructable focuses on a full-size vehicle, albeit a relatively small one. In the final step, there are some links to balancing robots.
















































Visit Our Store »
Go Pro Today »




Thanks
-r
Hope that helps!
For the accelerometer, I use a small-angle approximation that says sin(theta) ~ theta, in radians. This is good to within 5% between -30º and 30º. So, to get the angle you need to subtract a "zero" value and then scale by the correct constant.
If you need to work outside of -30º to 30º, the most common method is to take the arctan of two accelerometer axes.
here i got 2 18x25 pololu motor driver but the pins are
TIXN
ERR
RST
TX
RX
VIN
GND
instead of
V+
5V
FF2
FF1
RESET
PWM
DIR
as shown in your 18x25 motor driver
so plz tell me what r the PWM & DIR pin in my motor driver.
On the controller, you should be able to use the RC interface (pins labeled RC1 and RC2) and the Arduino servo library to command the motors.
A picture would be nice...
thanks
To attach, I used screws from the board into the heat sink. I put a couple of layers of Kapton tape between the board and the sink to insulate it.
after a little bit of thought, I am thinking of taking the fan off an old PC CPU heat-sink and just suspending it with 4 standoffs above both Pololu controllers but without a heat sink or mechanical contact point. This should be better than nothing I hope...
Your schematic shows A0 - A5 of the arduino connected to the Razor 6D0F but your code only uses A0 for the accelerometer input and A4 for the gyro input.
Is it necessary to connect the other Razor 6D0F outputs (A1 - A3 & A5) to the arduino and if so why?
(I might want to use those analog inputs for other things...)
thanks
I'm working on making a small robot balance, you can see my first attempt in this blog post:
http://makerandomstuff.blogspot.com/2011/12/introduction-fail-way-crappy-balancing.html
I've tweaked the platform a bit to make things neater but I'm still having trouble balancing.
The sensors from the Wii Motion Plus (gyros) and Wii Nunchuck (accelerometers) are outputting data over I2C and I'm filtering it to get g_roll, a_roll, and a filtered angle, so I think that part's good.
When I try to have my robot balance, it either oscillates a lot, or responds too slowly. I think the problem lies in my Kp/Kd values, my motor responsiveness, or my robot's small size (or a combination of 2 or more).
Any suggestions?
The sensors are inertial, meaning they respond to acceleration. They can't distinguish between standing still and moving with a constant velocity. So, even when tuned properly, the robot segway can't really stand still by itself. It will either oscillate (if the gains are high) or stay near vertical but drift off in one direction until the motors can't keep up, at which point it falls over.
A human rider can sense that the segway is drifting off in one direction and correct by leaning forwards or backwards to bring it back to zero speed. To mimic this, the controller would need to know the velocity (maybe from wheel encoders) and control it to be zero. This adds extra states to the control system and makes it more complicated. I attempted an autonomous balancing robot with no encoders with moderate success here:
http://scolton.blogspot.com/2011/05/mini-segstick-my-mid-quals-crisis-robot.html
Others have definitely done it with success. There are a few links to robot segways in the last step of the Instructable. Another option is to use radio control to guide it as a human rider would, preventing it from building up too much velocity when it should be standing still. Here's an example of that solution in action:
http://machinescience.wordpress.com/2011/11/29/ps2-module-controls-two-wheeled-balancing-robot/
I've gotten my hands on a cheap nunchuck clone so I'll be updating the sensor system soon, and maybe making things a bit more solid.
I also have some motors with quadrature encoders built in (9v LEGO NXT motors) so maybe I'll go somewhere with that. Is there any chance I could take a look at the code you used for your mini-segstick? Maybe I can integrate encoders with that strategy.
I still can not stabilize my Segway. Also, I had a problem with my IMU and the gyro stopped working, so I had to use another one. The gyro I had at hand is an Epson XV-3500 (http://www.epson-electronics.de/upload/PresidioIndustries/product/QuartzCrystalDevices/Sensors/GyroSensor/XV-3500CB_710020500_data.pdf) whose sensitivity is 0.67 mV / deg / sec. My accelerometer is the ADXL335. I'm supplying 3.3V.
The calculation bellow is correct?
Accelerometer (ADXL-335):
(57.3 ° / 0.3V) * (5V/1024LSB) = 0.932 ° / LSB
Gyroscope (XV-3500):
[(1 / s) / 0.00067V] * (5V/1024LSB) = 7.287 (° / s) / LSB (?????)
The value for the gyroscope seems very high and the Segway completly unstable.
Kind regards,
Marcos
Sensitivity: 0.67mV/(deg/s)
Range: +/-100(deg/s)
and that thus the voltage range is only +/-60.7mV, full scale?
If so, this sensitivity may not be suitable for use with the Arduino's ADC (at 5V or 3.3V reference). The signal might be just too small to get useful information out of. Even the Sparkfun Razer IMU gyro is cutting it close in terms of the available resolution, given the low angular rates typical on a balancing platform. (Under normal operation, 10-20(deg/s) might be the maximum rate.)
I think not because this project (http://diysegway.blogspot.com/) uses the same sensor and works very well (really stable). I would like to test the Trevor algoritm. The angle and the angle_rate are the tilt angle of the scooter in radians and its derivative in radians/sec. Is it the same that are in your code (rate and angle)? So, can I use the bellow code together your code? Are in same unit system?
Thanks for your help, I'm learning a lot!
balance_torque = 5.0 * (angle - rest_angle) + 0.4 * angle_rate;
overspeed = max(0, cur_speed - 0.5) ;
if (overspeed > 0) {
overspeed_integral = min(0.4, overspeed_integral + min(0.2, overspeed+0.05) * dt) ;
}
else {
overspeed_integral = max(0, overspeed_integral - 0.04*dt);
}
rest_angle = 0.4*overspeed + 0.7*overspeed_integral;
steer_cmd = 0.07/(0.3+abs(cur_speed)) * steer_knob;
cur_speed += 1.2 * balance_torque * dt;
left_motor_pwm = balance_torque + cur_speed + steer_cmd;
right_motor_pwm = balance_torque + cur_speed - steer_cmd;
In that application, they are using a sparkfun razor gyro & accelerometer which is connected to the 3.3v just as it is in Scolton's instructible but what is different is they tie the 3.3v line on the arduino to the Aref pin an then use the following command in the setup section of the code:
analogreference(EXTERNAL);
Here is the explanation:
the normal range for the 10 bit ADC (pins A0-A5) is 0 - 1023, where 0vDC input yields a value of 0 and 5vDC yields a value of 1023. If you plug a 3.3v sensor into an arduino analog input, the maximum value that an arduino can read is approximately 675 or so. (3.3v / 5v *1023), to get full range using a 3.3v device, you must connect the desied reference volage (3,3v) to the analog reference pin (aref) an add a line of code to the end of the setup() function to tell the arduino to use an external analog reference voltage.
I haven't tried it yet but this might smotthen things out as mine has been vey sporatic...
If you get a chance to try this before I do, please report back waht you find.
thanks
My MSN is marquinho-a [at] hotmail [dot] com, and my Gtalk is marcospassos.com [at] gmail [dot] com. You can add me and talk more to share experiences.
Kind regards,
Marcos
I'm using a Sparkfun 5 DOF, OSMC controller and two 450w 24v motors (MY1018z). Although my Segway can balance itself, it can't balance a person (seems to have no force, slowly). I've noticed my Gyro (IDG-500) has
2 mV/°/s of sensivity, so my LSB is [(1º/s)/0.002V]*(5V/1024LSB) = 2.4140625(º/s)/LSB, right? Anyway, it can't balance as well.
I also have noticed that over time the platform starts to get steep and considers it as level.
Do you have any tip?
Thanks,
Marcos
(Of course, that's for a very light platform like segstick. The more the platform weight becomes significant compared tot he total weight, the closer the gains should be for rider and no-rider.)
The best place to put the sensors is in the center of the horizontal platform, as close as possible to the axle line. They should be shock.mounted to prevent mechanical vibration from affecting the MEMS sensors.
Even with the correct angle, it is difficult to get the platform to stay balanced by itself. None of the full-size balancing platforms I've built can do this. The problem is that the sensors are measuring inertial effects, like acceleration. They have no way of knowing the difference between standing still and moving at a constant velocity. So it may be balancing, but it will pick one direction and move until it hits something. To get it to stand in one place, additional code is required that either uses a direct measurement or an estimate of the speed of the wheels. I made a mini self-balancing robot that attempted to solve this problem by very roughly estimating the back EMF of the motors:
http://scolton.blogspot.com/search/label/segstick
It worked okay, but wheel encoders would make it much better.
[(1º/s)/0.00333V]*(5V/1024LSB) = 1.466(º/s)/LSB
I know that my LSB variable would be different but what should it be with 16-bit res and is it even worth it or does it matter?
My DIY segway for some reason runs slower using my ATmega1280(mega) than it did using the ATmega328(Duelmanove)in terms of corrections for it's angle, and corrections for it's angular rate.
I'm adjusting KP and KD in realtime with pots and it seems to help a little but it just isn't like it used to be. I also now have a quick dead spot right when the motors change direction. Not sure if these two symptoms are related but any suggestions would help. Thanks for all your work.
Not sure about the daed spot. Do you think it's mechanical? Both the DIY segways I've worked on have had enough mechanical backlash to make changing directions a pain.
I figured out the dead spot as I am using OSMC motor controllers which require four inputs and one of mine was off.
Unfortunately I fried the right osmc last night but will try the LSB change when I re-solder some new transistors on the motor controller.
http://web.me.com/jaysettle/Jay/diy_segway.html
Hi Scolton, congratulation for the good job! I'm using a Sparkfun 5DOF IMU (http://www.sparkfun.com/products/9268) and I'm trying get working but the out of output_right or output_left they always are increasing to 255 even when is stabilized horizontally. Do you have any idea what can be?
I have observed the IMU values and this one never stabilizes. The acc_x, for example, is always a random value between 310 and 315. So, even if I have adjusted the a_zero the value of acc_x oscillates.
output_left:
0, -1, -2, -2, -3, -3, -4, -5, -6, -6, -7, -8, -9, -10, -11, -12, -13, -13, -14, -15, -16, -16, -17, -18, -18, -19, -20, -21, -22, -23, -24, -25, -25, -26, -27, -27, -28, -29, -29, -30, -31, -32, -33, -34, -35, -36, -37, -37, -38, -39, -40, -41, -41, -42, -43, -44, -45, -46, -47, -48, -50, -51, -51, -52, -53, -54, -55, -55, -56, -57, -59, -60, -61, -63, -64, -65, -67, -68, -69, -70, -72, -73, -74, -76, -77, -79, -80, -81, -83, -84, -85, -87, -88, -90, -91, -93, -94, -95, -96, -98, -99, -101, -103, -104, -105, -107, -108, -108, -110, -111, -112, -113, -114, -115, -117, -118, -119, -121, -122, -123, -125, -126, -127, -129, -130, -132, -133, -135, -136, -138, -139, -140, -142, -143, -144, -146, -147, -149, -150, -152, -153, -154, -155, -157, -159, -159, -161, -162, -163, -164, -165, -166, -167, -168, -170, -171, -172, -173, -174, -175, -176, -177, -178, -179, -180, -181, -183, -184, -185, -187, -188, -189, -191, -192, -193, -195, -196, -198, -199, -200, -201, -202, -204, -205, -206, -207, -208, -208, -209, -210, -211, -211, -212, -213, -214, -215, -216, -217, -218, -219, -220, -221, -222, -223, -224, -224, -226, -227, -228, -229, -230, -231, -232, -233, -234, -235, -236, -237, -238, -239, -240, -241, -242, -243, -244, -245, -246, -247, -248, -248, -249, -250, -251, -252, -253, -254, -254, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255, -255...
Regards,
Marcos