Welcome to RubpyxRobot Project
An educational STEM open-source project from the Innovation at Central Collegiate (I2C) Club in Moose Jaw, Sask., Canada.
Build your own Rubik’s Cube Solving Machine from 3D printed parts, servo motors, a Raspberry Pi computer, and some nuts and bolts.
1. Getting Started
Though currently not the fastest Rubik’s Cube solving machine out there (with an average solve time of around 5 mins), it sure is a fun machine to build, play with, program, and learn from! The entire machine (minus the motors and screws) is built out of 3D printed parts. The parts should be able to be printed on most desktop 3D printers, where the only limitation is if the printer has a printbed that is big enough to accommodate the frame part (see below). The ‘algorithm’ used to generate the sequence of cube turns is a beginner (layers-based) cube solving approach. On average, around 150 individual turns are required to solve any cube, hence it takes the machine a bit of time to perform these individual turns.
Below are lists of the components that need to be 3D printed and/or purchased in order to build your very own RubpyxRobot. If you don’t have access to a 3D printer, check out 3D Hubs to find someone near you who can possibly help with the 3D printing.
These instructions make use of a standard computer (Windows, Mac, Linux) and a cabled ethernet network (created using an inexpensive network router) to remote login to the Raspberry Pi computer and operate the RubpyxRobot. However, if a keyboard, mouse, and monitor are plugged directly into the Raspberry Pi computer, it can be logged into directly. This is a potentially confusing part of the current project, but don’t be alarmed as it’s easily overcome with a little bit of reading and practice!
3D Model of the Rubik’s Cube Machine
- Trimble SketchUp 2017 - RubpyxRobot_3D_Model.skp
3D Printed Parts List, click on a part to view its 3D model (print four of each part, recommended to use different colours for each, 32 total parts)
- bottom_finger.stl
- top_finger.stl
- hand_bottom.stl - print with supports
- hand_top.stl - rotate the part 180 deg. about its X (or Y) axis before printing
- servo_pinion.stl - print with supports
- frame.stl
- frame_brace.stl
- frame_brace_w_leg.stl
- DOWNLOAD ALL 3D PARTS (.zip archive)
Electronics Parts List
- Raspberry Pi computer (2B/3B/3B+/4B)
- microSD card (min. 4GB)
- Adafruit Servo Hat for Raspberry Pi
- 5 Volt power supply (5-10 Amps) with a 5.5mm plug connector
- Digital High Torque MG 996R Servo motor (Quanity 8)
- Servo wire extensions
Miscellaneous Parts List
- Flat top wood screws, total length ~1/2”
- Metric 3mm socket cap machine screws ~10mm threaded length
- Metric 3mm nuts (optional)
- Plastic zip-ties (optional)
2. Building the Machine
i. Assembling the Hands
- The first five 3D printed parts listed above, two servo motors, two trimmed servo horns, and some hardware are needed to build a single Hand.

- Find the counter-clockwise rotation limit.

- Find the clockwise rotation limit.

- Estimate the midpoint between the rotation limits.

- Install a trimmed servo horn inline with the body of the servo motor (you will need to mark the hole locations and carefully drill holes in the servo horn). If your servo motors come with metal servo motor horns, it is strongly recommended to use them! Though trimming and drilling holes though the metal horns will require more work to complete, it is definitely worth the effort.

- It’s suggested to use some loctite on the servo horn bolt.

- Twisting servo motor setup is now complete.

- Position the twisting servo motor on the back-edge of the hand_bottom 3D printed part.

- Use two metric 3mm machine bolts to attach the servo horn to the 3D printed part (if needed, nuts can be installed on the protruding bolts).

- Repeat steps 2-4 and then install the other servo horn perpendicular to the long direction of the servo motor body, then tighten the servo horn bolt (don’t forget the loctite).

- Position the servo_pinion 3D printed part on the servo horn so the part’s notch is at the top.

- Use two metric 3mm machine bolts to attach the servo horn to the servo_pinion 3D printed part.

- Install the servo pinion (and servo motor) through the bottom-side of the hand_bottom 3D printed part.

- Align the four holes in the mounting tabs on the servo motor with the pilot holes in the hand_bottom 3D printed part.

- Use the four included metal screws to install the clamping servo motor.

- Install the bottom_finger 3D printed part on the lower post of the hand_bottom part, see the next step for alignment information.

- The single ‘dot’ on the servo_pinion part must be aligned between the double ‘dots’ on the bottom_finger part.

- Install the top_finger 3D printed part on the upper post of the hand_bottom part. The top_finger’s last gear cog must be on the OUTSIDE of the bottom_finger’s last gear cog (pay close attention to the following image).

- Install the hand_top 3D printed part onto the rest of the Hand assembly, align the holes with the posts and the servo pinion.

- Use three 1/2” flat top wood screws to secure the hand_top part to the hand_bottom part.

- An assembled Hand.

- Gently open the fingers of the hand to check that they can fully open and then gently close the fingers to check that they can fully close. If the fingers do not fully open or fully close, then the position of the servo horn on the servo motor shaft needs to be adjusted. Lastly, install a soft pad on each ‘fingertip’ (foam or cork works well).

- Repeat this process three more times in order to assemble all four Hands.

ii. Assembling the Frame
- The last three 3D printed parts listed above (four of each) and 24 wood screws are needed to build the Frame. It is recommended to put small foam pads on the bottom of each of the frame_brace_w_leg parts to help the RubpyxRobot remain rigid while in operation.

- The rectangular servo hole in the frame 3D printed part is closer to the ‘top’ edge of the part, so ensure all four parts are orientated the correct way. The frame parts are designed to interconnect and use two wood screws to secure them together at one of the outside edges.

- The Frame interconnect at the outside edges only (notice the rectangular servo holes are closer to the top edge).

- Flip the Frame upside so it is laying on its top edge. Install the four frame_brace parts at each of the inside corners using two wood screws for each.

- Install the four frame_brace_w_leg parts on the bottom inside corners of the Frame using two wood screws

iii. Installing the Hands in the Frame
- Run the twisting servo motor’s cable through the rectangular hole in the Frame and then carefully insert the servo motor’s body through the hole. The cable needs to be on the top edge.

- Push the servo motor into the Frame until the servo motor’s four mounting holes align with the four pilot holes in the Frame.

- Rotate the Hand about 90 deg. and then carefully and slowly tighten the top two servo mounting screws. Having a screwdriver with a longer shaft can help get a better angle for tightening the screws (be careful as the screws can easily become stripped).

- Rotate the Hand about 180 deg. from its current position and then carefully and slowly tighten the bottom two servo mounting screws.

- Repeat steps 1-4 three more times in order to install all four Hands within the Frame. The RubpyxRobot software (discussed in an upcoming section) references the Hands by the colours (i.e., white, blue, yellow, and red). Regardless of the colour(s) you used to printed the Hands, the software always references the white and yellow Hands as being on opposite sides of the Frame, and likewise for the blue and red hands. In hindsight, the software should have used more generic Hand 1, 2, 3, and 4 object names.

iv. Connecting the servo motors to the Raspberry Pi
- Optionally, the Raspberry Pi computer can be mounted to the Frame at any one of the top corners. Notice that there are NO pilot holes within the Frame for mounting the Raspberry Pi computer, but using the 1/2” wood screws it is possible to easily secure the computer to the Frame.

- Install the Adafruit Servo Hat onto the GPIO pins on the Raspberry Pi. It is likely that the Servo Hat will first need to be assembled by soldering the 40-pin header and the sixteen 3-pin servo motor connectors to the Hat (see the Adafruit Tutorial for more information). Notice, the following image shows a micro-USB cable soldered to the Servo Hat’s GND and +5 solder pads and used to provide power to the Raspberry Pi 3B computer, this is an optional step as the Raspberry Pi can simply be powered using its own 5V power supply.

- Depending on where the Raspberry Pi computer is mounted (or positioned beside the RubpyxRobot), servo wire extensions may need to be used to have the eight servo motors all connect to the Servo Hat. If the computer is mounted to the top edge of the Frame, it is recommended to use plastic zip-ties to hold the servo motor wires in place (be careful not to tighten the zip-ties too much as you risk damaging/shorting the wires).

- The servo motors are connected to the 3-pin servo connectors numbered 0-7 on the Adafruit Servo Hat, as follows:
a. white clamping servo to connector 0
b. white twisting servo to connector 1
c. blue clamping servo to connector 2
d. blue twisting servo to connector 3
e. yellow clamping servo to connector 4
f. yellow twisting servo to connector 5
g. red clamping servo to connector 6
h. red twisting servo to connector 7

- Congratulations, your RubpyxRobot is now fully assembled!!

3. Setting up the Raspberry Pi computer
i. Installing the Raspberry Pi OS on a microSD card
- Download the latest Raspberry Pi OS with Desktop image file to a standard computer.

- Write the Raspberry Pi OS image to the microSD card using either the Raspberry Pi Imager software or another suitable image file writing software (e.g., Apple Pi Baker for Mac).

- Insert the microSD card back into the standard computer and follow these instructions to enable a remote computer to login to the Raspberry Pi (this type of connection utilizes what is called a Secure Shell, SSH).

- Install the microSD card into the Raspberry Pi computer, attach a network cable to the Raspberry Pi’s ethernet jack and ensure it is connected to the same network as the one being used by the standard computer. Power up the Raspberry Pi computer and the Adafruit Servo Hat using a high current 5V power supply. Using the standard computer, open a command line window or terminal window and run the command
ping raspberrypi. Hopefully the IP address of the Raspberry Pi computer should be returned to the window (in this example the returned IP address is 192.168.1.124).

- If you are using a standard computer running Microsoft Windows, download and install the Putty SSH client and remote login to the Raspberry Pi computer at the IP address discovered in the previous step. For a standard computer running Mac OS or a Linux distro, open a terminal window and run the following command,
ssh pi@192.168.1.124 (use your specific IP address instead). The default username/password for a Raspberry Pi computer is: pi/raspberry. If everything connects properly you should see a command line prompt as shown in the following image.

- The following steps need to be performed in order for the Raspberry Pi computer to have control over the servo motors. On the Raspberry Pi command prompt, run the command
sudo raspi-config and the dialog shown below will appear. Using the down arrow on the keyboard, highlight the Interfacing Options line and press Enter.

- Select the I2C line and press Enter.

- Select the Yes option and press Enter.

- A confirmation message should appear, press Enter to return to the main menu.

- Press the tab key on the keyboard and then select Finish and press Enter. You should now be back at the Raspberry Pi’s command prompt.

- Run the command
sudo i2cdetect -y 1 and you should see a table-like message returned to the screen, as shown in the following image. This indicates that the Raspberry Pi computer has detected the Adafruit Servo Hat and servo control will now work properly.

ii. Installing the RubpyxRobot Python scripts
- On the Raspberry Pi command prompt, run the command
wget https://github.com/ryan-brazeal-ufl/RubpyxRobot/archive/py.zip
This step requires that the Raspberry Pi (via the network it is on) is connected to the internet.

- Next, run the command
unzip py.zip && mv RubpyxRobot-py RubpyxRobot

- The RubpyxRobot Python scripts have now been downloaded to a directory within the pi user’s home directory. Navigate into RubpyxRobot directory to access the Python scripts that control the machine by running the command
cd RubpyxRobot
Followed by the command chmod +x *.py

- The RubpyxRobot is now ready to be calibrated!
4. Calibrating the RubpyxRobot
Please read ALL of the following instructions BEFORE beginning the calibration process!
The final step before the RubpyxRobot can solve its first Rubik’s Cube, is that the Hands of the machine need to be calibrated. Specifically for each of the Hands, the Fingers need to be calibrated to know when they are grabbing the cube (closed) or when they are not (opened), as well as the Wrist needs to be calibrated to know when it is rotated to the left (counter-clockwise/CCW), the right (clockwise/CW), or in the middle (neutral). Each of these 5 states is recorded as a number and stored inside the calibration.txt file inside the RubpyxRobot directory on the Raspberry Pi. Rather than editting the calibration.txt file directly, a Python calibration script is provided that allows you to easily determine these calibration numbers by manually operating one Hand of the RubpyxRobot machine at a time, and maneuvering each Hand into its 5 states.
IMPORTANT
- The calibration procedure can be performed as often as you would like, and should be performed whenever the RubpyxRobot doesn’t appear to be operating smoothly.
- The calibration procedure can be used to calibrate a single state for a single Hand or for all five states for all four Hands. At any time during the calibration procedure you can press the ‘Esc’ key to end the procedure.
The following instructions explain how to calibrate all 5 states for all 4 hands:
- Navigate to the RubpyxRobot directory by running the command
cd ~/RubpyxRobot
This command will ALWAYS navigate you to the RubpyxRobot directory regardless of the current directory you are in on the Raspberry Pi.
- Run the command
./calibrate.py
This will start the calibration Python script and a message will be displayed to the screen as shown below.

- When the calibration script first starts, the white Hand (though your’s might be a different colour) is activated by default. To change control to a different Hand, press the ‘1’, ‘2’, ‘3’, or ‘4’ key on your keyboard. A message will be displayed indicating which Hand is now being controlled.

- Begin by maneuvering each of the Hands into its neutral state. Press the ‘1’ key, followed by pressing and holding the ‘A’ key. The white Hand should begin to rotate counter-clockwise (when viewed from behind). How COOL is that! Press and hold the ‘D’ key and the white Hand should begin to rotate clockwise. Use the ‘A’ and ‘D’ keys to position the Hand so its Fingers are straight up and down (neutral state) and then press the ‘G’ key to save this position. A message will appear on screen indicating that the position has been saved. Repeat this process three more time, once for each Hand. Very important, finish this step by pressing the ‘spacebar’ key, which writes the saved positions to the calibration.txt file.

- Next, maneuver each of the Hands into its opened state. Press the ‘1’ key, followed by pressing and holding the ‘W’ key. The Fingers on the white Hand should begin to open. When the Fingers are in the desired opened state, press the ‘T’ key to save this position. A message will appear on screen indicating that the position has been saved. Repeat this process three more times, once for each Hand. Finish this step by pressing the ‘spacebar’ key.

- With the Fingers of the Hands now all open, place a standard-sized Rubik’s Cube into the middle of the RubpyxRobot. Press and hold the ‘X’ key and the Fingers on the white Hand should begin to close. When the Fingers are in the desired closed state, press the ‘B’ key to save this position. A message will appear on screen indicating that the position has been saved. Repeat this process three more times, once for each Hand. Finish this step by pressing the ‘spacebar’ key.

- Next, maneuver each of the Hands into its CCW state. Press the ‘1’ key, followed by pressing and holding the ‘A’ key. The white Hand should begin to rotate counter-clockwise. When the Cube appears to be rotated exactly 1 turn counter-clockwise, press the ‘F’ key to save this position. A message will appear on screen indicating that the position has been saved. Before repeating this process three more times, once for each Hand, the current Hand needs to be positioned back into its neutral state, press and hold the ‘D’ key until the Cube goes back into its neutral position. Finish this step by pressing the ‘spacebar’ key.

- Next, maneuver each of the Hands into its CW state. Press the ‘1’ key, followed by pressing and holding the ‘D’ key. The white Hand should begin to rotate clockwise. When the Cube appears to be rotated exactly 1 turn clockwise, press the ‘H’ key to save this position. A message will appear on screen indicating that the position has been saved. Before repeating this process three more times, once for each Hand, the current Hand needs to be positioned back into its neutral state, press and hold the ‘A’ key until the Cube goes back into its neutral position. Finish this step by pressing the ‘spacebar’ key.

- Before ending the calibration procedure you should check the saved states for each Hand. To recall the saved calibrated states for each Hand, the following keyboard keys can be used:
a. ‘K’ key recalls the neutral state.
b. ‘I’ key recalls the opened state.
c. ‘comma’ key recalls the closed state.
d. ‘J’ key recalls the CCW state.
e. ‘L’ key recalls the CW state.
Be careful NOT to rotate a Hand while the Fingers are in the opened state!
The following image highlights the keyboard keys used in the calibration process. The red coloured keys are used to manually maneuver the Fingers and Wrist of a Hand. The green coloured keys are used to save the current Fingers or Wrist state. The blue coloured keys are used to quickly recall the saved calibration states. The orange coloured keys are for writing the calibration values to the calibration.txt file (spacebar) or ending the calibration procedure (Esc). The yellow coloured keys are for changing control of the Hands.

5. Solving a Rubik’s Cube using the RubpyxRobot
Finally, the time has come for all of your hard work to pay off! Let’s get your RubpyxRobot to solve a Rubik’s Cube!!
- Navigate to the RubpyxRobot directory by running the command
cd ~/RubpyxRobot
This command will ALWAYS navigate you to the RubpyxRobot directory regardless of the current directory you are in on the Raspberry Pi.
- You need to record the current colours for each of 54 tiles (9 tiles on each of the 6 faces) on the Cube, as a long text string comprised of the letters w r b g o y which refer to the first letter of the tile’s colour. See the following images to understand the order for creating the long text string.

- Run the command
./solve.py {your_specific_long_text_string} false
This will run the solve Python script but the RubpyxRobot will NOT perform the solve. This is because you typed false at the end of the command. By stating false the solve script only simulates the solution and will report the number of sequences (turns) the machine will need to perform. If there is a problem with the long text string, error messages will be reported to the screen.
- Finally, if no errors were reported, run the command
./solve.py {your_specific_long_text_string} true
This will run the solve Python script and then instruct the RubpyxRobot to perform the sequential turns to solve the currently mixed Rubik’s Cube.

- The first thing the RubpyxRobot is going to do is close the Fingers on all the Hands, then the Wrists are set to their neutral positions, and lastly the Fingers will all open.
- Next, you have to insert the mixed Rubik’s Cube into the centre of the machine with the middle tile on the top face (tile #5) facing up, and the middle tile on the front face (tile #14) facing the white coloured hand. Slowly, the Fingers will close, one hand at a time. It is your responsible to hold the Cube in the centre of the machine until at least two Hands are grabbing it. Now, sit back and enjoy the show!
- If at anytime you need to stop the machine, you can press the ‘CTRL’ + ‘C’ keys together (option 1) or simply unplug the power supply from the Adafruit Servo Hat (option 2). Option 1 will terminate the execution of the solve script and a new command prompt will be available on the screen. In order to cut power from the servo motors, which is something you will definitely want to do, you can run the command
./stop.py. If you want to open the Fingers on the Hands you can run the command ./open.py.
- Once the RubpyxRobot has completed the sequence of turns and solved the Rubik’s Cube, all the Fingers will open and the solved Cube should fall out of the bottom of the machine.
6. Future Plans for the RubpyxRobot
Currently, the design of the Hands does not allow the Fingers to be fully opened when the Wrists are in their CCW or CW states (darn, should have thought of that)! As a result, after a turn is completed the Fingers are slowly opened while at the same time the Wrist is slowly rotated back to its neutral position. This is accomplished by a software ‘trick’ but seriously slows down the machine. Future plans are to redesign the Hands to allow for the Fingers to fully open and therefore allow the Wrists to return to their neutral positions much faster.
If you have any ideas for changes or improvements to the RubpyxRobot, either as a hardware design change or a software improvement, we would love to hear from you! Or, better yet, Fork the project and submit your proposed changes or improvements back to us using a Pull Request!!
SUBMIT ANY QUESTIONS OR COMMENTS TO THE ISSUES PAGE ON THE GITHUB REPO.
THANKS FOR READING!