Balancing cube

This cube can balance on its corner using three orthogonally mounted reaction wheels

This cube manages to balance itself on a corner, and can simultaneously rotate around its axis in a controlled manner. It does so using clever controls and a set of three reaction wheels.

The original idea for this device comes from researchers at ETH Zürich, who demonstrate their “Cubli” in this video. Its design has been improved in some ways in later years. Notably, Bobrow et al (University of São Paulo) introduce an improved controls concept, reducing the number of required IMUs (inertial measurement units) to just one instead of six.

I decided to pursue the challenge of building one myself. Even though the idea isn’t new, previous works are largely closed-source. I plan to change that. This means that I had to reverse-engineer and draw everything from scratch. The result of my work, which is completely open source (GitHub), is shown in the video below.

You might think: ANOTHER USELESS MACHINE?! When I published my M&Ms sorting machine, I received lots of similar remarks. Indeed, it has no practical value, but similar applications such as sorting of fruits, vegetables and nuts based on colour do. For this cube, the situation is similar: while this is mostly a great learning experience and research project, reaction wheels are often used in satellites (such as the James Webb telescope) for attitude control purposes.

A spacebound reaction wheel. Source: Wikipedia.

Mechanical design

The mechanical design of this cube is mostly the same as that of the original Cubli, but it has some subtle differences. The main structure consists of eight “cornerstones” and six face plates. Three of these face plates have additional features to support a motor and reaction wheel assembly. All parts were drawn in (con)Fusion 360. My student days are over, so I had to say farewell to Siemens NX. The latter isn’t used much (if at all?) in the DIY community anyway, so I can share my designs with others more easily now.

Most structural parts are made of stainless steel for its excellent strength. The faceplates are made of aluminium to save weight. These don’t need to be made of steel since the assembled structure will be more than stiff enough when made of aluminium anyway.

All metal parts in this project have been manufactured by PCBWay. I’ve used their PCB prototyping service before and was interested in their CNC capabilities. Part of the cost for these parts was sponsored by PCBWay. The ordering process was straightforward and I like that a quote was automatically calculated directly after uploading the part and specifying the material type. I’m satisfied with the parts and their quality: a small production issue was quickly resolved and all parts fit together without issue. Pictures below: judge for yourself.

I had fun with the design of the motor and flywheel assembly. I was looking for a robust design – after all, the wheels can reach speeds up to 6000 rounds per minute – while also keeping it lightweight. Even though I’m a mechanical engineer by education, construction principles aren’t my main strength, but after all that’s the reason for projects like these: to learn! I finally came up with the following.

The motor is connected to a stainless steel bridge using three countersunk screws. The bridge eventually connects to one of the aluminium faceplates.

A small hub is mounted onto the shaft of the motor and secured using three set screws. This hub is critical: if the center hole is not perpendicular with respect to the flat triangular face, the wheel will not be aligned with the motor shaft, causing vibrations and wear.

A reaction wheel is mounted onto the hub using three countersunk screws. This step requires a bit of trial and error to correct for imperfections in the hub and wheel, which may cause the misalignments I mentioned earlier. I resolve these by placing tiny pieces of paper between the horizontal contact surface of the hub and wheel and this provides satisfactory results. After all, these parts aren’t taken apart very often.

A small radial ball bearing is inserted into one of the faceplates and secured using cyanoacrylate (“super”) glue. This ball bearing will support one end of the motor shaft. The other end of the shaft is also supported by a bearing within the motor itself.

Finally, the motor shaft is inserted into the bearing and the bridge is connected to the faceplate using four bolts. This process is repeated two more times.

This result in half a cube. The remaining faceplates don’t require any special assembly steps and can be directly assembled. Notice how one of the motors is oriented differently with respect to the bridge to which it attaches? That is done on purpose: it simplifies the cabling work later on.

The result is a strong yet relatively lightweight structure. The aluminium faceplates are relatively weak by themselves, but won’t budge when assembled together.

Electromechanical design

For the motor and motor controllers, other balancing cubes use Maxon motors from the “EC flat” series. While it’s possible to find cheaper alternatives, the motors and their controllers are critical parts and I don’t want to skimp on them. The cube will balance by applying torques to the motors. Many DC motors do not even come with datasheets that specify the torque constant (which defines the relationship between torque and current), and many brushless motor controllers such as ESCs only offer speed control, but not current control. Both are essential in making this project a reality, so the choice for components of high quality is obvious here.

I selected a 60 W motor and a compatible 4-quadrant motor controller which can deliver currents up to 6 A. At 24 V, this corresponds to almost 150 W. While this is well beyond the nominal power rating of the motor, it is no problem to briefly overload the motor. Moreover, the controller has a built-in I2t algorithm which limits current to the motor if the winding temperature is estimated to become too high. It is unlikely that the cube hits these limits in normal operation anyway, because currents are generally very low while balancing.

The software that comes with the Escon motor controllers is pretty great. There are motor commissioning and tuning tools and a nice dashboard showing the status of the motor and its inputs/outputs during operation (shown in the screenshot above).

For the battery, I chose a 6S1P lithium-polymer battery. The motors are rated for 24 V so a six-cell LiPo battery (nominal voltage 22.2 V) is a good fit here. The battery has a capacity of 1300 mAh (29 Wh) which is enough to run the cube for at least an hour, normally.

The motherboard is a custom design and integrates the three motor controllers, IMU (hidden), ESP32-S3 development board, and some supporting components such as protection circuits and voltage regulators. The board also anticipates adding mechanical brakes to the cube, by providing outputs for RC servo motors. Mechanical brakes will enable the cube to jump up to the balancing position by itself. I haven’t finished the development of the brake design yet.

Assembling the circuit board was fun. I started by applying solder paste and placing the surface-mount parts. After reflowing it in a small toaster oven (more details about how this works here), I soldered all the through hole parts by hand.

Later, during integration and testing of the various components, I found that I had made a few small routing errors which I quickly corrected using bodge wires. It turns out that only one digital input on the motor controller supports PWM and I routed the PWM signal to another (unsupported) input.

I also designed a board to mount the battery onto. It’s much simpler: it has two XT60 connectors and two switches (wired in parallel because of currents up to 18 A) to turn the cube on and off.

Controller design and tuning

I didn’t actually design the controller the cube myself, but ported the work by Fabio Bobrow from Arm Mbed to Arduino. I’m also using an ESP32 instead of an STM32 Nucleo. Nevertheless, rewriting the code was a good chunk of work. Also, since I’m using a different IMU (the ICM20948 by TDK Invensense), I had to rewrite the corresponding “driver”. I still spent quite some time studying the design of this controller and will spend a few words to highlight some nice things about it.

The design of the main attitude controller is most interesting. It is perhaps best explained as a negotation between two contradictory objectives. The first objective is to keep the cube in its desired orientation, that is, at its unstable equilibrium position. A second goal, however, is to keep the wheel velocities to a minimum. Not considering this second objective could lead to wheels speeds getting out of control, saturing the motors, and thereby effectively rendering it unable to exert torques on the cube.

The two objectives are in conflict: if the ‘desire’ to keep wheel velocities close to zero is too great, the cube simply falls over. Like mentioned before, if it is too weak, the wheels might literally spin out of control. The trick therefore is to find gains that result in good balancing performance and disturbance rejection while keeping wheel velocities somewhat low.

There is another elegant mechanism in the controller to deal with constant errors. What are constant errors? For example, there might be a small difference between the configured equilibrium position and the actual equilibrium due to imperfections in the weight distributions of the cube. In a PID (proportional-integral-derivative) controller, the integral part deals with these kinds of errors. This controller uses the position (in degrees) of the wheel as the integral! In my opinion, this is actually a very intuitive way of visualizing an integral controller. When I modify the weight distribution of the cube (in the video: by placing a tomato on it), you can see the reaction wheels increase and then decrease in speed: they are moving to a new position to compensate for the increased error!

Commissioning and tuning the controller was, by far, the largest piece of code-related work. Like any experienced controls engineer, I spent a few days flipping the signs of various signals before I got them right. Then, I had to find the right gains for the controller. The tuning methodology as described in Bobrow’s dissertation didn’t work for me, so I resorted to tuning the gains by hand. Note that my cube uses different wheels compared to Bobrow’s cube, so reusing the gains was not possible. Using an iterative procedure, I finally obtained the gains that result in the stabilizing performance as shown in the video (which is very good, in my humble opinion).

That’s it! A balancing cube. It’s the only fully open-source cube in the world which achieves a balancing performance similar to that of Cubli, as far as I know. I hope that others will now also be inspired to build this cool device.

Here are some links to similar cubes which are at least somewhat documented (more than just a video or photo):

Next steps: jumping up

I plan to add mechanical brakes to the reaction wheels. These will enable the wheels to be braked rapidly, resulting in much larger torques than the motors can deliver. This enables jump-up manoeuvers which in turn enable the cube to get to its equilibrium position on its own. This feature is currently unique to the original Cubli, as far as I know. I don’t particularly like the braking mechanism that Cubli uses for various reasons, so I’m going to use a different approach. I’ll share results in a future post!

Thanks for reading.

Source files and documents

You can find all design, configuration and code files related to this project in this project’s GitHub repository. Feel free to reach out if you have questions about the project or want to build your own. In my case, the BOM was close to €2500, so be prepared for that.

34 comments

  1. I can’t afford to build one myself to test, but what would it do if it’s suspended in water (say, in a waterproof container such that the whole thing is neutrally buoyant) or during free fall?

    1. The control algorithm relies on the presence of earth’s gravity to determine its attitude so it would probably go crazy in freefall. In water, I theoretically don’t see that issue.

      Reaction wheels are used for attitude control in spacecraft, but the algorithms used are very different due to this lack of gravity as a reference.

  2. Great, I like it!

    > the BOM was close to €2500

    Wondering, what are the expensive parts? Seems the manufacturing of the steel frames contribute the largest part?

    1. The motors and motor controllers together are worth €1000. The machined metal parts together are also close to €1000. The remainder (PCB manufacturing, electronics, battery, cables, bearings) make up the remainder.

      The large frame pieces are made of aluminium and are relatively cheap when compared to the stainless steel parts such as the reaction wheels. Steel is generally more difficult to machine (increased tool wear, takes longer, etc).

      1. Hey Willem,

        Awesome project.

        Maybe you can get the price down, with more FPV Drone parts, as you already have a Battery, you are probably aware?

        A Flight Controller, ESC and Motors should be available for around 200 $. Technically that should work? Should even allow for the break performance. Maybe you don’t even need the hall, RPM measuring.

        Just thoughts, don’t have any practical experience.

        Love it, i want one!

        Induction charging via one or all corners would be cool.

        1. Very unlikely, unfortunately. Drone motors have way much RPM and way too little torque, plus they are designed to spin in only one direction. Also the cheap ESCs are not designed for rapid direction and torque changes this project needs.

          The Hall sensors are not for measuring RPM but required to actually get (and keep) the motor spinning at the low speeds this project requires. Drone motors can use back-EMF measurement but that doesn’t work when the motor is spinning slowly – the back-EMF is way too small and noisy to be useful for actually commutating the motor. That’s why slow spinning BLDC motors always have sensors of some kind – Hall sensors, position encoders, etc. to let the controller know where the rotor is.

          Induction charging also wouldn’t really work due to all that metal creating a shorted turn and also because it would take eternity to charge. It is a very inefficient way of delivering power that barely works for charging small electronics like phones. Not something with a beefy battery driving 3 large motors.

          The only way to save money here would be going for cheaper Chinese motors – but even those cost about 100€/piece, so you may save maybe half of the cost at the expense of buying a cat in the bag that may or may not work for what you need.

  3. Fantastic work and engineering! I just glanced at your other projects – may be in future a hybrid of this balancing cube and LED cube displaying patterns/images and reacting to changes in orientation… ;^)

  4. This is awesome, thank you for building, inspiring and sharing. Despite the high price, I look forward to building this myself slowly.

  5. Impressive work! Just wondering… if you had another similar cube would they be able to balance themselves if placed one on top the other (corner wise).

  6. This is pretty amazing, thank you for sharing! I will try to replicate this with a 3D printer and non metal parts (and a lot uglier propably) to see if a budget version is feasable

  7. So would 3d printing the frame be out of the question? That would be a good start with getting the cost down.

  8. Curious if it would be worth considering 3D printed (PETGCF) frame pieces instead of stainless and aluminum. That should cut the weight down to about half of aluminum…

    1. That should be possible. Alternatively, lasercutting from acrylic or a similar plastic could also be a cheaper alternative. Not sure how that would compare to 3D printing.

  9. Hi, very nice. I wonder if you couldn’t put an inductive charging coil at the balance point and balance the cube on an inductive charger to allow “in-flight” charging.

  10. Great job! It’s fantastic that you’ve decided to share your process with everyone. I’m always grateful when people give back to the community, especially after benefiting from the open sharing of others.

    About the aluminum frame, did it have to be metal, or could it have been 3D printed in ABS instead?
    Additionally, do you think there’s a way to reduce costs on certain components without significantly compromising performance?

    On a different note, what equipment do you use for photography? The picture quality is outstanding.

  11. Hello Willem,
    I’m a hardware engineer and looked at your balanced cube and loved it. So I got my hands on it based on your open source material, I reproduced your cube including everything, but I found a problem that I have no solution for.
    1> Having burned your code, the cube can achieve dynamic balance at startup (holds on for about 7~8 seconds), and when it wants to achieve static balance for rotation it falls over.
    2> I tried to modify the parameters inside your parameter.h and found that I can achieve occasional balancing (one out of 20 times succeeds), but with the slightest disturbance it falls over.
    3>What is the purpose of the accelerometer-calibration file inside your profile, and should the parameters of the gyroscope be calibrated. Since I am reproducing your work, I didn’t modify it.
    In response to the above question for the first case how should I adjust the parameters and what parameters should I modify. I hope you see this message can help me to solve my problem, love your work, thanks!

    1. Hello, you will have to verify a few things step by step before you can get the cube to balance. Did you successfully calibrate the gyroscope and accelerometer using the program and application note provided? Did you verify that when you actuate a motor, the correct one rotates in the expected direction? Did you also check whether the measured speeds are as expected when the motors rotate in a certain direction? The current software briefly spins the X, Y, and Z motors in positive (counterclockwise) direction during startup of program, so you can already verify by just looking at that whether your motor mapping is correct. In the end, everything should be defined such that your definitions are according to those in this paper (Figure 2). Motors 1, 2, and 3 in the code and paper correspond to the X, Y, and Z axes, respectively.

      1. Can you elaborate a bit more on what changes need to be made to the code for the different corner / edge cases? It seems like both a quaternion block needs to be uncommented and also the .generate() method needs to be uncommented.

        For the accelerometer calibration, I see that we’re supposed to calibrate all 6 sides but…where do those 6 values. I only see terms like b_acc_x and b_gyr_x in parameters.h, but that doesn’t seem sufficient

        1. Hello Chris, regarding the accelerometer calibration process I recommand to initially use the values that I provide. Of course, this is not perfect, but pretty close. If you want to do it properly, check out the page that I link in the accelerometer calibration sketch. It provides all formulae and procedures.

          To balance on an edge instead of a corner, you would indeed comment out the generate() method since the cube cannot pivot on an edge. You are also on the right track regarding the quaternions: the one that is defined by default is not commented out in the parameter file. If you comment it out and uncomment one of the edge orientation quaternions, the cube will balance on that edge instead of the corner.

          Hope this helps!

  12. The fact that you have the skills to develop the mechanics, the electronics, the software and the control theory part (the controller) all together is truly more than impressive, it’s exceptional and, being a maker myself, I take my hat off for you. Plain and simple.
    Best regards
    Vriendelijke groet
    Herwig

Leave a comment

Your email address will not be published. Required fields are marked *