EE/CS: Basic C Using the Robotics Library
Summer 2003
This handout basic programming constructs and how they are implemented using the C programming language syntax and semantics using the UE robotics library.
Executable statements tell the computer what to do with the
data. There are several different kind of control statements:
/* included libraries go here */
/* constant definitions go here */
void main (void)
{
/* variable declarations go here */
/* executable statements go here */
}
Sometimes we want to write notes to ourselves about what the
program is doing. This can be done by using comments which in C
begin with /* and end with */. Everything between
these marks is ignored. So in the above example, we would replace
the comments with the actual code that does those things.
#include "robotics7opt.h"Every OPTIONS LEGO project program must have this line at the beginning.
/* Sound constants */ #define OFF 0 #define ON 1defines the word OFF to have value 0 and the word ON to have value 1. Now we do not have to remember which value (0 or 1) will turn the buzzer off or on, and only have to remember the words, which is much easier to do. By convention, constant names are written in all uppercase letters with words separated by underscores.
Recall that a variable is a memory location where a piece of data can be stored and retrieved. Variables are declared (made known to the compiler) in C using the following syntax:
type namelist ;The namelist is one or more names separated by commas. A name must start with a letter (either uppercase or lowercase), and can be any combination of letters, digits, or the underscore character ('_'). C is case sensitive, which means that it cares about the difference between uppercase and lowercase, so that the name sum is different than SUM or Sum. Keil C supports a number of different types, but for now we will only be using one of them: unsigned char which is used to hold characters and small positive integers. Here are some examples of variable declarations:
unsigned char i, j, k; unsigned char channel0, channel1;Each type has some literal values. For unsigned char, they can be small integers like
0 1 23 42 or a character enclosed in
single-quotes. For example, 'A' 'z' '3' '?'. Note that
integer 3 is not the same as character '3'. For
the OPTIONS LEGO project, we will be storing small integers.
To give a variable a value, you can assign a value to it by using the following syntax:
variable = expression;The expression can be a literal value (e.g., 10), a variable name, a function call (more on that later), or a mathematical, relational, boolean, or bitwise expression involving literals, variables, function calls or other expressions. The operations supported as operators by C include:
The mathematical operations have usual precedence and associativity, and are of higher precedence than the relational and logical operators. The relational and logical operators compute a result of 1 (for true) or 0 (for false). The bitwise operators are used in the robotics library to manipulate single bits and are included here for completeness. Some examples of assignment statements and expressions:
Operation Operator Operation Operator Unary Negation - Equality == Addition + Inequality != Subtraction - Less than < Multiplication * Less than or equal <= Division / Greater than > Integer remainder % Greater than or equal >= Logical negation (NOT) ! Bitwise XOR ^ Logical conjunction (AND) && Bitwise AND & Logical disjunction (OR) || Bitwise OR |
var1 = 1; var2 = var1 + 5; var3 = var1 < var2; var4 = var1 + var2 - var3; ch1 = 'A';
The OPTIONS LEGO project has one type of sensor, an A to D
converter (that can be used to read light sensors). There is a
function for reading the A to D converter. It is used as follows:
GetAtoD(chNum)Where chNum is a channel number 0-7, and the function returns the value read in from the sensor attached to that channel. Some examples:
channel0 = GetAtoD(0); channel1 = GetAtoD(1);
The buzzer can be turned on and off using the
Sound(state) or Beep(num) functions. The
Sound function turns the buzzer on if argument state
is 1 and off if the argument is 0. As noted above, the robotics
library defines constants ON and OFF for use with
this routine. Beep oscillates the buzzer for num
cycles. An example:
/* Beep 5 times */ Beep(5);
The condition can be any expression. The semantics of this statement is if the condition is true (a value that is not 0), then the statements for true condition are run and the statements for false condition are ignored. If the condition is false (a 0 value), then the opposite happens and the statements for the true condition are ignored and the statements for false condition are run. In both cases, after the appropriate statement is run, the next statement after the if-statement is run. The else portion is optional. If it is missing, nothing is run when the condition is false. Since the if-statement is just another statement, it can nested inside another if-statement. For example,
if ( condition ) {statements for true condition }else {statements for false condition }
if (channel0 + 20 < channel1) /* Right eye darker than left eye */
{
Beep(1); /* Beep once */
}
else
{
if (channel1 + 20 < channel0 ) /* Left eye darker than right eye */
{
Beep(2); /* Beep twice */
}
else /* Both eyes about the same */
{
Beep(3); /* Beep three times */
}
}
will make the controller board beep the appropriate number of times
depending on which ``eye'' is darker.
In this repetition statement, the condition is checked to see if it is true or false (just as for the if-statement). If it is true, the statements to be repeated are run. If it is false, the repetition stops and the next statement after the while-statement is run. For example, the following code will check the eyes 10 times and stop.
while ( condition ) {statements to be repeated }
count = 1;
while (count <= 10) /* repeat until count become greater than 10 */
{
channel0 = GetAtoD(0); /* Right "eye" */
channel1 = GetAtoD(1); /* Left "eye" */
if (channel0 + 20 < channel1) /* Right eye darker than left eye */
{
Beep(1); /* Beep once */
}
else
{
if (channel1 + 20 < channel0 ) /* Left eye darker than right eye */
{
Beep(2); /* Beep twice */
}
else /* Both eyes about the same */
{
Beep(3); /* Beep three times */
}
}
count++; /* Increment count */
}
For the LEGO car, usually we want the program to just repeat continuously,
so we write:
while (1) /* Repeat continuously, since the condition is always true */
{
/* statements to be repeated */
}
A function call is just the name of the function and a
comma-separated list of arguments you want to pass to the function.
The syntax is:
function-name ( argument-list ) ;An argument can be a constant, an expression, or a variable. If the function returns a result, you need to assign it to a variable to save it.
The robotics library routines are all functions. For example, when you
write something like
Beep(2); /* Beep twice */
you are telling the program to go to the subprogram called
Beep giving it the values 2. The subprogram then does
whatever it is suppose to do, in this case making the buzzer beep
twice. A sensor reading function like GetAtoD returns a
value that you can use to determine the state of the sensor.
For the OPTIONS LEGO project, you will not need to write your
own functions. However, the robotics library consists of only
functions, so you can look at robotics7opt.c if you want to
see some examples.
There are a few other functions of interest in the robotics
library. There is an initialization routine for the motors called
InitializeMotors(), There are two functions related to
controlling the motors. AllStop() causes all motors to stop.
SetMotor(motorID, speed) will set the motorID motor
(1-3) based on the speed, which should be an integer between -255 and
255. A negative speed will make the motor go ``left'' or ``reverse'',
while a positive speed will make the motor go ``right'' or
``forward''. (Which actual direction these are depends on how the
motors were wired to the controller.) A speed of 0 will cause the
motor to stop. Finally, there is Delay(count), which causes
the processor to ``busy wait'' for approximately 200 microseconds for
each count.