Tutorial

Page Under Construction...

Building a robot can seem daunting to someone with no robotics experience. We've put together this tutorial to guide first-time robot-builders through the process we go through in our projects. The process is very standard -- it's like the scientific method of robotics. However, the way we follow it may differ from other roboticists because, at each step, we make our decisions based off of the resources, constraints, and goals we have as a club. Through this tutorial, we aim to clarify the rationale behind the decisions we make in hopes that new members will learn and improve the way we build robots.

Decide Objective
The first order of business in any robotics project is to clearly define what you want your robot to accomplish. Define your goals and constraints. Try to abstractly describe the overall purpose of the robot, e.g., "We want to build a robot that can move around and pick up balls."

Design
The next step is to decide how your robot will accomplish your objectives.

The chassis and actuators are the skeleton and muscles of your robot. First choose what you want the base of your robot to be, whether it is mobile, stationary, or some variation. It is often much easier to purchase a pre-made chassis or modify something existing than to build from scratch. Make this decision based off of your time frame, budget, and need for customization.

If your robot will be interacting with the environment, decide what kinds of end effectors would be most appropriate. First, carefully break down what exactly you want your actuator to do. Based on the exact movements it needs to perform, think of the easiest way to perform them. Unfortunately, this has a lot to do with experience with previous constructions. Therefore, sometimes you may have to go with a less efficient system that you know how to build so that you can build it.

At this time, also consider what materials you would like to use, although this decision may change after hardware prototyping. There are obviously numerous materials you can use for any project, but certain ones are most common, for good reasons:

Aluminum is probably the most common building material. For a chassis, it is strong enough to hold up the robot and withstand some abuse and light enough to keep your robot from being too heavy, while still be soft enough to cut easier with simple tools.

For components such as axles and shafts that experience large amounts of torque, or anything that experiences large forces, steel might be used since it is much stronger and harder than aluminum. However, steel is also heavier, costlier, and harder to work with.

Plastics, such as HDPE (High Density PolyEthylene), are also useful for building things, and can serve as coverings, mounting plates for small items such as electronics, and many other small parts that don't need to be strong or take weight. Plastics are relatively strong and light, also very easy to cut and shape and flexible enough to be bent stably.

Prototype Hardware Design
Prototyping is essentially testing the theory behind your robot before using the actual parts and materials you intend to build it with. Once you have your robot design roughly laid out, you can start prototyping parts of it or the entire thing. Usually, you might prototype one part at a time to see if it will work. For example, if you design a system to launch balls, you might build a smaller prototype of just the launching system to see if your design works at all.

Prototyping is usually done with wood or plastic and not always to scale. When prototyping, its not crucial to get every detail of your actuator or chassis perfect, but more to see if the concept as a whole functions in the way you desire. Generally, if a prototype fails miserably at something, its unlikely that building it more carefully is going to fix it if there are fundamental flaws in your concept or design. For example, if you are building a prototype of an elevating arm system that uses interlocking pieces of aluminum that slide past each other, you may find that the aluminum gets jammed and sticks and doesn't slide smoothly very frequently as you prototype it. Trying to smooth down the aluminum or lubricate it is not going to fix this problem (known as "binding"), the failures of your prototype should indicate to you that you may want to design a different elevator system, such as a scissor lift.

Choose the Electronics
At the heart of all but the simplest robots is a microcontroller. The microcontroller unit (MCU) is a complex integrated circuit that acts as the central control, running software programmed onto the unit and able to receive and send data. Microcontrollers typically have dozens of contact pins along its edges - some for connecting power, others allowing for the unit to be programmed, and most importantly, input/output (I/O) pins which allow us to interact with other electronic components, such as LCD screens, speakers, LEDs, motors, ultrasonic sensors, and so on. This is done by either sending out or listening for electric voltage changes of various intensities. For instance, sending out a 5 volt connection might cause a buzzer to activate, or we might have the software monitor the pin connected to a distance sensor, with different voltage readings correlating to different distances.

While possible to use a bare microcontroller, it's almost always more sensible to buy prepackaged robot controllers which usually will have some core features added unto a base MCU, such as power supply regulators, LEDs, buzzers, or LCD screens to help debug while prototyping, simplified programming cable interfaces, and easy to access I/O pins. These prepackaged boards take care of the baseline requirements to quickly get a MCU up and running in a much smaller package than possible by hand and allow us to focus on more important aspects of design.

We usually select various models of controller boards based upon power requirements, size/weight, cost, features such as LCDs which make debugging much easier, number and type of IO pins (analog vs digital), preconnected motor drivers, and programming languages supported. In any project all these factors have to be weighed against each other to decide the most appropriate models.

Once the microcontroller board has been selected, it's really a matter of selecting whatever sensors or output devices the project requires. Some components, such as LEDs or ultrasonic sensors, are very simple and only require a couple wires and maybe a resistor or a capacitor. Others, such as certain types of motors or LCDs, might involve more complex circuitry outside of the microcontroller in order to control. There's a practically unlimited variety of components that can be used with our microcontrollers, so after selecting components (usually based on complexity, price, and size), it is often necessary to look up manufacturer spec sheets for more involved parts to know exactly what patterns and timing of electric signals we must either send out or listen for on our microcontroller pins. In some cases, we'll have to program the unit to send and receive voltages on the same pin, switching between sending and listening several times within milliseconds.

For some projects, there will be other considerations, such as maintaining a good power supply (for one project, we designed an intricate array of solar panels, capacitors, and resistors to not only deliver power to our unit, but also to be able to monitor the voltage fluctuations of our power supply to the microcontroller via an IO pin on the microcontroller itself). At this point in the electronics design process, most our time is consumed by debugging with software, designing unique solutions to the robot's design goals, or researching any components that require more than simple wiring. Of course, during this process, we have to be aware of the work being done on the non-electronic hardware along with the software side. At some point, the electronics must bridge the two together, and usually there will be lots of debugging involved (e.g., the software will likely have to be heavily tweaked to ensure the motor control on a car is suitable for the wheels' friction and weight and the surface driven on, so that the car can reliably be controlled without smashing into walls.) This stage of design doesn't exist in a vacuum and is almost never fully discrete from other stages.

Prototype Electronics
Breadboard -> Perfboard/Stripboard -> PCB

[Continue, IC's, soldering, common components]

Soldering Tutorials:


 * 1) Great YouTube Tutorial


 * 1) Adafruit Tutorial

Write Software
Robotics software can be written in many programming languages. Generally, the microcontroller will have a specification for the languages able to be used. Typically, low level languages like assembly or C are used. These low level languages do no have specific support for any I/O interface, but allow for routines to supplement this. Thus, they allow for a breadth of options since they are not confined by any hardware limitations (in the case of assembly, the language is processor specific). In addition, these languages require less space and are more efficient than other languages like Java. Java is not the most ideal language since it has garbage collection. Effectively, the program could cease running at any moment to regain resources like memory.

If you are interested in the programming aspect of robotics, you probably know a little bit of Java because that is the most popular language to teach introductory computer science classes in. Even though Java was partly based off of C, there are vast differences between the langauges. Here are some of the more important differences: Java programs run in a virtual environment known as the Java Virtual Machine (JVM). Java does not have direct access to either hardware or the operating system. C also has no classes so its storage is limited to variables (local, static local, global, and register variables) or structs (a structure that may consist of a few variables). Both allow for dynamic storage but in C, you use pointers where as Java has references. Simply, C does not guarantee that a pointer has an address atttached, while Java does. There are more differences between these languages but these show a fundamental difference between the two languages- C: programmer is assumed to be "smart" and Java: holds the programmers hand to make sure everything is intended.

The purpose of software is to connect the microcontroller to needed I/O devices. The software directly relies upon the sensors, motors, and other electronic components to achieve some functionality. It allows a person to set certain pins on the microcontroller to read inputs (ex: read from an IR sensor to know if the sensor is within a certain range of an obstacle). Similarly, it can set pins as output pins to send data to (ex: telling a motor to run or stop). Without I/O, the microcontroller would not be able to transfer any data to components nor read in any information. Basically, the robot would not really be able to do anything.

PSEUDO CODE:

Before actually writing the code, it is beneficial to outline the code in what is known as "psuedo code". Pseudo code is a middle ground between the actual programming language and normal English. It allows you to setup basic functions and organization without worrying about all the syntax and nuances of a given language. Instead, it can be translated into any language.

Example:

while true


 * while IR reads out of range


 * left motor = off


 * right motor = off


 * bottom motor = on


 * bottom motor = off


 * right motor = on


 * left motor = on

This basic example could be used to keep an aerial robot a certain distance from the ground, while also propelling forward when above that distance. Though the translation is not always trivial, it formulates the desired funcationality and proves a "road map" to writing the program.

Real Code Sample
Here's some C code we used in OjAS, our autonomous car robot. This program simply makes three laps around a course and stops. Interfacing with the motors was trivial in this situation because we were able to use the built in Pololu libraries that came with the robot controller. The most interesting part of the program is the way we measured distance in the function returnUltrasonic. //Function Declarations long returnUltrasonic; void fullSpeedAhead; void turnLeft(int); void turnRight(int); //////////////////////////// //Global Variables unsigned const int MAX_SPEED = 115; //Robot speed goes up to 255, but it will skid on smooth surfaces. //////////////////////////// int main { 	unsigned const int DELAY_BETWEEN_PULSES = 10; unsigned const int LEFT_MIN = 100; unsigned const int LEFT_MAX = 140; unsigned const int TURN_THRESHOLD = 300; unsigned long ultrasonicValue = 0; unsigned short hasTurned = 0; unsigned long countTurns = 0; fullSpeedAhead; while(1) //Stops robot after 3 laps (12 turns). { 		clear; ultrasonicValue = returnUltrasonic; if(ultrasonicValue == -1) { 			turnLeft(0); } 		else if(ultrasonicValue >= TURN_THRESHOLD) { 			set_motors(210,-100); hasTurned = 1; } 		else if(ultrasonicValue >= LEFT_MAX && ultrasonicValue  LEFT_MIN) {	 			fullSpeedAhead; } 		else if(ultrasonicValue <= LEFT_MIN) { 			turnRight(100); if(hasTurned == 1) { 				countTurns++; hasTurned = 0; } 			if(countTurns >= 12) {	 				set_motors(0,0); delay_ms(100000); } 		}	 		print_long(countTurns); delay_ms(DELAY_BETWEEN_PULSES); } 	return 0; } /* * The delay between each pulse was tested to be accurate at 5ms.. * A smaller sampling resolution gives you more accurate readings, but don't lower too much or else * there won't be enough time for the readings. * Note: The ultrasonic sensor will only work with ranges between 2cm and 3m. * @return: Returns long equal to pulse time. */ long returnUltrasonic { 	unsigned const int SAMPLING_RESOLUTION = 5; unsigned long time_delay = 0; unsigned long time_delay2 = 0; red_led(1); set_digital_output(IO_C3, LOW);delay_us(10); set_digital_output(IO_C3, HIGH);delay_us(10); set_digital_output(IO_C3, LOW);delay_us(10); set_digital_input(IO_C3, HIGH_IMPEDANCE); while (1) {    	if(is_digital_input_high(IO_C3)) { 	 		while (is_digital_input_high(IO_C3)) { 			 	delay_us(SAMPLING_RESOLUTION); time_delay += SAMPLING_RESOLUTION; if(time_delay > 3000) //If no response in 5000 microseconds. Return 3000 return 3000; } 			red_led(0); return time_delay; } 	delay_us(1); time_delay2+=1; if(time_delay2 > 1000) return -1; } } void fullSpeedAhead { 	set_motors(MAX_SPEED,MAX_SPEED-35); //MAX_SPEED,MAX_SPEED } void turnRight(int turn_radius) { 	set_motors(turn_radius,MAX_SPEED); } void turnLeft(int turn_radius) { 	set_motors(MAX_SPEED,turn_radius); }
 * 1) include 

Test, Debug, Troubleshoot, Rinse, Repeat
[desc]

Considerations
[desc]