With PiDay coming up, and my company sponsoring projects, a group of people decided to take on an ambitious project.
We have several members of our engineering team who love to play chess together. There’s a game going on pretty much every day somewhere on the floor. For PiDay, we wanted to do a project that incorporated everyone’s chess habit, and had some robotics component. Everyone loves robots.
With those goals in mind, we set out to build a robotic arm that could play chess. A pretty ambitious goal with only a month to plan and execute, but we felt that if architected correctly we could complete the project. Spoiler Alert: we came close.
Of course we decided on a microservices architecture for the software (we wanted to be like the cool kids). So we broke the concept of a robot playing chess down into its most basic components:
- Opponent moves their piece
- Robot decides on a move
- Robot executes the move This was pretty basic, and we felt we could break it down into more manageable pieces.
A Bit More Detail
Here we break down the execution service a little further.
Detection Service - Detect opponent moves
This was the least important. If necessary, we would input the opponent moves into the computer. Given extra time, we could possibly implement a vision system, but this was unlikely.
Given the opponent move, we need to decide on a chess move. This would take as an input some chess notation, and output a chess notation or a set of board positions.
This service takes in the chess move that needs to be made, along with a configuration file that specifies the board dimensions and position. It would output a series of cartesian coordinates that the robot will move to.
This would be the controller of the robot that would move it to the necessary positions. It would have to run on the Pi to control the robot, and have the ability to do inverse kinematics and move to cartesian coordinates.
Eventually we realized that there would have to be some form of master or controller service. This controller service would talk to all of the other services, and have a UI that would allow us to see the progress and debug it.
Our code mostly runs in Amazon, and a little bit on the Pi. All of it is open source, and can be found in our github project.
Next we had to decide on a robot. We wanted to 3D print the parts, because why not make this as difficult as possible. After looking at several designs, we eventually decided on this design. We felt that Thor would provide the easiest construction, along with providing the actual ability to play chess.
So, we started printing. Three printers at a time (three different locations), for a total of 200+ printing hours. Then after several days of assembly, we had a sort-of working robot arm.
Because it was for PiDay, we decided to ditch the electronics that were originally included in the Thor design and go with a Raspberry Pi instead. This meant the addition of several HATs in order to control 7 stepper motors.
The Adafruit MotorHAT provided a great way to control these, since they were stackable. Now we have an UberPi with four hats stacked on and a lot of wires coming out. Couple this with a few 5V power supplies, and we can move this thing.
The Final Product
You may be thinking that all of this design and architecture is great, but what happened in the end? What happened was, we moved a chess piece.
I know that sounds underwhelming, but let me tell a story about the last couple days leading up to PiDay.
3 Days Before PiDay
The arm is built and assembled, I haven’t slept more than 3 hours for the last two nights, and it’s time to get this thing working. I have a 150W power supply that runs at 12V to power all of the motors. Sounds like a great idea since all of these motors together are going to take a lot of power. What I failed to remember was that this power supply ran at 12A, and the boards that I was hooking it up to peak at 3A for 20 milliseconds.
I hooked it up, started up the code, and became friends with the blue smoke monster. Well shit.
2 Days Before PiDay
I go to Microcenter and buy 4 2A power supplies and hook one up to each HAT. In addition, because now I am paranoid of burning out another $25 board, I wire a 2A fuse in line with each one. No more blue smoke monsters.
This also means that each HAT is running on only 5V, instead of the stepper max of 12V. Now we’re moving really slowly.
1 Day Before PiDay
Okay, we have working motors, and a fully assembled arm. The other members of the team have killed it on building the software, and we have a GUI for manual control, a Path Service, and a mostly complete Chess Service. I have the code finished to allow us to control the arm manually, and we can move it. The problem is, it moves very slowly. In addition, we have no inverse kinematics to enable us to move the arm to cartesian coordinates.
End Result - Pi Day Demo
Scrambling to tidy up our code while our robot moves at a glacial pace, I realize that I have used a function in the stepper library that only allows us to run one step at a time, in a single loop of Python. This means that we can only move one motor at a time, and we cannot control the speed of that motor. What I should have used is multiprocessing with a function that allows me to set speed and send a number of steps to each motor. Right now is not the time to refactor our entire movement service codebase, so we settle on a demo where we move a single chess piece. Without the kinematics available, we will have to manually control the robot.
We get into the demo, and we talk about the architecture, and I start moving the robot. It moves down to the piece, closes the gripper, and then fails to hold on. It drops the piece. A little deflated, I try again, and again. It keeps dropping it. I finally give up and start to move the robot to a home position, and it holds on! The crowd goes wild, and we successfully did a demo. I think my demo karma is empty now.
Thanks to being so ambitious, and having a team of incredibly smart people on my team, we won the PiDay competition. For the next year, we get to proudly display the ReadyTalk PiDay Trophy.