In an attempt to make a stabilizing platform without too much hassle, i recently bought some phidgets.
As far as a quick test goes, the idea is simple - having an accelerometer move a servo. The fact that the APIs are ridiculously easy to use (don't need to write your own firmware, analog to digital converters, drivers, etc.), makes this task pretty simple.
The finality of the project will consist in being able to stabilize a surface on 2 axes, using 2 servos. I'll follow up on this post when the project is done.
For now, i wanted to see if i can control the movement of a servo based on the tilt registered by the accelerometer. This is in itself trivial.
However, suppose you'd want to stabilize a plane surface on 1 axis, with 1 servo. The 'level' position (when the accelerometer measures an acceleration of 0 on the specified axis), needs to be in the middle of the servo's range, because you should be able to tilt the plane in both directions, while attempting to keep it level.
The servo motor is extremely cheap, and it doesn't seem to have a 180 degrees range, which is fine. You still have to know its exact limits though.
For this, you use the phidgets servo interface application, and find out how far you can go with the position, before the servo starts to shutter and make funny noises.
The one i had worked fine between position 30 and 225, which means the middle position is the mean of the two. This is where we want to keep the servo when we're leveled, and at this exact position the blue line and the red line in the following picture should be parallel.
In the picture below, the red line is level, and the grey cross represent the servo's 4 'blades' ; one blade is marked to be able to tell the blades apart. Assume the blue line is a plane surface attached to the blade. As the servo moves, the plane is tilted. So the level position would be when the blue line and the red line are parallel, at servo position (min+max)/2 (assuming the servo is positioned properly, which should be easy to do in your project).
All this means it's a little more to it than simply passing the tilt angle to the servo directly; our reference point is the middle of the servo range, which means that for negative tilt angles we have to subtract from the level position, and for positive angles we have to add to the level position, so that the servo tilts our imaginary plane surface right or left, if you're looking at the picture above. The 90 degrees angle is also a reference point.
The next requirement is calculating (basic trigonometry, phidgets accelerometer documentation contains a decent explanation and a pretty picture) the tilt angle: arcsin(acceleration). The result will be in radians, so we should convert to degrees, with the help of your language's math library or by doing it yourself (degrees = radians*180/pi).
Because we're using an accelerometer to get tilt, readings out of the [-1;1] range will be ignored.
Also, because all the different types of servos, you might need to adjust the final value; this can be easily done via experiments.
/
The relevant Python code is the AccelerometerAccelerationChanged event:
def AccelerometerAccelerationChanged(e):
if (e.acceleration >= -1 or e.acceleration <= 1) and e.index == 0:
print e.acceleration
deg = math.degrees(math.asin(e.acceleration))
print "Deg: %f | Acc: %f" % (deg, e.acceleration)
#asv is the servo object
#setPosition takes 2 parameters - servo motor index, and position
if deg < 0:
#because we can't go to a negative position, we also multiply by -1
asv.setPosition(0, (min+max)/2-deg*(-1)*((min+max)/2)/90)
else:
asv.setPosition(0, (min+max)/2+deg*((min+max)/2)/90)
The accelerometer sensitivity is set to 0.02, which means it will only trigger the event if the acceleration changes by more than 0.02g, which is about 1.146 degrees of tilt.
This short clip (AVI, 888.5KiB) shows everything in action (notice the top blade of the servo has a pinkish dot - that's where the blue plane surface would be attached).
To make things more smooth you could sample the accelerations and act on say the mean of 2 successive events, use a gearbox for the servo (the code would need a bit of adjustments for that), get a more expensive and precise servo, etc.