[A little bit of robot now]
One mans trash is another mans robot bartender
But why? Human bartenders are amazing!
But why? Human bartenders are amazing!
Whereas this is very true, this arm needed a project, and a party needed libations. This robot bartending exercise expanded my understanding of industrial automation and made for a great conversation piece for an evening cocktail hour with friends.
Via Craigslist, I obtained this Elite Robotics 6-axis industrial robot arm, complete with teach pendant, control box, arm and zero documentation or support.
Fortunately, the robot was in working condition—except the entire system was in Chinese! Since I don’t speak or read Chinese, my first priority was figuring out how to change the language. I reached out to Elite Robotics for support, but hit a dead end. This particular model had long been discontinued, and it seemed they had completely flushed all support code. Most of the original developers had moved on to other ventures.
Still, I suspected they had built the system using existing industry components given their startup status at the time—and I was right. The arm’s superstructure is a Mitsubishi RV7, the teach pendant is a Newker variant, the motors and drives are HCSERVO units, and the control box runs a stripped-down version of Linux. Thankfully, they hadn’t changed the root password.
Once I had the root password, I was able to change the system language back to English and poke around in the filesystem. The motion control executable and the robot monitoring executable were accessible as well as a few old motion path (*.JBI) files. The motion control configuration files also hinted at a command server that could connected to via TELNET. YES! Now I have a list of commands into the robot. It was a lot of trial and error. Getting tired of that I decided to decompile the executable binary to try and make sense of the commands and their purpose. It was enough insight for me to make my own python control widget. GITHUB: https://github.com/benkokes/elite_EI65_robot_controller/
Sidenote: During decompilation phase I found Ghidra. It's AMAZING! I'm surprised the NSA released this tool..
Seeing that Elite Robotics was unwilling (or unable?) to throw me even a bit of example program, I went through the task of understanding the details of the control commands. They put a lot into it; welding, stacking, vision system, palleting. All useless because you need special knowledge, and possibly a license, to run those features. That's ok, because I wasn't doing ANY of that anyhow -- but the vision system and conveyor tracking would have been nice. They don't stream the robot joint positions as a binary output but instead have an on-controller app that pushes them to a terminal. For me to obtain the positions, I had to capture this output, parse it, and then make it accessible to an interfacing program. Uuuggghh, annoying.
After clobbering through the few executables on the controller and the command server, I was able to write an applet to consolidate control in one place. It made it super convenient to validate movements from the bot when I moved onto interfacing it to R.O.S (Robot Operating System)
The next chunk of time was me trying to integrate this arm into ROS2 Jazzy from scratch. It was a bit painful, but I learned a lot. I wanted to leverage this software package to path plan , avoid objects and even incorporate a vision system. RVIZ is powerful, Moveit does a LOT, but it is setup for robots that can accept an interpolated path. This is somewhat unfortunate because this Elite robot only accepts point to point. AND the joint control it CAN accept doesn't move the joints at full speed. Even though I was able to get a full integration, it's not really that useable except for a visualizer. This hurt.
Stop, start, stop, start.
Stop, start, stop, start.
That's.....not quite right.
Sure ROS2 didn't pan out as planned and sure I didn't have a user manual, but the left over JBI files and the teach pendant did have nearly all the pieces I needed to make this idea come to life. I decided on a modular approach with some unit tests to prototype movements so that the robot didn't crash into itself or other things. First order of business was to get it moving to target points and understand the I/O system.
The robots backside has the industrial controls interface, complete with Digital AND Analog inputs and outputs. Conveniently the hardware I/O interface structure contained relays that could be controlled to switch higher power loads, this becomes useful later. The digital inputs are all PNP, so many sensors will be plug and play. A bit irritating, some of the I/Os seemed to be reserved. I haven't tracked down as to why that's the case yet, but it's also not a showstopper, so I will address that as needed.
At this point, I have very high confidence that I can make all the bits go the way I want them to. Now it's time to architect the system. It needed to do the following:
-Selection mechanism for drink
-Obtain a cup
-Dispense one or more liquors or mixers in the cup in a predictable fashion
-Mix the contents of the cup
-Present cup to customer
-Protect the customer from murderous robot arm
I opted to keep most of the functions passively mechanical in the interest of time. The exception was that I had a linear rail and really wanted to use it, figuring it would serve a perfect role here. Also a proximity sensor needed to be employed, so that was the extent of the external electronics.
Gripping the cup was a challenge I wrestled with for quite a while. Initially, I envisioned an iris-style closer around the rim, but the mechanism turned out to be too bulky and prone to sticking—so I scrapped that idea and went with a two-jaw claw instead. I really liked how the jaws pivoted naturally when engaging the cup.
At first, I designed the claws to grab the cup with a horizontal engagement while fully open. That approach proved unreliable, so I switched to spring-loaded jaws, which offered much better consistency.
As for the lid, my original plan was to open it by pressing upward from the lip. However, that method introduced a significant amount of torque on the end effector mount, which wasn’t sustainable. I eventually rethought the design and developed a pry-tool solution (covered later). The lid itself is simply hinged.
To seal the cup, I used a super-low durometer silicone sheet that covers the entire lid opening. I treated it with a food-grade superhydrophobic compound, which dramatically reduced liquid adhesion—almost nothing sticks to it now.
Magnets are mounted in the grabbers, and there is a steel plate on the lip of the lid.
Thankfully, the good folks at The Internet had a few ideas up their sleeve to vend cups. One idea was to use this wedge-style separator to part the cups and keep the others from falling. I was able to re-imagine it into this sled style using a Scott Russell linkage to leverage the motion of the robot to slide the sled. It worked like a champ. (Overall picture)
So I have a small bone to pick with the Hefty Party On! plastic cups. They sell these 16oz cups in packs of 100, 4 colors. The green, blue and purple cups have pretty regular dimensions. During testing, I cycled the green, blue and purple cups through the cocktail making process about 250 times. Same thing every time: Lid close, shakey-shakey, lid open, place in sled. No failures. Then I tried the orange cups. 100% lid seal failure. The cause? The white lip on the cup is between 2-3 mm thicker than the other cups, all 25 of them. The other cups were within 0.5mm of each other. With the extra thickness, the magnetic latch was not able to fully engage allowing the lid to open during the tumbling shaker routiene. This was only discovered after dumping out a cup of liquid all over the table. Well, those were obviously not to be used. It is interesting how different the orange variant are from the other cups -- a real outlier. If anyone from Hefty manufacturing is reading, I'd like to have a chat.
Opening the lid went through a few trials. Originally I was going to catch the end of the lid lip and just force it open. The robot did it fine a few times, but I didn't really like it, so much force on a small spot. Then I thought to push the cup up from its bottom, forcing the lid open. It crushed the cup 15% of the time, so that was right out. Also, more importantly, these methods put a LOT of strain on the end effector mount. The 3D printed mount. I didn't like that, so I then came up with this pry method using a curved ramp. The radius of curvature matches the opening curvature of the lid, so I figured it would be the most efficient way to open it, and so far it's working great.
Closing the lid is dead simple. Use a stick to push it down. Magnets engage, and on we go.
These inverted 1oz liquor dispensers always looked so cool to me, and they seemed like the perfect way to measure out liquid for this project. That was true—until I discovered that these valves are prone to “stalling.”
Here’s how they’re supposed to work: you place a glass under the valve, push upward, and wait for the liquid in the sight glass to drain into your glass. Then, you release the valve by lowering the glass back to its resting position, which should trigger the sight glass to refill.
The problem is that when you release the valve, surface tension can hold the liquid at the entrance hole of the sight glass, preventing it from refilling. When operated by hand, the natural variability in motion usually prevents this from happening—though it still occurs about 20% of the time. But with a robot arm, which is extremely precise and repeatable, I managed to stall the valve nearly 80% of the time. Not ideal for making cocktails!
The solution? Add a disrupting object to the flow path—like a stainless steel wire. I bent one into a U-shape, slipped it into position, and now the sight glass refills 100% of the time.
Assembled valve with wire
Assembled valve with wire
Vending from the jugs was way more straightforward. The glass jugs came with a top-pressed valve, but I swapped those out for a horizontal-press valve and just dwell for a set time to get the right amount of liquid in the cup. It stays fairly consistent until the jugs are about 1/4 full then the fills become noticeably lighter. I address this in the app used to control the drink selection.
I opted to not have the customer remove the cup from the robot end effector. This just left too many questions of safety for me to confidently (and conscientiously) deploy it. I needed a secondary step to present the cup to the customer. Enter the linear rail. This badboy boasts position resolution down to 50 MICRONS. Who says you can't taste the precision!?! But, what this actually does is shuttle the drink our of the robot motion envelope and into an area convenient for the customer to retrieve the beverage. The interface to the rail is RS232, and it accepts a formatted ASCII string for commanded locations. Using a simple Arduino and RS232 <-> UART converter, I set it up to send out 3 commands: Home, accept cup position, and vend cup position. These three positions could be commanded by way of hooking up the Arduino board to the digital outputs from the robot controller hardware. Commanding a specific digital output in the robot control code would ultimately send the position command to the linear rail, moving it.
The ending dwell location also includes a proximity sensor to determine if the customer has removed the cup from the sled. It will block the system from processing the next drink order until the cup has been removed from the sled holder.
To send drink orders to the robot, I developed an Android application featuring eight buttons, each corresponding to a specific drink. When a user selects a drink, the app compiles the drink contents and quantities into a file, which is then uploaded to the robot via SFTP. Once the upload is confirmed, the onboard drink dispensing motion code is triggered to execute. This motion code accesses the drink order file and selects the appropriate drink contents accordingly. Throughout the process, the tablet provides real-time feedback to the user on the status of their order.
I would like to give a shout-out to my pal Nate Kelly (https://www.artofnatekelly.com/), a very talented artist, puppet maker, and darn nice guy. He rolled on in and TAILORED this tuxedo on the robot in about two hours! It really made the whole experience come together. Thanks Nate!
Naturally the party, of course. I did spend the prior week testing the various permutations of drink orders, simulated failures, a power outage and even some light horseplay around the serving sled. The last thing you want to have happen is someone to get hurt while having a good time. I had a few friends come over and use it without any instruction. It led to a few reinforcements of design making the whole experience smoother. I am thankful for patient and enthusiastic friends that helped the process!
Getting this going only needed a few things, mostly found in everyone's garage:
-Robot arm, the more DOF the better!!
-A heavy base mount. The reaction of the rapidly moving arm could shift around the base if it's too light.
-3D printer to make the various holders or other tooling.
-Tablet, preferably Android (and Android Studio IDE for code development).
-Linear rail, a Zaber in this case.
-CNC Mill, 3 or more axis to make the magnet catch for the lid.
-Lathe to turn the lid opener dowel.
-Arduino microcontroller. Use this to interface the robot controller to the Zaber linear rail ( Arduino IDE for THAT simple code development).
-Liquor dispensing shot glasses.
-Two-gallon jugs with push-dispensing valves.
-Proximity sensor for detecting the presence of a cup in the shuttle.
-RGB LED strings for robot state awareness and flair.
The good news is that you can write the controller code on the robots teach pendant, so you don't actually need extra stuff for that. No, not really. You will want to jab your eyes out from that painful experience, so you should get a PC, write the control code on THAT and then upload it to the robot via SFTP.
Easy!
Contact [[email protected]] to get more information on the project