For a recent robotics competition, I created a robot which had to complete a series of tasks in a simulated disaster scenario. From reading gauges and picking up objects, to pushing buttons and deploying payloads, the tasks were very exciting. What made it really challenging, however, was the fact that the entire mission had to be carried out without ever looking at the robot or arena (directly, anyway)! There were no restrictions on the types of robots you could bring – so there were a lot of really creative designs at the competition. From robots running on 6 Raspberry Pis, to ones large enough to allow the operator to sit inside, no two robots looked alike. I took this unique opportunity to implement one of my own creative designs. I built an omni-directional robot! The design was inspired by the work of Professor Raffaello D’Andrea (ETH) – whom I had the privilege to meet – and his robot soccer team as well as Kiva Systems. Before I say too much more, check out the video below:
Now, I could write a 200 page book about my experiences at this competition, but I will keep it short. I will break this post down into the following sections: technical details, technical challenges, design decisions, and lessons learned. Feel free to ask me any questions. Here is a link to all the code I wrote for this robot. Finally, bear in mind that I completed this project in a time span of roughly 8 days with two midterms – not very easy. Let us begin!
If you come from a technical background, your primary question about this project is probably how this whole thing came together. Discovery is comprised of several sub-systems. The brain of discovery is an Atmel ATmega328 microcontroller – Atmel kindly sent me some for free. The 328 received commands over its UART interface from my ground station. This was all done wirelessly over a Bluetooth link. In reality, my ground station was just my laptop, a monitor (on which I was displaying my live video feed), a USB game controller, and a the wireless video receiver. The entire robot was powered by LiPo batteries – which I had an abundance of thanks to my interest in RC. So here is a breakdown of the main components which comprised this robot:
1. Microcontroller: ATmega328 (running at 16 MHz with an external crystal – thank you Atmel)
2. Motor drivers: L293D (two, each one controlled two motors – thank you TI)
3. Wireless video system: Wireless 1.2Ghz Color CMOS Camera + Receiver
4. Bluetooth module: JY-MCU Module
5. Motors: Metal Gear DC Motor with Planetary Reduction 3 V-24 V, 80-800 RPM, 4 KG.cm Torque
6. Servos: Micro 9g Hobby Servos
7. Ground Station Controller: Betop 2165 Game Controller
8. Batteries: Rhino LiPos
9. Programmer: USBasp
10. Wheels: FXA310 (2051KX) CAT-TRAK
I think the best way to explain how my setup works is by taking you through each step (i.e. from me pushing a button on the controller, to the robot actually responding):
- Since the wireless video feed is my only way of knowing where my robot is, I first analyze my surroundings, and quickly deduce the best course of action. Let’s say I want to move forward slowly, and pick up a sensor on the ground.
- I slowly push my right joystick upward, about half way. This sends a signal in the form of a single byte indicating a movement command being sent, followed by a value which corresponds to the location of the joystick. The value indicates the speed of movement. Since all four motors are controlled with a PWM signal, speed control is a cinch. The control scheme can be found in my code is described below.
- Both of these bytes are sent through my computer’s Bluetooth port (direction first, then speed). Assume my robot and laptop are paired (and will hopefully stay that way).
- Discovery’s Bluetooth module receives these bytes, and processes the commands (see code). It decides that the user wants it to move forward at the specified speed, and does so.
- I now reach the sensor. In order to get a better view, I use my left joystick to look downward. This time, Discovery picks up commands to pan/tilt the camera, and does so.
- Having attained my desired position, it is time to lower the primary arm. I send the command to do so by pressing the “2″ button on my game controller. The arm is lowered.
- I then press the “3″ button on my game controller, and the gripper is actuated.
- I confirm by looking downward that the sensor has been picked up. I then lift the gripper, and commence with the rest of the mission.
So this is a very high level view of what is going on. Behind the scenes, there is a little more to it. Now, just for fun, I did this whole project in a Windows environment. Alright, I’ll be honest. I actually chose Windows because something possessed me to try dual booting Windows 8 on my Linux box. BAD IDEA! I don’t know what happened, but my Linux system was completely erased! Since I was very short on time, I did not have time to get everything up and running again.
So from a software perspective, there were really only two parts. The first was code written in Java for my ground station. I utilized the RXTX library which allows me to connect to a COM/serial port, and communicate with it. So that took care of sending data to my robot over my PC’s COM port, which was actually the Bluetooth connection. Next was grabbing data from my game controller. For that, I used the JInput library. Both of these libraries worked beautifully together, and I couldn’t be happier. Being the amateur I am, I had some trouble getting all the libraries to compile with my code properly, but oh well, it all worked out in the end.
The code for the robot was not so easy – initially anyway. I decided that 8 days is a very short amount of time for me to write low level code – I feel really guilty writing high level code (e.g. Arduino) because I feel like I am cheating. So for the first 6 days, I tried really hard to perfect my low level code for the robot. But I was running into a lot of problems with the timers and interrupts, so I decided two days before the competition in a moment of desperation to switch over to just flashing code from the Arduino IDE to my controller (note, I was using the USBasp – to flash code through it to your MCU, go to File -> Upload Using Programmer).
There are several design decisions I made when creating Discovery. Throughout this section, you will see some pictures of prototypes I made out of cardboard, doodles I scribbled into my notebook in the subway … things like that.
1. Using Bluetooth, and Creating a Command Scheme
In case you missed it earlier, I mentioned that each of the commands I sent were one byte long. The robot interpreted each byte, and through a series of control statements, decided exactly what I was intending to do. This scheme can be seen in DiscoveryControl.java. Here is a basic breakdown of what it looked like:
- MotorCommand (movement): R (right), L (left), F (forward), B (backward). This was followed by a value up to 255 (max size of a byte) which indicated how fast I wanted to move in that direction.
- RotationCommand (rotation): c (clockwise rotation), w (counterclockwise rotation), s (stop rotation).
- CameraCommand (camera control): > (look right), < (look left), ^ (look up), v (look down). This was followed by a value between 0 and 90 indicating the exact angle at which I wanted the camera point.
- MissionCommand (actuating mechanisms): m (move arm), g (actuate gripper), p (press button), l (turn on lights), r (release payload).
Notice how simple this whole control scheme is? Neat eh? The advantage of using Bluetooth was that I did not have to encode this. Ideally you would, but since Bluetooth pairs with only one device, I was set! That’s the disadvantage of using something like those overly expensive xBee modules – particularly because most people use those, so at competitions/conferences there is a chance you might run into interference issues. Plus, UART serial communication is the easiest thing in the world.
2. Choosing Omni-Wheels
One likely question you may have is why I chose omni-directional wheels. Well, there are many reasons for that decision. Primary of which would be that I wanted to make a very flexible/dextrous robot. Based on the mission document, the description of the course was very, very vague. I wanted to be prepared for every eventuality. Since the mission was time critical, the faster I would complete it, the better I would do. Being able to move in any direction reduced the amount of time I would need to change my orientation. The only thing I disliked was the fact that the wheels were quite small. Although, thankfully that did not pose any problems, it very well may have. The robot was actually quite low to the ground. If the terrain were not uniform, then Discovery would have difficulties.
As with any roboticist, fitting things together is always a challenge. Discovery was no exception when it came to coupling the motor with the wheels. Before I get to how I accomplished that, I want to speak to my choice of motors. I obviously wanted to move as fast as possible. So I spent a lot of time selecting the perfect motors for the job. The motors I purchased (linked above) based on my calculations (wheel diameter 5 cm, approximate coefficient of kinetic friction 0.3, approximate weight of discovery 1.5 kg, running motors on 8 V) would allow Discovery to travel at a whopping 1 m/s. I thought this was too fast, but it was nice to have that comfort zone. I did install a turbo mode sequence into my robot’s design, but never had to use it.
So back to the coupling. How would you couple two completely unknown parts? Well, it’s 2013, 3D printers are on the desks of every hobbyist these days, so … print them! That’s exactly what I did. I purposely chose keyed wheels to make sure the coupling would have a better grip on the wheel, and whipped up a solid model for the coupling (also on the Git) within minutes. They were printed, and voila! Problemo solved. Try doing that before 2010 (for the average joe, anyway) Feel free to play around with the embedded 3D model below.
Finally, the reason I chose four wheels instead of three was simply for efficiency. The directional vectors of three wheel drive create vector components which unnecessarily cancel each other out. Also, four wheels made Discovery more stable.
P.S. The real reason I chose these wheels was because I thought omni-directional movement was so cool! But don’t tell anyone!
3. Choosing 1.2 GHz for Video Transmission
Simple, I did not want it to interfere with other robots or my Bluetooth connection. Pretty much no one uses 1.2 GHz (typically because you need a license to use it over 200 mW I believe). Trust me, there were a lot of wireless connectivity issues at the competition. I must admit that I am very fortunate to not experience any communication or video signal dropouts. I am pretty sure I was pushing that Bluetooth connection to its limits at over 30 ft.
4. Choosing LiPos as the Power Source
The primary reason for this decision was because I had them on hand, plus they are very good batteries. LiPo batteries can deliver current at phenomenal rates (critical for RC hobbyists), are very fast and easy to recharge, and are very compact. All ideal characteristics for my project.
5. Choosing to Have Two Arms Instead of One
This feature was mainly there as a fail safe mechanism (i.e. if one stopped working, the other could still manage to do the job). I literally built arms before going to sleep the night before the competition, and was extremely worried that they would not work. So I thought this would be a good idea, and a simple measure to ensure I had a backup. More on the importance of contingencies and alternatives later. An important thing to note about the primary arm is it’s ability to pick up a fallen down sensor as well. A lot of team knocked the sensor over onto its side, and since their grippers were only designed to grasp in the vertical direction, things didn’t work out so well. You’ll notice this feature in the video above.
6. Choosing Acrylic for the Chassis
Again, really simple reasons for this choice: acrylic is cheap, strong, easy to cut/form with heat, and looks great. I do not have my CNC machine working yet (I wish I did for this project), so everything was done old school on a scroll saw. I must say, I am quite impressed with the results!
7. ATmega328 as the Processor
I don’t have any really great justifications for choosing this model in particular, but here are a few:
- It just met the number of outputs I would require to drive 6 servos, and 4 motors.
- It had a built in UART.
- It had 3 timers (needed 2 for the 4 motors, and one for the servos).
- Could run on a one cell LiPo
- Can compile code in C
- In the worst case, can program with Arduino libraries (this saved me)
All these reasons justified the use of this controller. Plus, my friends at Atmel who have sent me a lot of fun stuff to play with kindly sent me this as well. Rock on Atmel!
Things have a tendency to stop working at the worst times. This project was no exception. What made it worse was the limited amount of time I had to complete the project. Anything going wrong meant I would be wasting time which was absolutely critical. Trust me, a lot of things went wrong. I will just outline some that I recall most (they may not be as major, but they certainly caused the most panic).
1. Battery Falls Apart
Picture this: you have spent 8 straight days building a robot, you’re running on 3.5 hours of sleep, have been working 7 hours straight since you woke up trying to finish your robot, skipped lunch at the competition because you’re still not done it, and you find out you’re the first one running. That is not a good situation to be in, trust me. But you know what’s worse? You think everything is working, you enter the controller’s room, set up all your equipment and everything, and the last thing left to do is power up your robot. You reach into your pocket to take out the very important battery which you forgot to bring a backup for, but you only pull out the plug! The rest of the battery is still in your pocket. NOT GOOD!
The judges tell you that you have one minute before you will be disqualified – the clock is ticking. You have one minute, and are absolutely panic stricken. Your mind is completely and utterly blank, but you know you must solve this problem.
Now I don’t know what happened to me, but I felt like something possessed me, and my brain starting running through all the possible options I had. I had tape, a few wires with alligator clips at their ends, some jumper wires, a wire stripper, and a broken battery – 45 seconds left. I tore apart the battery (the wires had to lead somewhere) and was relieved to find two terminals buried deep inside the battery. I know how dangerous LiPos can be, so I did this with caution. I took two of the alligator wire things, and attached them to the terminals. I then tore off the female battery connector on Discovery, and clipped the terminals there. Fingers crossed, I turned it on – it worked! Now, I know this sounds like a really simple fix, but trust me, the situation deemed it very challenging. I don’t think I took a single breath for 2 minutes.
2. Incorrectly Grounding the Servos
Micrcontrollers 101, you can’t connect any high power devices to the pins – but don’t worry, that’s not what I did. What I did do was just as silly. A few days before the competition, I was having a problem with my motor drivers. I was sending a signal to them through my MCU, but they weren’t working right. I had the external power supply connected to the drivers, as well as the signal input, so everything should have been working right. I then discovered that the reason for this was that the external power supply and the MCU had to share a common ground. Of course, this makes sense. If they don’t then the signal has no reference. Everything worked, and I was well on my way. Fast forward to 3 hours before my run at the competition: none of my servos are working. They looked like they had a mind of their own, and my robot was all over the place! Since my servos needed 5V to run, and my MCU was running on 3.7, I couldn’t share the power supply. So my servos were also using an external power supply.
15 minutes before my run, I still couldn’t sort this out. I blame this on the lack of sleep I got. But knowing that if I don’t solve this problem, all my efforts will be wasted, I forced myself to think of the solution. I then sat down, and thought. I remembered the problem I experienced earlier with the motor driver, and felt like an apple just plopped on my head and I discovered universal gravitation! That was it, the servo’s power supply needed to share ground with the MCU! Again, seems simple, but with so much time pressure, these little things are easily overlooked. Especially with that rat nest of a setup I had inside Discovery.
3. Arduino to the Rescue!
I have to admit, after this competition, I have garnered a new-found appreciation for the Arduino system. Yep, thank you Mr. Banzi! So it was two days before the competition, and I could not get those pesky timers working right on my 328. I was left with no choice – I was running very low on time – and settled for the Arduino. Within minutes, I wrote the code in the Arduino IDE, flashed it to my 328, and everything worked flawlessly. I literally felt like crying for so many reasons, but mostly because I just came to the realization that Arduino has made engineering so accessible for so many passionate but inexperienced/experienced people alike out there. I used to think that an engineer using LEGO Mindstorms, Arduinos, etc. was too lazy to do things the hard way – or they didn’t know how. As important as it may be to learn fundamental concepts, in situations like this it’s time to put one’s ego aside (better yet, get rid of it completely), and focus on completing a task as efficiently as possible. Hats off to the Arduino community for providing this platform for rapid prototyping, and I apologize for my mildly negative outlook towards the project. You will be seeing a lot more Arduino and open source code in my future projects.
1. Plan A, B, C … Z – Have Backups!
Perhaps the most important lesson I learned was the value of having backups, contingency plans, and simulated scenarios prepared ahead of time in the event of something going wrong – because things always go wrong. The component I was most afraid of failing (or rather, not working as expected) was the drive system. Will the motors work as planned? Will the motors couple properly with the wheels? Will the motors arrive on time? Will they actually be up to spec? There were so many questions, and no time to answer them without physically trying them. Since everything was coming in from China, there was no guarantee of an arrival date. So, I ordered three completely different setups of 5 pieces each (in case one failed, I would have a replacement on hand). I bought 5 of one type of DC geared motor, 5 large servos (which I would modify for continuous rotation), and 5 other geared DC motors. Thankfully, after a lot of bargaining on AliExpress, I got a great deal on the motors I chose (at least, that’s what he made me think), and they turned out to work beautifully. I will sell off the rest.
I also had backups for almost everything else: all the batteries (except the one which failed), Bluetooth module, wheels (well, I ordered 5 in case something happened to one), microcontroller, and motor driver. I can tell you, it was very comforting to know that I had backups (and many came in use, e.g. I set the wrong fuse bits on my other MCUs) but it turned out to not be enough. After a certain point, you have to call it quits due to factors like financial constraints, and just hope for the best.
2. Don’t be Afraid/Ashamed to Take Make Things Easier for Yourself
I described this lesson quite clearly above in “Arduino to the Rescue!”, but it is definitely worth noting. I guess it’s important to ask yourself if re-inventing the wheel is necessary from time to time. It’s easy to get carried away with doing things the easy way, but getting stuck when things get too complex is imminent. Similarly, it’s easy to develop an egoistic outlook and sneer at the easier way of doing things. Both are not ideal engineering characteristics in my opinion. It is important to understand the situation, and employ the best tools/resources at your disposal. If you have a limited amount of time, there’s no harm in taking the easier route – just don’t get used to it.
3. Spend Time Designing – it Pays Off
Another key lesson I learned was that rushing to implementation is not the best way to get things done. In fact, it usually doesn’t work that way. This lesson really hit me the night before the competition. Among many other things, none of the arms on my robot were built, let alone working. From 8 pm until midnight, I was going back and forth frantically cutting acrylic parts, slapping them on my robot, and realizing the design won’t work. Midnight hit, and I pretty much decided that I wouldn’t be able to compete the next morning. I calmed myself down, and allowed myself one more attempt. This time, I put away all the electronics, acrylic, and everything else, and took out a piece of paper, some cardboard, scissors, and tape. I carefully drew out a new design, and prototyped it with cardboard. I will never forget that moment. I modified the design several times because working with cardboard is so easy! Eventually, I reached a perfect design. I cut it out in acrylic, put it all together, and the design worked great! The lesson I learned that night was extremely valuable: cardboard is extremely valuable building material … don’t throw it out!
In all seriousness though, if you focus on making a flawless design, then implementation becomes a cinch. Otherwise, you will be stuck in the same infinite loop I got stuck in, and no one likes infinite loops. Just ask Sheldon.
That’s all folks! Certainly let me know what you think. A lot more happened in comparison to what I described in this post, but I think I have already said way too much. Looking forward to reading your comments!
P.S. I named my robot Discovery in honor of my favorite shuttle.