Tesseract - Rubik's Cube Robot
Rubik's Cubes may be the most tested, non-athletic, test of SPEED on the planet. At this point computers have humans beat, at .103 and 3.13 seconds, respectively. This project attempts to see how fast a student can compare to the current records.
Note: all figures generated by me unless noted otherwise.
Supplies
Electronics and Hardware:
Arduino Uno (or Raspberry Pi or any other hobby-friendly MC)
6 Nema 17 Stepper Motors (in my case I had 3x17HS16 and 3x17HS19. This is actually suboptimal due to possible compatibility problems, but this is what I had on hand.)
Protoboard, jumpers, and soldering equipment
M3x10mm screws (24 screws)
A Rubik's Cube (of course)
Fabrication
Any CAD software (I used OnShape)
Any 3D printer (I used BambuLab P1S)
PLA Filament (2 contrasting colors)
Designing the Shell
The goal here was to design a rigid frame that can handle the torque of the stepper motors without flexing, which would cause the cube to jam. The design here consists of dual chassis, two "orbiting rings" that are connected by the motors attached to them. This rings design allows to mount 6 stepper motors that are all perpendicular or parallel to each other. This design allows us to minimize the number of parts needed to print as all 6 motors can be attached onto 2 parts instead of a more complex frame that would require additional mounting hardware.
Note on Terminology
Before we go further, I want to clarify some terms I might use in the rest of this Instructable. A Rubik's Cube has 6 faces. Each face has 4 corner pieces, 4 edge pieces, and a center piece. It is important to note that when you rotate a face the centerpiece does not rotate meaning a fixed motor can rotate the fixed centerpiece. That means the white side, even when the cube is not in a solved position, is the one with the white center piece.
In addition, the 6 sides can be labelled with 3 opposite pairs, Front and Back, Left and Right, and Top and Bottom. However, these sides do not have a definite position in that the front is always the side facing the person solving the robot. For clarity sake if I reference any of the side names, assume the reference position shown in the diagram.
Adapter
Some Rubik's Cube solvers grab on to the sides of the cube, but this would require a much more complex system. Instead we pop the end caps off the centers which reveal a convenient passive mounting location. The adapter I made used the negative of the internal measurements of the cube, which snuggly fit in.
Downloads
A Bit of Aesthetics
I created some red tabs that fit into the holes of the frame. You should attach them opposite to the side where you would view the cube. This helps give contrast to the frame and make the cube really stand out.
Downloads
3D Printing and Assembly
Now we need to 3D print and assemble the pieces. We will need to print the following pieces:
- 1x Outer Ring
- 1x Inner Ring
- 6x Rubik Adapters
- 8x Tabs (Optional).
You should use whatever print settings have reliably worked for you in the past. However, in order to ensure structural integrity, I would suggest these settings.
- 30% infill
- 4 walls
- Support On(Trees)
Once these pieces are printed assembling is pretty easily. Slide the inner ring into the outer ring, while the Rubik's cube is sitting inside the outer ring. Push the Adapters onto the shafts of all the motors. Insert one motor into the intersection of the inner and outer ring as shown in the photo above. Attach it with 4x M3x10mm screws. Now the rings are mechanically connected. Continue sliding in and attaching the motors to the frame.
If you choose to print the tabs, they can be pretty easily snapped into place, but if they are too loose you can use a glue gun or other adhesive to stick into place.
Wiring Diagram
In order to understand how to wire 6 stepper motors, we need to understand how to wire 1. In the diagram we see there are 4 main parts, connecting the stepper motor to the TMC2209 Driver, powering the motor with an external voltage (this is important as the Arduino cannot support the voltage and current demanded by the motors, powering the driver logic (this time we do use the Arduino 5v or 3v3), and connecting the DIR and STEP pins to the Arduino. However, this would be quite messy if you directly made these connections with wires.
Soldering Custom Boards
In order to prevent a rat's nest of cable we use Protoboards to create PCB-like connections reducing cabling. There are two types of boards as shown, one with copper strips connecting holes horizontally and another only with exposed pads. The exact ones we use don't matter I just used whatever was on hand. The green board connects the TMC2209 drivers to the motors, power source and Arduino. Specifically, I soldered female headers to male headers and connected them with a solder bridge. Make sure to use sufficient flux or this will not work. The solder bridge also tends to be pretty finnicky. In order to get a good result use the lead of a resistor (or any other Through hole component) to guide the solder between the gap. You can either remove the resistor or snip off the ends.
The second, orange board, helps handle power distribution for the motors. This will carry the 5V-28V needed to power the motors, not the logic. The orange strips on the board are actually flat copper sheets and really help to guide the solder to connect all of the pins.
Completing the Wiring
Despite my efforts to reduce wiring, it still ended up as a mess. The real solution would be ordering a custom PCB with internal traces instead of wires, but that is currently out of the scope of this current project. As for the wiring itself, I followed the wiring diagram from Step 6 and made sure to note which motor connected to which driver and what drivers connected to which pins on the Arduino Mega. (This is important or you will waste time trying to figure out which wire and motor is which. )
In regards to power, I used a bench power supply allowing me to safely test with varying currents and voltages. I settled on 24V and a maximum of 8 amps. 24V was empirically tested as sufficient based on motor speeds and torques. 8 amps should be the theoretical maximum amperage for 6 motors using around max current at 1.3A. Please note that the Arduino is not powered by this supply, but externally through a USB-B cable connected to the computer. It actually can power it if you want through the Vin port which steps down the voltage to a usable level for the Arduino.
Representing Rubik's Cube Programmatically
One common method is a 9×6 matrix, where each of the six faces is flattened into nine positions and encoded using integers that represent colors. This keeps the cube state unambiguous and easy for algorithms to manipulate. The color mapping used is:
- 1 — White
- 2 — Yellow
- 3 — Red
- 4 — Orange
- 5 — Blue
- 6 — Green
The TMC2209 stepper driver uses two control pins to move motors that manipulates cube. STEP determines how far and how fast the motor turns by advancing one microstep per pulse, while DIR sets the rotation direction by switching between two logic states. So in this case we might have DIR set to high to rotate clockwise and pulse STEP 200 times in 1 second (think of this similar to PWM).
Creating a UI
Since there is no camera system to determine the position of each of the pieces, we will instead rely upon manual input. Without a User Interface (UI), modifying the position programatically would become quite tedious quite quickly. Thus, I created a simple UI that allows you to change the color of the squares and also tells the human how to solve the cube without the robot.
Solving the Rubiks Cube
The previous step makes it seem as though solving Rubik's sube is trivial. However, a 3x3x3 Rubik's cube has 43,252,003,274,489,856,000 positions! Humans are able to achieve this feat by using methods like layer-by-layer solving or a more efficient CFLOP algorithm. Robots, however, face some limitations and benefits. Generally, the robot is not able to actuate more than 1 face at a time (or 2 if the faces being rotated simultaneously are parallel.) This means we would want to optimize solutions for the latter types of "twofold" turns.
This ends up being a non-trivial problem, but thankfully we are not trying to reinvent the wheel here. Kociemba's algorithm is a powerful tool that allows solving in an average of 18 moves. This is notable because, God's Number, the maximum number of turns needed to solve a Rubik's cube from any of its 43 quintillion positions is a measly 20 moves.
Using these powerful techniques, I was able to achieve average solves of around 4.3 seconds. This does have SPEED in human terms; in that it would be the 7th fastest solve of all time for any human. However, on the computer frontier there is much to improve being around 43x slower. Modern solvers use water-cooled BLDC motors and machined metal fabricated parts to achieve accelerations of millions of radians per second^2. I think my next task should be reducing the burden of manually inputting positions by using a computer-vision system.