CHAPTER 38

INTEGRATING THE BLOCKS
With the function of the robot defined, you will have to decide how you are going to bring all the pieces together. So far in this book, different building methodologies, electronic circuits for motor driving and control, computer and microcontroller devices, sensors and output devices have been discussed along with example circuits. You probably feel comfortable with the individual building blocks that have been presented although bringing them all together with a single controller probably seems scary and difficult. By following a few simple rules, you will be able to bring all the pieces together into a functional robot.
The first rule is to try and maintain the basic program format that was discussed in Chapter 13. Written out in pseudo-code, the structure of your first robot programs should always be:
images
where Outputs = Processing(Inputs) is a simple way of saying that each of the robot’s outputs is a function of the various inputs available. This will reduce the complexity of your software to just a simple Input—Processing—Output model for each output and will allow you to easily observe the response of some outputs to specific inputs and if they are not working properly they can be changed without affecting other functions in the robots.
For a light-following robot, the LeftMotorProcess function could be
images
and used to control the left motor of the robot directly. In this function, the Left Motor will be active if the robot is to move forward (LeftLight equal to RightLight) or turn right (Right- Light is greater than LeftLight). If the robot has to move left, then the motor stops and the left wheel becomes a pivot the robot turns around.
The right motor function (RightMotorProcess) would be identical except that the comparison statement would be reversed, becoming;
images
As the application became more complex, then the functions governing the actions of individual outputs can be made more complex without affecting other output functions and additional ones could be added without affecting any of the original output functions.
This approach may seem somewhat inefficient because much of the code will be repeated, but as an approach for your first attempts at getting a robot working, they will be quite effective, easy to code, and (most importantly) easy to debug and get running.
In contrast to a PC, where there seems to be almost limitless resources available, a microcontroller or microprocessor used to control a robot has only a limited amount of resources that can be brought to bear on the task of controlling a robot. Before beginning to design the robot, the resources that will be required should be listed and a controller selected from the chips and system PCBs that have the required resources.
The resource that will seem to be the most restricted when deciding on which controller to use will be I/O pins: both digital and analog. During planning of the robot features, the different I/O requirements must be cataloged and matched to I/O pins with the required capabilities. This task is not difficult, but forgetting to do it can cause a great deal of stress and rebuilding when you are finishing the robot later.
When you are first starting out, invest in microcontrollers that have quite a few I/O pins available; larger chips can have 30 or so I/O pins that can be used for a variety of different tasks. These chips will be somewhat more expensive and physically larger than those that have a dozen or so I/O pins, but the extra I/O pins will be useful when you want to add another feature to your robot, LEDs, or a speaker to indicate different input conditions from the robot’s sensors that will be important for either debugging the application code or better understanding the input data being received by the controller.
Along with I/O pins, most controllers have a number of other features that you will want to take advantage of in your application design. Timers, analog-to-digital converters, voltage comparators, and serial interfaces are all resources that must be managed like I/O pins as they are available only at specific pins and addresses within the devices.
The BASIC Stamp 2, which has been used for demonstrating different functions, is unusual in the flexibility given to each pin. They can be used for digital I/O, serial I/O, PWM inputs and outputs, limited serial interfaces and so on, which are usually devoted to specific pins in a traditional controller. For this reason, you may want to use only a controller like a BS2 because you are not as constrained as you would be with other controllers and chips.
The best way to manage limited internal features and resources is to treat them as central resources—available for the complete robot application rather than only specific functions. One of the best ways to ensure that the resources are available to all the functions in the robot is to continually execute the internal functions and make the results available to all the output procedures as global variables that can have status flags and values read by the output functions as inputs, just like digital I/O pins or register values to prevent any one function from affecting the value for the other output functions which also rely on the resource’s data.
Even in systems that lack multitasking capability it’s still possible to write a robot control program that doesn’t include a repeating loop that constantly scans (polls) the condition of sensors and other input. Two common ways of dealing with unpredictable external events are using a timer (software) interrupt or a hardware (physical connection) interrupt.
When using interrupts, they should set flags or other variable values to indicate that the interrupt has been requested and processed. During the main loop of the control program, the flags and variables should be used as inputs, just like object, sound, speed, and other standard sensors.
A timer built into the computer or microcontroller runs in the background. At predefined intervals—most commonly when the timer overflows its count—the timer requests the attention of the microprocessor, which in turn temporarily suspends the main program, if it can spare the cycles. The microprocessor runs a special timer interrupt handler subroutine, which in the case of a task-based robot would poll the various sensors and other input looking for possible error modes. (Think of the timer as a heartbeat; at every beat the microprocessor pauses to do something special.)
If no error is found, the microprocessor resumes the main program. If an error is found, the microprocessor runs the relevant section in code that deals with the error. Timer interrupts can occur hundreds of times each second. That may seem like a lot in human terms, but it can be trivial to a microprocessor running at several million cycles per second.
A hardware interrupt is a mechanism by which to immediately request attention from the microprocessor. It is a physical connection on the microprocessor that can in turn be attached to some sensor or other input device on the robot. With a hardware interrupt the microprocessor can spend 100 percent of its time on the main program and temporarily suspend it if, and only if, the hardware interrupt is triggered.
Hardware interrupts are used extensively in most computers, and their benefits are well established. Your PC has several hardware interrupts. For example, the keyboard is connected to a hardware interrupt, so when a key is pressed the request is sent to the processor to stop executing the current code and devote its attention to processing the data from the keyboard. The standard PC hardware has 16 hardware interrupt sources, which are prioritized by hardware within the PC down to just one interrupt request pin on the microprocessor. You can do something similar in your own robot designs.
There are two basic ways to deal with error modes in an interrupt-based system. One is to treat them as “exceptions” rather than the rule:
  • In the exception model, the program assumes no error mode and only stops to execute some code when an error is explicitly encountered. This is the case with a hardware interrupt, which will stop execution of the current application anytime an error condition is detected and used to cause an interrupt.
  • In the opposite model, the program assumes the possibility of an error mode all the time and checks to see if its hunch is correct. This is the case with the timer interrupt in which the handler subroutine will poll all the robot’s sensors periodically.
The approach you use will depend on the hardware choices available to you. If you have both a timer and a hardware interrupt at your disposal, the hardware interrupt is probably the more straightforward method because it allows the microprocessor to be used more efficiently.
As workers, robots have a task to do. In many books on robotics theory and application, these tasks are often referred to as goals. A robot may be given multiple tasks at the same time, such as the following:
 
1. Get a can of Dr. Pepper.
2. Avoid running into the wall while doing so.
3. Watch out for the cat and other ground-based obstacles.
4. Bring the soda back to the “master.”
 
These tasks form a hierarchy. Task 4 cannot be completed before task 1. Together, these two form the primary directive tasks. Tasks 2 and 3 may or may not occur; these are error mode tasks. Should they occur, they temporarily suspend the processing of the primary directive tasks.
From a programming standpoint, you can consider most any job you give a robot to be coded something like this:
images
X is the primary directive task, the thing the robot is expected to do. Y is a special function that gets the robot out of trouble should an error condition—of which there may be many—occurs. Most error modes will prevent the robot from accomplishing its primary directive task. Therefore, it is necessary to clear the error first before resuming the primary directive.
Note that it is entirely possible that the task will be completed without any kind of complication (no errors). In this case, the error condition is never raised, and the Y functionality is not activated. The robot programming is likewise written so that when the error condition is cleared, it can resume its prime directive task.
For a real-world robot, errors are just as important a consideration as tasks. Your robot programming must deal with problems, both anticipated (walls, chairs, cats) and unanticipated (water on the kitchen floor, no sodas in the fridge). The more your robot can recognize error modes, the better it can get itself out of trouble. And once out of an error mode, the robot can be reasonably expected to complete its task.
How you program various tasks in your robot is up to you and the capabilities of your robot software platform. If your software supports multitasking, try to use this feature whenever possible. By dealing with tasks as discrete units, you can better add and subtract functionality simply by including or removing tasks in your program.
Equally important, you can make your robot automatically enter an error mode task without specifically waiting for it in code. In non-multitasking procedural programming, your code is required to repeatedly check (poll) sensors and other devices that warn the robot of an error mode. If an error mode is detected, the program temporarily branches to a portion of the code written to handle it. Once the error is cleared, the program can resume execution where it left off.
With a multitasking program, each task runs simultaneously. Tasks devoted to error modes can temporarily take over the processing focus to ensure that the error is fixed before continuing. The transfer of execution within the program is all done automatically. To ensure that this transfer occurs in a logical and orderly manner, the program should give priorities to certain tasks. Higher-priority tasks are able to take over (subsume, a word now in common parlance) other running tasks when necessary. Once a high priority task is completed, control can resume with the lower-priority activities, if that’s desired.