The image below is the Autonomous Wi-Fi Robot we will be programming. This is the promotions robot give-away we did in 2013. This support page deals with the programming of the robot. My name is Matt. I am a recent hire at SuperDroid Robots and my first task was program this robot and let you know my experience and provide code samples.
Click on Image for Larger View
The Project Scope
This robot is a Mecanum Wheel Vectoring Robot Autonomous Arduino Platform. It was built, designed, and programmed specifically as promotional robot to be given away to a lucky winner! This robot was designed to be a good start for any robot enthusiast. The starter application we will be supplying (link to this software will be coming soon) to you will be a free movement program. This will allow the robot to automatically travel around any room predicating the safest path to take while broadcasting video back to a local computer. Each part of this code will be comments to explain its purpose and how it can be edited to make changes. This will allow you to learn how the code works and create new functionality for this robot or any similar robot. Along with these program comments, we will also be explaining some problems we ran into while building this robot in the hopes you will have material to refer to if you get stuck. This will be split up between two sections of Hardware and Software.
Below is a full list of the components used on our robot directly after that will be the reasoning behind choosing each part and some of the problems I ran into and solved while constructing the robot.
Fully programmed based on contest participant input
We knew we wanted to use the Arduino Mega Microcontroller because of its strength and ease to use. Along with this we knew we needed an Ethernet shield for it to broadcast the video back. This Ethernet shield will be attached to a router which will do the broadcasting. After attaching the Arduino's Ethernet shield, we found it was difficult to reach the pins we planned to use this project. We decided to use our SDR Custom Arduino Mega Shield. This allowed us to have access to the pins we wanted to use while thinking ahead about wire management.
We decided at an early stage that sonar sensors would be the best for our robot. They are a cheaper alternative to other proximity sensing tools. A sonar sensor works just like how a bat detects what is around it. It shoots out a sound wave and waits for a reflection of that wave. The amount of time it takes for the wave to come back determines the distance from the object you are.
With this robot we are hoping to get no closer to an obstacle then 3-5 inches. Knowing this we were able to pick out a sensor with a high precision in this range. We ended up picking two HRLV-MaxSonar-EZ4 Ultrasonic Range Finder because of the signal strength in this area from the sensor.
We were able to test the sonar sensor by providing power and ground to the circuit to power it on. We then connected the output pin to a voltmeter. From this point we could see the voltage move up and down depending on how close we held the sensor to something. This quickly confirmed this was the proper distance sensor for us.
There are several different types of sonar sensors with a difference of range, width and precision of the reflect signal. Here is our list of Sonar Range Finders.
Now that we have sonar sensors, we need a way to make them move. This is to allow two sensors to see 360 degrees around the robot. They can(and have) been programmed to sweep different sides of the robot.This movement was accomplished by using two HS-422 Servo. This allowed for a 180 degree rotation but you can customize your servo purchases for different projects. This is our list of Servos. In order to mount the sonar sensors to the servos we need a Single Maxbotics Sonar Servo Arm Bracket.To mount the servos to the chassis you will need Servo Standoff Mounting Hardware
The servos expect power, ground and a signal to work properly. The input signal need a pulse every 1500 usec. The servo knows to spin when it this pulse frequency is changed. The acceptable frequency are 800 usec to 2200 usec without 800 usec being the furthest spin in one direction while 2200 usec is the furthest in the opposite. You can test this with a signal generator/Arduino and a oscilloscope.
The robot needed to be nimble and light and we knew that the battery would be one of the heaviest components. When it comes to batteries, the larger the voltage, the larger the size. We decided to go with a 12V 4500 mAHr NiMH 2x5 Battery Pack instead of two 12Volt battery packs. The Arduino itself only required 5 volts to run properly but we knew the motors were going to need more to move the robot. This was the limiting factor when it came to battery decisions.
We want the robot to be able to move, so we need motors and wheels. We decided to go with PWM Motor Controller 3A 12-55V. This is a easy to use and cheaper alternative than other motor controllers.It also was a lower voltage alternative taking only 12 volts to power while some require around 24+ volts. We sell a large variety of Motor Controllers which maybe needed for other applications.
Many different wheels could have been chosen for this robot. We were able to match 4 inch Nexus Robot Aluminum Mecanum Wheels with these motor controllers. We decided on these wheels for multiple reasons. They are small enough to be driven by our motor controller while having the ability to move in all directions. Each wheel has many smaller wheels on it at a 45 degrees angles to allow translation instead of only forward and backward movement.
As we started to put the robot together, we knew wire management was going to be a problem. When it comes to wire management there is always a trade-off. While working on the robot, it is generally nice to have longer wires to allow you to move things around and have more room to work with them. The problem with this is it quickly because hard to deal with. Not only can the wires start to get in your way but it also can get in the way of the robot. As you add more and more components you start needed to reacquire this real-estate for your robot. Aesthetically smaller more precise wires looks better as well.
When building up this robot, I ran into many difficulties I needed to overcome. In this section I am hoping to talk about these problems and how I went about troubleshooting and eventually solving them.
Connector and Wiring Problems
Cutting to length, Stripping and Crimping are all important steps to making your own wires. (A guide to Crimping can be seen here : Crimping Guide). Whenever you make your own wires, you should immediately check them for continuity with a voltmeter. After verifying the wire fits, you can plug it into one end of the connection and test the voltage on the wire with your voltmeter. After doing so you can be more confident that the wire will transfer the desired signal/voltage. If you are still not getting a good connection it might be that the header of your wire is not a snug fit, the metal crimped onto the wire may be lose, or maybe the connection between that metal and the pin is not secure. Normally you can try re-seating the wire or redo the header connection.
This problem arose for me many times when I was wiring the Range sensors. The added complication to the range sensors was that they were designed to pivot, which required the wire to be more mobile then the stationary wires. As the range sensor turned 180 degrees the wire was bend and would pull either the power, ground or signal wire out. This could happen on either the board connection or the range sensor end. After re-crimping the wire a few times, I decided I would need a better solution for this. Adding a pole to the chassis of the robot, I was able to give more slack to the wire and give it a better approaching angle to the sensor, now as the sensor spins most of the wire is stationary. Check out the pictures below to get a better idea of the positioning.
Another quick thing to note is that since the chassis is also ground, when mounting circuit boards make sure you leave room between the bottom of the board and the chassis itself. We use plastic separators for screws to keep this gap.
Short Circuits and Chassis Grounding Problems
This issue is one of the biggest you have to deal with. After every additional wiring or edit to the robot before turning it on, you should check to make sure that ground and power are not shorted together. If you turn the robot on when ground is connected to power many different things could happen depending on where the connection(short) to ground is. If the battery itself is shorted to ground, it will heat up and break or even explode. We have had this happen a few times even here at SuperDroid Robots. When the chassis of the robot is connected directly to ground, one loose wire dropping to the chassis can cause batteries to be shorted with noticing. If the short occurs inside of a component or around a wire, these parts will heat up and break. These breaks occur because the component is trying to drawl all the power of the battery in a very short amount of time. As it drawls more and more current the component starts to heat up until it melts itself. At this point two things could happen. The melt may make the short permanent which will cause your battery to break or the melt may stop the current flow which could save your battery. Short circuit damage can be avoided by adding fuses into your system, which will break after a predetermined amount of current flows through it.
So you added a component and you seeing a short between ground and power. How do you find and fix that? The first thing I would recommend doing is look closely at the new component you added. Before you worked on this section of the robot, there were no shorts, meaning the component must be wired incorrectly. Make sure your ground and power wires have now way of touching, make sure the component itself is not broken from a past short or defective from the start. This can be done by removing the new component and checking the component for the short. Use a voltmeter and check for continuity between power and ground with nothing plugged into it. If the short still is there, then you know the component is bad. If the component is not shorted, then test the wires alone and then the robot itself. By removing components one at a time and testing them you can trace down the short and fix the problem.
I remember specifically running into this problem during testing of the robot. The robot was tracing out a room and hit a bump and then I heard a spark and the robot shut off. Immediately I turned off power and looked for the short. I found that the batteries themselves have rubbed through their plastic and the metal of the battery hit the chassis. You can fix this problem by wrapping the batteries in electrical tape but we decided to add a layer of cushioning between the chassis and the batteries.
Battery Charge and Motor Speed
In order to test the movement of a robot without having to chase it around, You can place it on a box. This box is designed to lift it off the ground so you can watch the wheels spin without them touching the floor. This is especially important when testing an automated robot. If you are unsure of how the motors will respond to the environment the robot is in, you maybe have to chase the robot around to prevent it from hurting itself or possible the things in your environment. I tested all of the automation firmware originality on a box, using pieces of wood to simulate approaching a wall or container. This allowed me see how the wheels and range sensors would react to approaching a wall.
After finishing this testing, I put the robot down and let him loose in the shop. The motors made noises like he was moving but was not actually moving. I found that I needed to increase the torque of the wheels because having the wheels spin freely while on a box is completely different then moving the entire robot. Another Motor related issue is that as the battery pack approaches 11.5 volts in charge, the motors start to slow or even stop moving. This can make the robot function differently then it was programmed to do. If you are getting strange behavior from the robot with little to no programming changes, be sure to check the battery with a voltmeter to make sure its still within the acceptable range.
Programming in Arduino
Although most of this step seems pretty straight forward, it is still a 100% roadblock in programming in the Arduino. The first thing you need to check is that the Arduino programming software is set to the proper board type. This Arduino is the Arduino Mega 2560, if the software is looking for a different Arduino type, then many things like pin declarations and other board specific things will throw errors. You change this by going to Tools->Board->Arduino Mega 2560
Another issue you can run into is not having the specific "included" libraries. The program I have written so far includes only default libraries except for SoftwareServo.h. You can include this into the default libraries by going to sketch->Import Library->Add a Library then specifying the location of the h file you want to include. I have included my SoftwareServo.h in the firmware file on my git hub listed below.
Arduino also has two main programs it runs. It starts by executing "setup", which should be the initialization of pins and setting initial states for your variables and state machines. After this, it moves onto "loop" which it runs through and then starts back at the top. Any code your write, make sure it can be executed multiple times or you have a way to jump over it when you do not what it to run. You can of course write you own functions that you call inside of loop, which will help segment your code and make it easier to read, write and edit later.
Sweeping the Servos
I created a function to sweep the sensors. Servos are extremely easy to use and easy to program components. They require power and ground and a position you want them set at. The biggest issue with setting the servos is that because they take real time to move, getting multiple signals before completing the movement can confuse the servo. An example of this that I ran into was "loop" was taking a fraction of a second to execute, this meant I was telling the servos to re-position the sensors faster then they could move. This left the servos twitching and not sweeping cleanly. In order to prevent this, I put the sweep function inside of a conditional if statement. This if statement was linked to a variable that incremented every time loop finished running. After about 50 iterations of "loop", I could assume the servo has moved most of its position vector and then I sent it another position to move to. This allows for clean sweeping while looking for object to avoid. Remember that after incrementing the variable to 50, you should reset it to 0 or it will just increase past 50 and only reach 50 again once the variable overflows.
Troubleshooting Distance Sensors
Setting the robot sensors left and right without movement. You are able to test how close to an object the sensors can get and what number they will send back to the Arduino. This will help you decide what number to use to say to your robot is to close and tell it to move away from that object. This can be done one of two ways. The first would be to set the variable to a number and test how close you can get without it responding say moving the sensor or an LED lighting up). A more precise way of doing this is to send the actual readout from the Sensor to your laptop and watch how the variable responds with varying distances.
Setting up the State Machine
This was a very important task for the automation part of this robot. I started out with an extensive list of If-Then statements. This quickly spiraled out of control as I found out how complicated the commands would become. I decided at this point to create a state machine. This state machine needs an additional variable that I called "State" and several more constants that I named to be a State(Example: S_forward=0).
Any time that "State" was equal to 0, the robot knew that it should be moving forward. I created many different states including Forward,Sliding_Left, Sliding_Right, Backward, Spinning_Left, Spinning_Right and Looking.
Of course more states could be added to add more functionality to the robot. I will explain the state machine a bit more here but I will include a state diagram below in the pictures to better explain its movement. One example would be, if the robot is in the "Looking" state, the motors are stopped and the servos/Range sensors are sweeping left and right. After this the robot knows which direction is more open and decides to Slide in that direction. This is done by setting State to Slide and waiting until the loop finishes.
Another thing to think about when it comes to states is the robot needs to have another initialization phase for the new state. Which way should the sensors be facing? Which way should the motors spin? How fast should it be going? Are there any variables that need to be reset since the last time we were in this state? All of these problems can be solved by having an initialization variable(ini). If this variable is true, the robot knows it just entered a new state and needs to set up for the change. At the end of this initialization section, you set ini back to 0, and the next time through the loop it will go to the actual function of the state rather than the initialization.
Additional State Machine
Another state machine can be added to prevent the robot from getting stuck in a loop. One current problem with the automation software is that when in a small box shaped area. The robot will move forward, then left, then back then forward again and repeat this pattern until it is manually moved. Another state machine can added to detect when a pattern has been repeated. My advice for this would be after detecting the pattern, to have the robot spin left or right for a set period of time(or 90 degrees). This will allow the robot to attempt to get free and then try another way approach to the situation. This would be an easy way to increase the reliability of the automation portion of the robot.
By adding additional sensors you will be able to detect the environment better then just having two. Early on in the development of the robot, there was talk about adding another range sensor onto the back of the robot. This would allow for the left and right sensor to check left and right while the rear sensor would detect collisions from behind. In the current iteration of the robot, the right sensor faces backwards and the left watches the side. Having two sensors facing on their side, would allow the robot to decide which direction between reverse/left/right is more open and make more informed decisions on which direction to travel.
I will be coming back and updating the hardware and software portions of this section but if you have any questions on construction of a Autonomous robot that have you stuck, feel free to consult our forums and ask away.SuperDroid Robots Forums
The software has been finished and the robot is ready to ship! We will be picking our winner this week and will send out a message informing them. We would love to hear about any progress or changes made by this person and have opened a forum for discussion here. Of course any other questions or comments would be welcome to be added to the conversation.Congratulations to our lucky winner.
The videos show a Mecanum robot on the same chassis running. It is not the exact same robot as is being sold in the contest. As soon as we are done programming the robot and ready to ship it to the lucky winner we will make and updated video and post it.