Go to the first, previous, next, last section, table of contents.

The IC Library File

Library files provide standard C functions for interfacing with hardware on the robot controller board. These functions are written either in C or as assembly language drivers. Library files provide functions to do things like control motors, make tones, and input sensors values.

IC automatically loads the library file every time it is invoked. Depending on which 6811 board is being used, a different library file will be required. IC may be configured to load different library files as its default; for the purpose of the 6.270 contest, the on-line version of IC will be configured appropriately for the board that is in use.


As of this writing, there are five related 6811 systems in use:
the 1991 6.270 Board (the "Revision 2" board), the 1991 Sensor
Robot, the Rev. 2.1 6.270 Board (from 1992), the Rev. 2.2 6.270 Board
(from 1993), and the Rev. 2.21 6.270 Board (from 1994).  This writing
covers the Rev. 2.21 board only; documentation for the other systems
is available elsewhere.

On the MIT Athena system, IC library files are located in the following directory:

`/mit/6.270/lib/ic'

To understand better how the library functions work, study of the library file source code is recommended. The main library file for the Rev. 2.2 6.270 Board is named lib_r22.lis.

Output Control

DC Motors

Motor ports are numbered from 0 to 5; ports for motors 0 to 3 are located on the Microprocessor Board while motors 4 and 5 are located on the Expansion Board.

Motor may be set in a "forward" direction (corresponding to the green motor LED being lit) and a "backward" direction (corresponding to the motor red LED being lit).

The functions fd(int m) and bk(int m) turn motor m on forward or backward, respectively, at full power. The function off(int m) turns motor m off.

The power level of motors may also be controlled. This is done in software by a motor on and off rapidly (a technique called pulse-width modulation. The motor(int m, int p) function allows control of a motor's power level. Powers range from 100 (full on in the forward direction) to -100 (full on the the backward direction). The system software actually only controls motors to seven degrees of power, but argument bounds of $-$100 and $+$100 are used.

void fd(int m)
Turns motor m on in the forward direction. Example: fd(3);
void bk(int m)
Turns motor m on in the backward direction. Example: bk(1);
void off(int m)
Turns off motor m. Example: off(1);
void alloff()
void ao()
Turns off all motors. ao is a short form for alloff.
void motor(int m, int p)
Turns on motor m at power level p. Power levels range from 100 for full on forward to -100 for full on backward.

Servo Motor

Servos are motors with internal position feedback which you can accurately command to a given orientation. Servos will actively seek to move to and remain at the orientation they are commanded to go to. Servos are useful for aiming sensors or moving actuators through a limited arc. They are generally able to sweep through about 180 degrees and no more.

Library routines allows control of a single servo motor. The servo motor has a three-wire connection: power, ground, and control. There is a dedicated connection for the servo on the main board at the top of the bank of connectors which are above and to the left of the main power switch. A three prong connector with ground on the left, power in the middle, and control on the right should be used to plug the servo into its connector. So long as you are sure to get power in the middle, the servo will not be damaged by plugging it in backwards, but will simply not work until it is plugged in properly.

The position of the servo motor shaft is controlled by a rectangular waveform that is generated on the A7 pin. The duration of the positive pulse of the waveform determines the position of the shaft. The acceptable width of the pulse varies for different models of servos, but is approximately 700 timer cycles minimum and 4000 timer cycles maximum, where the 6811's timer runs at 2MHz. The pulse is repeated approximately every 20 milliseconds.

void servo_on()
Turns the servo signal on. You must call this function before the servo will move.
void servo_off()
Turns servo signal off. The servo will no longer try to move to any particular position and will move freely. When you are not actively using the servo, turning it off will save power and processor cycles.
int servo(int period)
Sets the high time of the servo signal to period timer cycles so long as that falls within the acceptable range for the servo. Otherwise it trunctates the value to the closest the servo is physically able to go to. It returns the thresholded version of the period you gave it. Remember that servos have a finite reaction time which, while very fast to human senses of time, is very slow to a processor. If you are resetting the servo angle in a tight loop it may well never catch up with you.
int servo_rad(float angle)
Sets the commanded orientation of the servo to approximately the angle in radians that it is given and returns the pulse width in timer counts which the servo was actually commanded with. The minimum pulse width is defined to be zero radians and the maximum is defined to be pi radians.
int servo_deg(float angle)
Sets the commanded orientation of the servo to approximately the angle in degrees that it is given and returns the pulse width in timer counts which the servo was actually commanded with. The minimum pulse width is defined to be zero degrees and the maximum is defined to be 180 degrees.
int radian_to_pulse(float angle)
Converts the angle given in radians to the corresponding pulse width in timer counts. Input range is 0.0 to 3.14.
int degree_to_pulse(float angle)
Converts the angle given in degrees to the corresponding pulse width in timer counts. Input range is 0.0 to 180.0.

Unidirectional Drivers

LED Drivers

There are two output ports located on the Expansion Board that are suitable for driving LEDs or other small loads. These ports draw their power from the motor battery and hence will only work when that battery is connected.

The following commands are used to control the LED ports:

void led_out0(int s)
Turns on LED0 port if s is non-zero; turns it off otherwise.
void led_out1(int s)
Turns on LED1 port if s is non-zero; turns it off otherwise.

Expansion Board Motor Ports

Motor ports 4 and 5, located on the Expansion Board, may also be used to control unidirectional devices, such as a solenoid, lamp, or a motor that needs to be driven in one direction only. Each of the two motor ports, when used in this fashion, can independently control two such devices.

To use the ports unidirectionally, the two-pin header directly beneath the motor 4 and 5 LEDs is used.

void motor4_left(int s)
Turns on left side of motor 4 port if s is non-zero; turns it off otherwise.
void motor4_right(int s)
Turns on right side of motor 4 port if s is non-zero; turns it off otherwise.
void motor5_left(int s)
Turns on left side of motor 5 port if s is non-zero; turns it off otherwise.
void motor5_right(int s)
Turns on right side of motor 5 port if s is non-zero; turns it off otherwise.

Sensor Input

Digital Input

int digital(int p)
Returns the value of the sensor in sensor port p, as a true/false value (1 for true and 0 for false). Sensors are expected to be active low, meaning that they are valued at zero volts in the active, or true, state. Thus the library function returns the inverse of the actual reading from the digital hardware: if the reading is zero volts or logic zero, the digital() function will return true.
int dip_switch(int sw)
Returns value of DIP switch sw on interface board. Switches are numbered from 1 to 4 as per labelling on actual switch. Result is 1 if the switch is in the position labelled "on," and 0 if not.
int dip_switches()
Returns value on DIP switches as a four-bit binary number. Left-most switch is most significant binary digit. "On" position is binary one.
int choose_button()
Returns value of button labelled Choose: 1 if pressed and 0 if released. Example:
    /*  wait until choose button pressed  */
    while (!choose_button()) {}
int escape_button()
Returns value of button labelled Escape. Example:
    /*  wait for button to be pressed; then
        wait for it to be released so that
        button press is debounced           */
    while (!escape_button()) {}
    while (escape_button()) {}

Analog Inputs

int analog(int p)
Returns value of sensor port numbered p. Result is integer between 0 and 255. If the analog() function is applied to a port that is implemented digitally in hardware, then the value 255 is returned if the hardware digital reading is 1 (as if a digital switch is open, and the pull up resistors are causing a high reading), and the value 0 is returned if the hardware digital reading is 0 (as if a digital switch is closed and pulling the reading near ground). Ports are numbered as marked on the Microprocessor Board and Expansion Board.
int frob_knob()
Returns a value from 0 to 255 based on the position of the potentiometer labeled frob knob.
int motor_force(int m)
Returns value of analog input sensing current level through motor m. Result is integer between 0 and 255, but typical readings range from about 40 (low force) to 100 (high force). The force-sensing circuitry functions properly only when motors are operated at full speed. The circuit returns invalid results when motors are pulse-width modulated because of spikes that occur in the feedback path. The force-sensing circuitry is implemented for motors 0 through 3.

Infrared Subsystem

The infrared subsystem is composed of two parts: an infrared transmitter, and infrared receivers. Software is provided to control transmission frequency and detection of infrared light at two frequencies.

Infrared Transmission

void ir_transmit_on()
Enables transmission of infrared light through ir out port.
void ir_transmit_off()
Disables transmission of infrared light through ir out port.
void set_ir_transmit_period(int period)
Sets infrared transmission period. period determines the delay in half.microseconds between transitions of the infrared waveform. If period is set to 10,000, a frequency of 100 Hz. will be generated. If period is set to 8,000, a frequency of 125 Hz. will be generated. The decoding software is capable of detecting transmissions on either of these two frequencies only.
void set_ir_transmit_frequency(int frequency)
Sets infrared transmission frequency. frequency is measured in hertz. Upon a reset condition, the infrared transmission frequency is set for 100 Hz. and is disabled.

Infrared Reception

In a typical 6.270 application, one robot will be broadcasting infrared at 100 Hz. and will set its detection system for 125 Hz. The other robot will do the opposite. Each robot must physically shield its IR sensors from its own light; then each robot can detect the emissions of the other.

The infrared reception software employs a phase.locked loop to detect infrared signals modulated at a particular frequency. This program generates an internal squarewave at the desired reception frequency and attempts to lock this squarewave into synchronization with a waveform received by an infrared sensor. If the error between the internal wave and the external wave is below some threshold, the external wave is considered "detected." The software returns as a result the number of consecutive detections for each of the infrared sensor inputs.

While enabled, the infrared reception software requires a great deal of processor time. Therefore, it is desirable to disable the IR reception whenever it is not being actively used.

Up to four infrared sensors may be used. These are plugged into positions 4 through 7 of the digital input port. These ports and the remainder of the digital input port may be used without conflict for standard digital input while the infrared detection software is operating.

The following library functions control the infrared detection system:

void ir_receive_on()
Enables the infrared reception software. The default is disabled. When the software is enabled, between 20% and 30% of the 6811 processor time will be spent performing the detection function; therefore it should only be enabled if it is being used. You must wait at least 100 milliseconds after starting the reception before the data is valid.
void ir_receive_off()
Disables the infrared reception software.
void set_ir_receive_frequency(int f)
Sets the operating frequency for the infrared reception software. f should be 100 for 100 Hz. or 125 for 125 Hz. Default is 100.
int ir_counts(int p)
Returns number of consecutive squarewaves at operating frequency detected from port p of the digital input port. Result is number from 0 to 255. p must be 4, 5, 6, or 7 Random noise can cause spurious readings of 1 or 2 detections. The return value of ir_counts() should be greater than three before it is considered the result of a valid detection. You must wait at least 100 milliseconds after starting the reception before the ir_counts() data is valid.

Shaft Encoders

Shaft encoders can be used to count the number of times a wheel spins, or in general the number of digital pulses seen by an input. Two types of shaft encoders can be made using 6.270 sensors: optical encoders which use optical switches whose beam is periodically broken by a slotted wheel, or magnetic encoders which uses hall effect sensors which change state when a magnet on a shaft rotates past.

Shaft encoders are implemented using the input timer capture feature on the 6811. Therefore processing time is only used when a pulse is actually being recorded, and even very fast pulses can be counted. Because digital ports 0 and 1 are the only two input capture channels available for use on the 6.270 board, only two channels of shaft encoding are possible.

The encoding software for the 6.270 board keeps a running count of the number of pulses each enabled encoder has seen. The number of counts is set to 0 when a chanel is first enabled and when a user resets that channel. Because the counters are only 16-bits wide, they will overflow and the value will appear negative after 32,767 counts have been accumulated without a reset.

As shaft encoders are an optional feature and not part of the standard hardware of the 6.270 board, the library routines which read them are not loaded on start up.

In order to load the following routines for use in your programs, load the file encoders.lis. This file is in the standard 6.270 library directory so IC will find it by this name.

The actions of the shaft encoders are commanded and the results are read using the following routines. The argument encoder to each of the routines specifies which shaft encoder the function should affect. This value should be 0 for digital port 0 or one for digital port 1. Arguments out of the range 0 to 1 have no useful effect.

void enable_encoder(int encoder)
Enables the given encoder to start counting pulses and resets its counter to zero. By default encoders start in the disabled state and must be enabled before they start counting.
void disable_encoder(int encoder)
Disables the given encoder and prevents it from counting. Each shaft encoder uses processing time every time it receives a pulse while enabled, so they should be disabled when you no longer need the encoder's data.
void reset_encoder(int encoder)
Resets the counter of the given encoder to zero. For an enabled encoder, it is more efficient to reset its value than to use enable_encoder() to clear it.
int read_encoder(int encoder)
Returns the number of pulses counted by the given encoder since it was enabled or since the last reset, whichever was more recent.

Time Commands

System code keeps track of time passage in milliseconds. Library functions are provided to allow dealing with time in milliseconds (using long integers), or seconds (using floating point numbers).

void reset_system_time()
Resets the count of system time to zero milliseconds.
long mseconds()
Returns the count of system time in milliseconds. Time count is reset by hardware reset (i.e., pressing reset switch on board) or the function reset_\-system_\-time(). mseconds() is implemented as a C primitive (not as a library function).
float seconds()
Returns the count of system time in seconds, as a floating point number. Resolution is one millisecond.
void sleep(float sec)
Waits for an amount of time equal to or slightly greater than sec seconds. sec is a floating point number. Example:
/*  wait for 1.5 seconds  */
sleep(1.5);
void msleep(long msec)
Waits for an amount of time equal to or greater than msec milliseconds. msec is a long integer. Example:
/*  wait for 1.5 seconds  */
msleep(1500L);

Tone Functions

Two simple commands are provided for producing tones on the standard beeper.

void beep()
Produces a tone of 500 Hertz for a period of 0.3 seconds. Returns when the tone is finished.
void tone(float frequency, float length)
Produces a tone at pitch frequency Hertz for length seconds. Returns when the tone is finished. Both frequency and length are floats. In addition to the simple tone commands, the following functions can be used asynchronously to control the beeper driver.
void set_beeper_pitch(float frequency)
Sets the beeper tone to be frequency Hz. The subsequent function is then used to turn the beeper on.
void beeper_on()
Turns on the beeper at last frequency selected by the former function. The beeper remains on until the beeper_off function is executed.
void beeper_off()
Turns off the beeper.

Menuing and Diagnostics Functions

These functions are not loaded automatically, but they are available for you to use if you wish in the standard 6.270 library directory. They provide a standardized user interface for prompting users for input using the choose and select buttons and the frob knob. You may wish to use this library for debugging the state of your robot while away from the terminal or for changing thresholds or gains on the fly.

menu.c

Load menu.c to be able to use these functions.

int select_string(char choices[][],int n)
Interactively selects a string from an array of string (two-dimensional array of characters) of length n and returns an integer when a button is pressed. If the button pressed was the choose button, it returns the index into the array of the selected string, otherwise it returns -1. Example of use:
        char a[3][14]={"Analog Port ","Digital Port ","Quit"};
        int port,index=select_string(a,3);

        if(index>-1 && index<2)
           port=select_int_value(a[index],0,27);
int select_int_value(char s[],int min_val,int max_val)
float select_float_value(char s[],float min_val,float max_val)
Interactively selects and returns a number between min_val and max_val which is selected by adjusting the frob knob until the appropriate value is displayed then pressing a button. If the escape button was pressed, returns -1 (or -1.0) regardless of the value chosen. Otherwise returns the chosen value. Remember that the frob knob only returns one of 255 values, so if the range is greater than that not all values will be possible choices.
int chosen_button()
Checks the user buttons and returns CHOOSE_B if the choose button is pressed, ESCAPE_B if the escape button is pressed, and NEITHER_B if neither button is pressed. If both buttons are pressed, the choose button has priority.
int wait_button(int mode)
Waits for either user button to execute the action appropriate to mode then returns which button was pressed. The choices for mode are: DOWN_B -- wait until either button is pressed; UP_B -- wait until no buttons are pressed; CYCLE_B -- wait until a button is depressed and then all depressed buttons are released before returning.

diagnostic.c

Load menu.c and diagnostic.c to be able to use these functions. You can easily copy diagnostic.c and modify the control_panel function to call your own routines.

void control_panel()
General purpose control panel to let you view inputs, frob outputs, or set A to D thresholds. Pressing the escape button from the main menu or selecting "Quit" exits the control panel.
int view_average_port(int port,int samples)
Displays the analog reading of the given port until a button is pressed. If the button is the choose button, it then samples the reading at the given port, averages samples readings together, then prints and returns the average result. If the button pushed was the ecape button, it returns -1.
void view_inputs()
General purpose input status viewer using the standard menuing routines to show digital inputs, analog inputs, frob knob, dip switches, and motor force inputs. Pressing escape at any time exits the viewer.
void frob_outputs()
General purpose output frobber. Uses the standard menuing routines to let you control the motors, led outputs, ir output, and the servo. Pressing escape from the main menu or selecting "Quit" exits the frobber.

Go to the first, previous, next, last section, table of contents.