analog(a) gives you the value (state) of the analog sensor in port a.
start_button() gives the value (state) of the start button.
stop_button() gives the value (state) of the stop button.
For instance, the following Interactive C program will turn motor 3 on and then turn it off.
void main( ) { fd(3); off(3); }
Note the semicolons. Each semicolon marks the end of a statement.
Also note the curly braces. They mark these two statements as a single block (i.e., single unit) of code.
Don't worry about the meaning of "void main()" -- we'll go over that soon. For now, all you need to know is that it signals the beginning of a program.
The commands are executed sequentially. First, motor 3 is turned on at full power in the forward direction. Then motor 3 is turned off.
What will the actual result of these statements be? Nothing noticeable! There's no delay between turning the motor on and turning it off!
We can modify our short program as follows:
void main( ) { fd(3); sleep(3.5); off(3); }
sleep(3.5); tells the system to wait for an amount of time equal to or slightly greater than 3.5 seconds.
In general sleep(n) tells the system to wait for an amount of time equal to or slightly greater than n seconds.
n must be a real number. Trying an integer value, for example, will give an error. So
stop_press(); waits for the stop button to be pressed and then released.
If there are two motors on your robotic vehicle such that
void main( ) { start_press(); fd(1); fd(3); stop_press(); ao(); }
void spin_a_bit( ) { fd(3); bk(1); sleep(5.0); off(3); off(1); }
void forward( ) { fd(1); fd(3); }
void slow_stop( ) { motor(1, 20); motor(3, 20); sleep(5.0); off(1); off(3); }
void main( ) { start_press(); forward(); sleep(3.0); spin_a_bit(); forward(); stop_press(); slow_stop(); } void forward( ) { fd(1); fd(3); } void spin_a_bit( ) { fd(3); bk(1); sleep(5.0); off(3); off(1); } void slow_stop( ) { motor(1, 20); motor(3, 20); sleep(5.0); off(1); off(3); }
The order of functions within a program, on the other hand, does not matter. Execution will always begin with "main". My personal preference is to have "main" appear first, since it gives the reader of the program a sense of its high level design.
int LEFT_MOTOR = 3; int RIGHT_MOTOR = 1; void main( ) { start_press(); forward(); sleep(3.0); spin_a_bit(); forward(); stop_press(); slow_stop(); } void forward( ) { fd(RIGHT_MOTOR); fd(LEFT_MOTOR); } void spin_a_bit( ) { fd(LEFT_MOTOR); bk(RIGHT_MOTOR); sleep(5.0); off(LEFT_MOTOR); off(RIGHT_MOTOR); } void slow_stop( ) { motor(RIGHT_MOTOR, 20); motor(LEFT_MOTOR, 20); sleep(5.0); off(RIGHT_MOTOR); off(LEFT_MOTOR); }Let's look at the first two lines a bit more carefully:
int LEFT_MOTOR = 3; int RIGHT_MOTOR = 1;They tell IC that we would like the name LEFT_MOTOR to refer to the value 3 and RIGHT_MOTOR to refer to the value 1. Once this is done, we can use LEFT_MOTOR and RIGHT_MOTOR in place of 3 and 1, respectively, in the rest of the program.
There are a couple of important things to note about each of these lines:
We must precede the name (e.g., LEFT_MOTOR) with information about the type of the value to which the name will refer. In our example, the names refer to integers (i.e., "int"). The names we use can also refer to real values. The type name for real values is "float":
float LONG_PAUSE = 5.0;Each of these lines is referred to as a declaration and initialization.
/* A. Danyluk */ /* October 2008 */ int LEFT_MOTOR = 3; /* the left motor port */ int RIGHT_MOTOR = 1; /* the right motor port */ /* Move forward, spin a bit, straighten out, then slow to a stop */ /* when the stop button is pressed. */ void main( ) { start_press(); forward(); sleep(3.0); spin_a_bit(); forward(); stop_press(); slow_stop(); } /* Move forward */ void forward( ) { fd(RIGHT_MOTOR); fd(LEFT_MOTOR); } /* Spin right for 5 seconds */ void spin_a_bit( ) { fd(LEFT_MOTOR); bk(RIGHT_MOTOR); sleep(5.0); off(LEFT_MOTOR); off(RIGHT_MOTOR); } /* Slow to a stop */ void slow_stop( ) { motor(RIGHT_MOTOR, 20); motor(LEFT_MOTOR, 20); sleep(5.0); off(RIGHT_MOTOR); off(LEFT_MOTOR); }Interactive C ignores comments. Comments are there to make the code easier to read and understand.
void forward_for_n(float n) { forward(); /* note that you can call any function from within another */ sleep(n); ao(); } void forward( ) { fd(LEFT_MOTOR); fd(RIGHT_MOTOR); }In the function forward_for_n, "n" is a placeholder for a specific value that we expect someone to supply when the function is actually needed. Note the function header:
void forward_for_n(float n)Inside of the parentheses we include the declaration
float nThis tells Interactive C that when the function is called, the caller will supply a value and the value is expected to be a real number.
To use the function (say, to make a robot go forward for 3 seconds), all you need to do is supply the value 3.0 in parentheses:
forward_for_n(3.0);We call "n" in the example above a formal parameter. We say that 3.0 is an actual parameter.
The syntax for supplying an actual parameter to a function should seem familiar, as you've used it in the fd, bk, motor, and sleep functions, among others.
All messages are printed to the LCD on the Handy Board. We can print cute messages like "I am a happy handy board" (recall Lab 2). We can also print status information that might be useful in debugging our programs.
To print a message such as "I'm printing...":
printf("I'm printing...\n");
Recall our program from last time (with a minor modification so that we make use of "forward_for_n"):
/* A. Danyluk */ /* October 2008 */ int LEFT_MOTOR = 3; /* the left motor port */ int RIGHT_MOTOR = 1; /* the right motor port */ /* Move forward, spin a bit, straighten out, then slow to a stop */ /* when the stop button is pressed. */ void main( ) { start_press(); forward_for_n(3.0); spin_a_bit(); forward(); stop_press(); slow_stop(); } /* Move forward for n seconds */ void forward_for_n(float n) { forward(); sleep(n); ao(); } /* Move forward */ void forward( ) { fd(RIGHT_MOTOR); fd(LEFT_MOTOR); } /* Spin right for 5 seconds */ void spin_a_bit( ) { fd(LEFT_MOTOR); bk(RIGHT_MOTOR); sleep(5.0); off(LEFT_MOTOR); off(RIGHT_MOTOR); } /* Slow to a stop */ void slow_stop( ) { motor(RIGHT_MOTOR, 20); motor(LEFT_MOTOR, 20); sleep(5.0); off(RIGHT_MOTOR); off(LEFT_MOTOR); }Let's modify it by adding a printf at the beginning of each function:
/* A. Danyluk */ /* October 2008 */ int LEFT_MOTOR = 3; /* the left motor port */ int RIGHT_MOTOR = 1; /* the right motor port */ /* Move forward, spin a bit, straighten out, then slow to a stop */ /* when the stop button is pressed. */ void main( ) { printf("Starting main\n"); start_press(); forward_for_n(3.0); spin_a_bit(); forward(); stop_press(); slow_stop(); } /* Move forward for n seconds */ void forward_for_n(float n) { printf("in forward for n\n"); forward(); sleep(n); ao(); } /* Move forward */ void forward( ) { printf("In forward\n"); fd(RIGHT_MOTOR); fd(LEFT_MOTOR); } /* Spin right for 5 seconds */ void spin_a_bit( ) { printf("In spin\n"); fd(LEFT_MOTOR); bk(RIGHT_MOTOR); sleep(5.0); off(LEFT_MOTOR); off(RIGHT_MOTOR); } /* Slow to a stop */ void slow_stop( ) { printf("in slow stop\n"); motor(RIGHT_MOTOR, 20); motor(LEFT_MOTOR, 20); sleep(5.0); off(RIGHT_MOTOR); off(LEFT_MOTOR); }Now as the program runs, the LCD will display where we are in the execution of the program. This is generally not necessary in short programs, but can be very useful when we're trying to debug a large, complex program and want to pinpoint where the program fails.
In addition to printing messages, we can print values -- for example, sensor readings, results of computations, etc.
To print a sensor reading - for instance, the value of the digital sensor in port 8:
printf("%d\n", digital(8));
To print a message and a value:
printf("Digital %d is %d\n", 10, digital(10));
if the value of digital sensor 10 is 0
In summary: