Self-Leveling Table

I started this project after I graduated from Berkeley.  I wanted to see if I could make a self-leveling table with an Arduino and spare servos that I had from our capstone project.

The original premise was to have 4 servos (2 sets of opposing servos) to balance a table on 2 axes.  I am currently still working on settling a design and figuring out the geometry of the servos as the table rotates (it is harder/more complex than I had originally assumed).  I will update this page as I create new designs or reach new milestones.

Quick Jump
Design 1
Design 2
Design 3
Functional Build

Design 1: 4 Servos With 8 Ball Links

This was my first major design and fully “functional” SolidWorks model.  I modeled the servos and ball links to scale from measurements I made on the components.  As can be seen in the video, the table had too much freedom to yaw and elevate, which would make controlling the table’s angle impossible to control.

At this point, you can see that in order to rotate the table about its centroid, opposing servos did not rotate as inverses of each other.  After doing the geometry by hand, I found these two curves for servo angles versus table angle:


This came as an absolute surprise to me that the servos would not just rotate as inverses of each other.

Back to top

Design 2: 4 Servos With 4 Ball Links and 2 “Elbow” Hinges

To reduce the inaccuracy of the previous design, I replaced the connections at the servo horns with 1-DOF connections.  This eliminated the yaw and elevation problems seen in the first design.

The above two videos show the same motion, with the second video showing the actual connection at the servo horn.  The desired rotation of the table was achieved, except this design was too rigid.  Having the 1-DOF hinges at the servo horns prevented the table from tilting in both axes at the same time.

Back to top

Design 3: 3 Servos

After trying multiple configurations of hinges, I found that it is very unlikely that there is a solution that will allow the table to rotate about 2 axes that are both through the centroid of the tabletop while using 4 servos in the current setup.

I determined that removing 1 servo and replacing it with a stationary post (with a ball link) would allow the desired rotations, except one axis of rotation would not be through the centroid of the table.

This short animation shows the axis of rotation that does not coincide with the centroid, but is possible.  The two servos that share an axis going into the view plane in that video (the two in the middle of this animation) need to rotate as the servo on the right rotates.  This required more geometry done by hand, which I solved and plotted the angles below.

3Servo curves


I ran the numbers on what varying the connector arm length and the length of the servo horn do to the total table rotation.

This first graph shows the table angles with varying connector lengths (represented as “l”).  The graph shows that the total table angle range is pretty much identical between all connector lengths, it’s just the center angle that changes.



This second graph shows the table angles with varying servo horn lengths (represented as “h”).  The graph shows that the total table angle range is increased as the servo arm length increases.  This is a great discovery, except I am limited by the servo horns that came with the servo, so I’m limited in this sense.



I cut the wood and assembled everything.  I also created a basic sketch on the Arduino to read the table angle and actuate the servos.  Right now I am only using a proportional controller to make sure that everything works.  This video shows the fully assembled table working (mostly) as intended.  There is a slight yaw problem due to the hinge (on the right-most servo at the start). wobbling and torquing the servo horn.  The table only has a ~15 degree total range due to having such a small servo horn length.  I have larger servo horns (almost 2x as long) but they are for different, continuous servos that I have.  I may create a second version of the table that uses these larger servos for a better table rotation range.


I crunched the numbers for the angle required of the two side servos in relation to both table rotation angles (x and y axes). This gave a 3D surface of servo rotation angles. I did the calculations in MATLAB and have graphs of the surfaces shown below from a few different perspectives. I was going to try fitting a simplified 3D surface to the results I got out of MATLAB, but my version of MATLAB does not have the “cftool” that would help me fit the data, and my knowledge of 3D surface equations is not this complex. Since this is the case, I will try to optimize my MATLAB code and convert/export it to C++ for Arduino.


side servos 3d3


Isometric view of servo angle surface.


side servos 3d5


Top-down view of the servo angle surface.Side view of the servo angle surface.

These equations use the angle of tilt between the table top and the base.  In order to enact this architecture, I had to move the accelerometer from the tabletop itself down to the base.  This way, the servos could use the table angle determined by the accelerometer to move the tabletop to a level position.  The problem with this setup is the fact that now there is no direct feedback of the tabletop angle, which can introduce more error in the steady-state table position than if the servo is directly on the table top.  This would be easy to solve if I had a second accelerometer, but I do not.


I finally finished debugging and perfecting the Arduino code and the table is fully functional!  The table works on both axes and stays within 1-2 degrees of level.  There are still a few annoying problems with the servo horns flexing, causing the table to yaw, but this can be combatted with more rigid servo arms and connections.

Back to top