To design, program, and prototype a working robotic arm that can be wirelessly controlled.
Started in the winter break of 2021-2022, I had just completed my first semester of college and was working for my next door neighbor, cleaning his yard from 9 to 5 for 7 days. With the work I was doing, I had enough cash laying around to start a new project, but I didn't know what to pick. As someone very wise once said, "if you want to make a fun project, try automating something." So with that proverb in mind, I decided to make a robotic chef, something that could make eggs or other basic dishes.
I pondered the idea for a while and decided that a robotic arm would be the best option here as it's versatile enough to be used in a wide variety of cooking tasks such as stirring, flipping, chopping, etc.
After some basic sketching and problem decomposition, I had broken down the arm into its components and decided to begin with just the arm and not the hand, yet.
The arm could be completed in a reasonable amount of time because it's only a few moving pieces, while a hand has several moving components in a confined space. I concluded that after I had finished the arm, I would start the hand; however, this responsibility was passed on to my college friend who was already designing a robotic hand separately, Dakota Kosiorek. His robotic hand is capable of lifting at least 400g (a full can of soda) and has enough grip strength to crush an emptied soda can.
Returning to the arm's design process, the arm consisted of 3 joints, and 2 members, and a base. The joints would be controlled via motors and potentially a gearbox, and everything else would be 3D printed using my Ender 3 Pro.
I spent the next 2 weeks using Onshape, an free, online CAD (computer aided design) package, to virtually model and assemble each of the parts, working on a tight schedule to 3D print everything before I had to return to school.
Through a lot of trial and tribulation, I managed to CAD everything I had to and even 3D print all of it. Unfortunately, I did not have the electronics with me, so I waited until I got back to school to assemble.
The base is as wide as it is heavy for holding the A.R.M. down while lifting objects.
The bottom joint allows for panning on the base, and tilting on the bottom arm. It's designed to be one of the strongest links in the A.R.M. because it generates such strong reaction forces to not topple over.
This is the member closest to the base and has a whopping 20kg•cm servo located within it. For reference, the most abundant hobby servos are only 2kg•cm.
This is the member furthest from the base and has been designed to be lightweight, yet strong. This is the furthest member from the base, meaning that it has the largest lever arm. To make sure the base doesn't tip over and the motors aren't working unnecessarily hard, the top member is made as light as possible.
One of the hardest decisions was the type of motor to use: servos or steppers.
I put in about 3 days worth of research, trying to find all the benefits and drawbacks of each type of motor.
I found that:
Servos are cheap, already assembled with encoders and gearboxes, but are usually not continuous.
Steppers are expensive, continuous, have very high torque, have high accuracy, but require encoders to be useful (encoders know which 'step' the motor is at).
After weighing each of my options, I decided to go with servos because of my familiarity with them, and how inexpensive they are compared to a stepper.
When I wasn't CADing, I was using MATLAB, a programming platform, to model exactly where the arm could move to and how I would get to each position using the geometry of the arm itself. Later, I learned that the process I was using is called Inverse Kinematics.
I started by creating a 3D cartesian coordinate space (x, y, z) with the bottom of the center of the base of the arm at the point (0, 0, 0).
Then, I used some basic trigonometry functions to relate the radius and height components of the end effector (the end of the arm) to the angle between the top and bottom members and the angle between the bottom member and the base.
After, I used polar coordinate relations and substitution to make x, y, and z a function of the angles above, thus giving me:
To find a position from an angle(s) is called Inverse Kinematics. To find an angle(s) from a position is called Forward Kinematics.
Programming the A.R.M. is no easy task, so I used functional decomposition again to break this problem down into two smaller problems: a computer that sends data, and a computer that receives it.
In order to control the A.R.M. and send data, I decided to use a GUI or a graphical user interface. I've had some experience using Tkinter, the standard GUI library of Python, so I chose to use it again due to its elegant simplicity.
For receiving the data on the A.R.M., I'm using a Raspberry Pi 4, a credit-card-sized computer with WIFI, Bluetooth, and GPIO capabilities.
The main idea is to set up a webserver on my desktop (where the GUI is hosted) and have the Raspberry Pi connect to it. The GUI would push angle data to the webserver as a JSON file (a data structure) and the Pi would scrape that data.
The GUI would compute what angle to turn each motor to, and the Pi would control each servo motor and set its angle accordingly.
The reason I went with this approach is because it's what I did previously with my robot crab. I implemented the system exactly the same way as before and it worked perfectly as intended, I could type in angles to move each servo to on my desktop, and I could watch as each motor arrived at its final position sequentially.
I decided to do a benchmark test of my A.R.M. so far. I wrote a simple python script that would make the end effector follow a parabola along the x-z plane.
Upon running the program, I noticed two things: 1) the shape made was not a parabola and 2) the Pi's scraping program was crashing.
The first issue was caused by the motors arriving in sequence meaning that they did not reach their final positions at the same time. When trying to follow a smooth curve, the A.R.M. was actually following a very rough curve like below.
The reason for the rough parabola is the direct result of a lack of timing.
Imagine we have two identical motors, A and B that rotate at the same angular speed, but motor A must rotate twice as much as motor B. If you start both motors at the same time, motor B will arrive at its end position twice as fast as motor A.
This is a problem when we need every end position to be reached by every motor simultaneously, so the solution is to break up each movement into steps. Move to each step, rather than straight to the end position. Find the largest distance to travel of the motors, and divide the largest distance to travel by the amount of degrees each motor moves.
For example, if motor A is traveling 90 degrees and motor B is traveling 45 degrees:
Find the largest distance to travel, which is motor A with 90 degrees.
Then divide the largest distance to travel by the amount of degrees each motor moves.
So 90/90 means that motor A will have 1 step and 90/45 means that motor B will have 2 steps.
Even though motor B has 2 steps, it travels 1/2x as far, so it has 2x as many steps, while arriving at its final position at the same time as motor A.
Up until this point there were no issues with my webserver-client setup, but now that I was sending more than 8 position updates a second the webserver couldn't keep up, so I reached out to my friend Connor Ricotta for advice. He explained that because the Pi was constantly requesting data, and the webserver was restarting every time there was new data, sometimes the Pi would request at a time when the server was restarting. This meant that the server wouldn't reply, and that no data would come through, crashing the program.
He recommended using Python's socket module, something I'd only tried once before. Sockets are a way of communicating between devices and make it easy to quickly send small amounts of data in milliseconds. They maintain a persistent connection, meaning that they can talk to each other without the middleman of a server.
One device sends data and the other receives. The way I have it set up for a confirmation that the data arrived. The way I'm doing this is as such:
1) The GUI sends the data to the Pi
2) The Pi confirms that the data was sent
3) Upon confirmation, the next set of data is sent
Using this method, data can be sent almost 1000x faster than before. To summarize, the webserver was slow and could take almost a full second to restart each update, inevitably interrupting the connection in the process. The socket method has a persistent connection and can send data at lightning speeds.
The previous ways of controlling the A.R.M. are through a GUI, typing in each angle that the motors should move to, or by using a pre-programmed path.
I have found another way.
One day after class, I was exploring one of the buildings at my university and I stumbled upon a large e-waste pile next to the main entrance. Like every other aspiring engineer, I was curious to see what kind of stuff there was in this dump, so I started rummaging through and to my surprise and delight, I found something that resembled a robotic arm with the words "Microscribe G2" printed on the base in large white text. There was a small LED bulb above these letters and next to the text were several ports, one being a USB port with a cable plugged in.
I separated it from the rest of the junk and plugged the cable into my laptop to see if anything came to life. Nothing happened. My computer didn't detect that a USB device had been inserted and the LED did not turn on. I figured that it was a power issue since the LED should have at least turned on and Windows should have told me that there was an issue configuring the device. I took the Microscribe and the cable back to my dorm room for testing.
Upon plugging in my own USB cable, not only did the LED turn on, but Windows instantly recognized the device as a "Microscribe G2" and installed the necessary drivers. I was ecstatic.
So now, I had this 26" long, robot-looking arm, but I didn't even know what it was for nor how to use it.
I googled the name and found that the Microscribe G2 is actually a CMM or Coordinate Measuring Machine, a three-dimensional measuring device for measurements accurate to the hundredth of an inch. I also found the software used for operating the device from the manufacturer's website that miraculously still had the 15-year-old software.
I installed the software, plugged in the Microscribe, and watched as the data started flowing. I could see the position that the tip of the arm was at change by the hundredth's place in such precision and accuracy.
I decided that the Microscribe would become my controller for the A.R.M. I was building and create a system with a 1-1 movement, meaning as I move the Microscribe to the right, so too does the A.R.M.. If I move the Microscribe to the left, so too does the A.R.M..
In order to get data from the Microscribe, I learned online that there was a foot pedal attachment that recorded the current position of its end effector. To record, the Microscribe acts like a keyboard, literally typing the data into whichever window is selected by the user. So I had yet another issue: I did not have a pedal.
This got me thinking, what is a pedal? A pedal is essentially just a way to electrically connect two conductors, or a button. After looking at the pinout for the pedal port, I could see that there was a DATA+ and a VCC line. Through my knowledge of electronics, I made an educated guess and shorted the two lines with a resistor (1kΩ to not fry anything if I was wrong) and sure enough, the data was recorded.
To integrate the Microscribe into the GUI was a very simple process.
As previously mentioned, the Microscribe records data by acting as a keyboard, so I just plugged my resistor into the pedal port, selected my GUI window, and I could see the data successfully being written.
This new controller was almost completely set up; however, there were still a couple of things left to resolve: 1) the Microscribe records position data, not angle data, and 2) the Microscribe is about 6 inches longer than the A.R.M..
In order to solve these problems, I first scaled each of the Microscribe position components down to the size of the A.R.M., and then implemented forward kinematics to find the angles that the A.R.M. servos need to rotate to.
After doing this, I plugged in my Microscribe, opened up my GUI and the Microscribe software, turned on my Pi, and watched as swaths of data streamed from my desktop to the Pi.
Everything above has been the culmination of roughly 2 months effort and I'm excited for what's on the horizon.
1) Integrate Dakota's hand with the arm to make a the complete A.R.M.
2) Robert Tetreault, a computer science major, has joined the team and is working on making a more streamlined GUI
3) Use computer vision to recognize objects and possibly have the A.R.M. control itself
4) Use stepper motors instead of servos for more precise positioning and suitable torque
The end goal of this project is to make a fully autonomous pizza making robot. It should be able to recognize ingredients, use them in the correct order, and produce a spicy pizza pie without any human support.