Lego Proximity Detector
Home
Projects
People
Lego
Experiments

Articles on Lego:
Scanner
Vector Rover
Proximity Detection
Rotation sensor
Bot-Navigation
Links to Lego
The way Lego-rovers usually detect obstacles in their proximity is by bumping their bumpers into them and check the touch sensors. If you implement the proximity-detector you will have a way of knowing there is something out there even before the obstacle is actually reached.

The RCX emits fairly strong infrared light when communicating through the IR port. If we could see infrared light, it would probably be like a flashlight to us. Fortunately the light-sensor that comes with it can see the infrared light.

Try this little experiment: Configure the RCX so that you can see the sensor readings of the Light sensor on the display, then mount the light sensor just above the IR port on the RCX. Place the RCX close to the IR tower having the light sensor directly facing it. Download something to the RCX (anything). You will see the light values jump wildly as if the lights in the room were flashing. Well - in a way they are, its just not visible to us mere mortals. The light sensor is of course picking up the infrared light from the IR communication.

As with visible light the infrared light is reflected by everything. If you put something in front of the IR port (like a wall or something) it will reflect the infrared and the light-sensor will be able to see it flashing, this is how a proximity detector works. You flash the IR, and if the sensor senses flashing there is something facing it that is reflecting the light - if the sensor senses no such thing there is probably nothing in front of it (or something incredibly black that does not reflect the light). So all we have to do is to flash the IR every now and then while looking for flashes on the light-sensor.

Luckily for us the RCX has a command that activates the IR port. In NQC it is called SendMessage, in the Spirit.ocx it is called SendPBMessage. To keep flashing the IR light while driving about, my rovers does a SendMessage a couple of times each second. It doesn't matter what message you send, personally I send the value 255, but I have no reason to believe that it matters.

To detect reflecting obstacles we have to look for rapid changes in the light sensor reading. The best way to do this, I think, is to sample the sensor quite often and compare two and two readings. If the difference between them is more than a set threshold (I use 100 raw units) we count that as an impulse - the proximity detector has been tripped. This is very reliable, in my experience it detects almost anything from white walls to black boots or transparent soda bottles. Putting a small roof over the light-sensor to shield it from overhead light will to my experience enhance the working range of the sensor a great deal.

To actually use the readings from the detector for a wandering rover some sweetening of the data might be required. It has sort of a Geiger-counter like randomness to it so that the closer you are to an object, the more impulses you get. If your bot reacts immediately to the readings its movements might be jerky and not very efficient. I delay the readings by testing the proximity sensor for a set number of times, and if any of those readings count as an impulse, my bot will consider the space in front of it as untravelable until two complete cycles of sensor readings have passed without any impulses.

I have a global variable called IN_PROXIMITY that I treat as a virtual sensor. I have then written a small "driver task" that constantly polls the light sensor and checks for changes larger than 100 units. This is done seven times and the largest change gathered during this time (that is >100) is used as the sensor value and assigned to IN_PROXIMITY.

This works almost perfectly. To account for the rare sampling cycle where no spikes is gathered even though the bot is facing a wall I do not reset the sensor value immediately. If no IR reflection was sensed IN_PROXIMITY is set to exactly 100, and not before a second sampling sequence has passed with no reflections is the sensor value really reset to 0. This works completely reliable for my small bot.

scanflash.gif (29252 bytes) I taped the rover with a IR-sensitive DV camera just to check how the lights were acting. I found that it is approximately on for about 1/25 of a second (1 frame) and off for between 3/25 and 4/25 of a second. This GIF animation is timed as correctly as I could. I just did this so I have not taken it into account in the code below, but John and James Cooper have optimized the proximity detection based on similar observations. You can read their post here.

This is my "driver task", it assumes that the light sensor is attached at IN_2 and that it is configured for RAW values:

task proximitydriver
{
  newluxsample = IN_2;
  proxsamp = 0;
  while (true)
  {
    proxsamp -= 1;
    maxprox = 0;
    SendMessage(255);
    oldluxsample = newluxsample;
    newluxsample = IN_2;
    oldluxsample -= newluxsample;
    if (oldluxsample<0)
    {
      oldluxsample *= -1;
    }
    if (oldluxsample>100)
    {
      if (oldluxsample>maxprox)
      {
        maxprox = oldluxsample;
      }
    }
    if (proxsamp <0)
    {
      if (maxprox == 0)
      {
        if (IN_PROXIMITY > 100)
        {
          IN_PROXIMITY = 100;
        }
        else
        {
          IN_PROXIMITY = maxprox;
        }
      }
      else
      {
        IN_PROXIMITY = maxprox;
      }
      proxsamp = proxisamples;
      maxprox = 0;
    }
  }
}

Variables:

  • proxsamp - a counter that counts down the number of samples that will be made until IN_PROXIMITY should be updated
  • maxprox  - largest fluctuation gathered in this sampling sequence
  • oldluxsample, newluxsample - the former and current RAW sensor reading
  • proxisamples - constant, number of samples to gather each cycle

See my Vector Rover for an example of a bot using proximity detection.

Conversations on this topic:
Optimized proximity detection
Up ] Scanner ] Vector Rover ] [ Proximity Detection ] Rotation sensor ] Bot-Navigation ] Links to Lego ]
Comments and questions: simen@mop.no