1. Arithmetic
  2. Variables
  3. More on using while to control repetition

Arithmetic

Say we want to modify our earlier "ouch" program: The robot starts moving forward when the start button is pressed. Once the robot is moving, it checks the average of its two light sensors. If the average detected is very bright, it stops for five seconds and says "ouch".
/* A. Danyluk
   October 2008 */

int RIGHT_MOTOR = 1;   /* the right motor port */
int LEFT_MOTOR = 3;    /* the left motor port */

int RIGHT_LIGHT = 3;   /* the right light sensor port */
int LEFT_LIGHT = 5;    /* the left light sensor port */

int BRIGHT = 20;       /* light sensor value considered to be very bright */

/* Goes forward, stopping for five seconds whenever the average light
detected is too bright.  Says "ouch" whenever it stops. */

void main() {
    start_press();
    forward();
    while(1) {
        if ( (analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2 < BRIGHT ) {
            ao();
            printf("Ouch\n");
            sleep(5.0);
            printf("\n");
            forward();
        }
    }
}

/* starts the motors at full power in the forward direction */
void forward() {
    fd(RIGHT_MOTOR);
    fd(LEFT_MOTOR);
}

Interactive C allows us to use the 4 arithmetic operators: + (add) - (subtract), * (multiply), / (divide). The "usual" order of operations applies. To override the usual order, we can use parentheses.

Note that all of the values in the arithmetic expression for computing the average are integers. In Interactive C we aren't allowed to mix integer and real values. Since all the values in this expression are integers, an integer value will be produced as a result. IC does not allow us to mix integers and reals.


Variables

Now say that we modify our program as follows: if the light is very bright, we stop and say "ouch"; if it's "sort of" bright, we slow down for a couple of seconds; otherwise we just keep going forward at full power.
/* A. Danyluk
   October 2008 */

int RIGHT_MOTOR = 1;   /* the right motor port */
int LEFT_MOTOR = 3;    /* the left motor port */

int RIGHT_LIGHT = 3;   /* the right light sensor port */
int LEFT_LIGHT = 5;    /* the left light sensor port */

int BRIGHT = 20;       /* light sensor value considered to be very bright */
int SORT_OF_BRIGHT = 80; /* value considered to be sort of bright */

/* Goes forward, stopping for five seconds whenever the average light
detected is too bright.  Says "ouch" whenever it stops. 
If the average light detected is sort of bright - but not too bright -
just slows down for a couple of seconds. */

void main() {
    start_press();
    forward();
    while(1) {
        if ( (analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2 < BRIGHT ) {
            ao();
            printf("Ouch\n");
            sleep(2.0);
            printf("\n");
            forward();
        } else {
            if ( (analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2 < SORT_OF_BRIGHT) {
                slow_down();
                printf("Oh, the glare\n");
                sleep(2.0);
                printf("\n");
                forward();
            }
        }
    }
}

/* starts the motors at full power in the forward direction */
void forward() {
    fd(RIGHT_MOTOR);
    fd(LEFT_MOTOR);
}

/* adjust motors to half power */
void slow_down() {
    motor(RIGHT_MOTOR, 50);
    motor(LEFT_MOTOR, 50);
}

The program above is fine, but it isn't as efficient as it might be. In particular, we compute the average light sensed in order to decide whether it's too bright. If it isn't, we recompute it before testing whether it's sort of bright. It would be nice if we could just compute it once before asking whether it's very bright or sort of. Fortunately, we can do so. Before we execute the if-else statement, we can compute the average light sensed:
(analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2
So that we can refer to this value later (i.e., in the if-else statement), we give the value a name -- in our case, avg. Remember that if we want to give a value to a name, we need to also tell Interactive C what type of value it will be. In this case, it's an integer. This modification is illustrated below:

/* A. Danyluk
   October 2008 */

int RIGHT_MOTOR = 1;   /* the right motor port */
int LEFT_MOTOR = 3;    /* the left motor port */

int RIGHT_LIGHT = 3;   /* the right light sensor port */
int LEFT_LIGHT = 5;    /* the left light sensor port */

int BRIGHT = 20;       /* light sensor value considered to be very bright */
int SORT_OF_BRIGHT = 80; /* value considered to be sort of bright */

/* Goes forward, stopping for five seconds whenever the average light
detected is too bright.  Says "ouch" whenever it stops. 
If the average light detected is sort of bright - but not too bright -
just slows down for a couple of seconds. */

void main() {
    start_press();
    forward();
    while(1) {
        int avg = (analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2;
        if ( avg < BRIGHT ) {
            ao();
            printf("Ouch\n");
            sleep(2.0);
            printf("\n");
            forward();
        } else {
            if (avg < SORT_OF_BRIGHT) {
                slow_down();
                printf("Oh, the glare\n");
                sleep(2.0);
                printf("\n");
                forward();
            }
        }
    }
}

/* starts the motors at full power in the forward direction */
void forward() {
    fd(RIGHT_MOTOR);
    fd(LEFT_MOTOR);
}

/* adjust motors to half power */
void slow_down() {
    motor(RIGHT_MOTOR, 50);
    motor(LEFT_MOTOR, 50);
}

Notice that this time our name is written with all lower case letters. This is because we intend for the name to refer to different values over time: the average light value is computed; we check whether it is very bright or sort of bright (or neither). Then we do this all over again. Because this name refers to a value that will change over time, we call it a variable.

To summarize, don't forget that you must declare a variable name in order to use it. That is, you must:

  1. list the variable name to be used
  2. indicate what type of value it will hold
  3. optionally set its value

Local vs global variables

  1. if declared within a function, a variable is called local to that function; it is only known in the context of that function.
  2. if declared outside of functions, then a variable is called global; it is known in every function in that file.

More on using while to control repetition

In many of the examples we considered last time, we used while(1) to indicate that wanted Interactive C to execute a block of statements over and over and over... The only thing that stops those programs is turning off the Handy Board. There are often times when we want to execute a block of statements over and over, but sometimes we want to stop before the board is turned off. We can accomplish this by specifying in the parentheses of the while the conditions under which the while should continue to execute. If these conditions ever evaluate to false, the repetition will stop.

For example, say that we want to modify our last program so that it stops either when the stop button is pressed or when one of the touch sensors is pressed.

/* A. Danyluk
   October 2008 */

int RIGHT_MOTOR = 1;   /* the right motor port */
int LEFT_MOTOR = 3;    /* the left motor port */

int RIGHT_LIGHT = 3;   /* the right light sensor port */
int LEFT_LIGHT = 5;    /* the left light sensor port */

int RIGHT_TOUCH = 11;  /* the right touch sensor port */
int LEFT_TOUCH = 14;   /* the left touch sensor port */

int BRIGHT = 20;       /* light sensor value considered to be very bright */
int SORT_OF_BRIGHT = 80; /* value considered to be sort of bright */

int avg;

/* Goes forward, stopping for five seconds whenever the average light
detected is too bright.  Says "ouch" whenever it stops. 
If the average light detected is sort of bright - but not too bright -
just slows down for a couple of seconds. */

void main() {
    start_press();
    forward();
    while(!stop_button() && !digital(LEFT_TOUCH) && !digital(RIGHT_TOUCH)) {
        avg = (analog(LEFT_LIGHT) + analog(RIGHT_LIGHT))/2;
        printf("%d\n", digital(LEFT_TOUCH));
        if ( avg < BRIGHT ) {
            ao();
            printf("Ouch\n");
            sleep(2.0);
            printf("\n");
            forward();
        } else {
            if (avg < SORT_OF_BRIGHT) {
                slow_down();
                printf("Oh, the glare\n");
                sleep(2.0);
                printf("\n");
                forward();
            }
        }
    }
    ao();
}

/* starts the motors at full power in the forward direction */
void forward() {
    fd(RIGHT_MOTOR);
    fd(LEFT_MOTOR);
}

/* adjust motors to half power */
void slow_down() {
    motor(RIGHT_MOTOR, 50);
    motor(LEFT_MOTOR, 50);
}

The general form of the while statement is:
while (condition) {
   statements to execute
}
If condition evaluates to true (i.e., a non-zero value), the body of the loop is executed. Otherwise, the body of the loop is ignored.

Any expression that qualifies as a condition in an if statement can also be used in a while statement (and vice versa).

Remember that the condition doesn't specify when you stop. It specifies the conditions under which you keep repeating! So to say that we want to stop either when the stop button is pressed or when a collision is detected, we have to say that the repetition should continue as long as the stop button is not pressed and as long as neither touch sensor is pressed.