Sonar Drivers for the Handy Board

This page documents how to connect the Polaroid 6500 Series Ultrasonic Ranging System to the Handy Board. These updated schematics and drivers do not require the removal of a motor driver chip, and no assembly code is used to interface with the sonar system!

Parts List

In addition to the 6500 series Polaroid module, the following components and materials are required:

Connection Diagram

The following diagram shows how the Polaroid Ranging Module is connected to the Handy Board. For the three wires that are plugged singly into the Handy Board (i.e., to Handy Board Port D5, Port D4, and Sensor Input 7), 22 gauge solid hookup wire is ideal. For the motor power connector, use the same wiring technique as for typical Handy Board sensor devices.

****** You must install the 0.1 µF capacitor in the C7 position on the sonar board!! Most versions of the sonar board will not work properly without it!! This is true even if you are using the HB Expansion Board. ******

Please note that the Polaroid 9-pin connector is illustrated from a bottom view,
as if you were holding the connector in your hand looking at its pins.

The Driver Code

There is an initialization routine, and two versions of the driver. These routines may simply be copied into your Interactive C programs.


First, the initialization code:

void sonar_init() {
    bit_set(0x1009, 0x30);      /* ddrd */
    bit_set(0x1021, 1);         /* at tctl2, */
    bit_clear(0x1021, 2);       /* set tic3 for rising edge */

The first bit_set instruction establishes the two Port D pins as 6811 outputs. These two pins are used to control the sonar’s transmit pulse (Port D5, connected to the sonar INIT pin) and user-adjustable blanking (Port D4, to the sonar’s BINH pin).

The second pair of bit_set and bit_clear instructions modifies the settings in the 6811’s TCTL2 register, telling timer input 3 pin to trigger on rising edges. This pin is connected from the sonar’s ECHO signal, which rises from 0 to 1 when the return sonar pulse is received.

Bit_set and bit_clear operations are used, rather than poke instructions, so as to not affect the settings of any other bits in these two 6811 registers.

Simple Sonar Driver

This driver performs the basic task of triggering the sonar pulse by bringing high the INIT signal, and then measuring elapsed time until the ECHO signal goes high. Because the ECHO signal is plugged into a 68HC11 timer input, the timer subsystem is used to automatically capture the time value when the ECHO signal goes high. This is the purpose of the earlier settings to the TCL2 register in the initialization routine. Therefore, all the main driver needs to do is record the global time value when the INIT signal is raised, clear the timer, wait until the ECHO signal goes high, and then calculate the total elapsed time by looking at the captured time value in the timer input’s register:

int sonar_sample() {
    int start_time;
    poke(0x1023, 1);                /* clear tic3 flag */
    start_time= peekword(0x100e);   /* capture start time */
    bit_set(0x1008, 0x20);          /* trigger pulse */
    while (!(peek(0x1000) & 0x1)) { /* wait until receive echo */
        if ((peekword(0x100e) - start_time) < 0) {
            /* if too much time has elapsed, abort */
            bit_clear(0x1008, 0x20);
            return -1;
        defer();                    /* let others run while waiting */
    bit_clear(0x1008, 0x20);        /* clear pulse trigger */
    return peekword(0x1014) - start_time;   /* tic3 has time of echo */

Let’s go through the code in detail. First, an integer variable is created to keep track of the starting time of the sonar ping. Next, the TIC3 flag (for Timer Input Capture 3, the pin that is connected from the ECHO signal) is cleared, by writing a “1” into its bit position in the TFLG1 register. The timer is now set up to capture the global time value when the ECHO signal goes high.

Next, the start time is stored from the global TCNT time register (at address 0x100e). TCNT increments every 0.5 microseconds (2,000,000 counts per second). Then the sonar pulse is triggered, by setting bit 5 in the Port D register.

Now the routine enters a while loop, waiting for the ECHO pulse to go high. Remember, the real work is going to be done by the 68HC11 timer subsystem, which will automatically capture the exact TCNT value when the ECHO pulse is received. The purpose of this while loop is mostly to just wait for that value to be captured, so the sonar_sample() routine can report it. Also, the while loop checks if too much time has elapsed; if so, it returns an error value of –1.

Notice that the while loop includes a defer() instruction each time through the loop. This is a special Interactive C command that yields control to any other C processes that might be running. Because of this, the while loop doesn’t waste much processing time while it is waiting for the sonar ping to return. The precision timing is being done by the underlying 68HC11 timer system, so this while loop can be sloppy and just occasionally check if the operation has completed or timed-out.

The remainder of the routine cleans up by turning off the pulse trigger, and calculates the total elapsed time by subtracting the starting time value from the echo time captured in the Timer Input Capture 3 register.

Sonar Driver with Close-Up Capability

The Polaroid module normally blanks the receive input for the first 2.38 milliseconds (corresponding to 1.33 feet, according to the Polaroid manual) after a ping is produced, so that the sensor does not detect residual ringing of the sonar transducer after the transmit pulse. This default mode of operation limits the sensor to detect distances of 1.33 feet and beyond.

This limitation may be circumnavigated with the use of the BINH, or Blanking INHibit, input. The module will accept receive echo signals as soon as the BINH input is taken high. Some blanking interval is needed; however, it can be much shorter than 2.38 millisconds, allowing targets much closer than 1.33 feet inches to be detected.

The following routine extends the earlier sonar_sample() by turning on the blanking inhibit 0.5 milliseconds after the sonar ping is generated. This allows the sensor to detect objects down to a few inches.

int sonar_closeup() {
    int start_time;
    poke(0x1023, 1);                /* clear tic3 flag */
    start_time= peekword(0x100e);
    poke(0x1008, 0x20);
    while ((peekword(0x100e) - start_time) < 1000);
    bit_set(0x1008, 0x30);          /* turn on BINH */
    while (!(peek(0x1000) & 0x01)) {
        if ((peekword(0x100e) - start_time) < 0) {
            /* if too much time has elapsed, abort */
            bit_clear(0x1008, 0x30);
            return -1;
    bit_clear(0x1008, 0x30);
    return peekword(0x1014) - start_time;   /* 0x1014 is tic3 */

A Test Routine

The following test routine may be used to demostrate proper operation of the Polaroid sonar device. Note the 50 millisecond delay between successive calls to the sonar driver; some delay between sonar pings is necessary for the device to operate properly.

void sonar_display()
    while (1) {
        int result;
        result= sonar_sample();
        if (result != -1) printf("%d\n", result);
        else printf("*******\n");

Converting Time Measurements to Actual Distance

Sound travels approximately 1.1 feet per millisecond in average atmospheric conditions. Since the sonar ping must travel out to the target and back to the sensor, one must use the round-trip travel time when calculating from time to distance.

The sonar routines presented here report elapsed time in the 68HC11’s TCNT units, which count at the rate of 2,000,000 counts per second, or 0.5 microseconds per count. Thus, for example, a reading of 10000 corresponds to a time of 5 millseconds. Multiplying by the sound travel rate of 1.1 ft/millisecond yields a travel of 5.5 feet. Accounting for the round trip time, this corresponds to a target that is 2.75 feet from the sensor.

In another example, the Polaroid manual states the default blanking interval of 2.38 milliseconds corresponds to a distance of 1.33 feet (the closest object the sensor can measure without using the blanking inhibit feature). That's a travel of 2.66 ft in 2.38 milliseconds, yielding the 1.1 ft/ms figure.

Sonar Driver Program File

All of the above programs are contained in the driver file sonar.c.


The Polaroid 6500 Series Modules may be obtained directly from Polaroid in their OEM kit #606783, which consists of two sets of ranging boards and transducers. Contact info is in the Vendors/Robot Stuff area of the Handy Board site.

Additionally, Wirz Electronics and Acroname sell single pairs of the ranging board and transducer.


Thanks to Kent Farnsworth for his notes on using the Polaroid 6500 system.

Back to Handy Board Home
Fred Martin / MIT Media Laboratory
Created: Sat Nov 22 13:59:11 1997 Last updated: Thu Oct 14 12:13:25 1999