Home > CollectorBot, My Robots, RobotC Code > Differential Light Sensor – Two NXT Light Sensors as One

Differential Light Sensor – Two NXT Light Sensors as One

 Collector Robot One of the goals of the Collector Robot is to push pucks to a light source “Home Base” and leave them there.  In order to accomplish this, the robot must be able to home in on a light source.  In order to home, the robot needs to have some method for finding the light, and adjusting its course to drive toward it.

I created a virtual differential light sensor using two NXT light sensors mounted on the robot facing forward, angled to the left and right.  This gives me a good starting point to read values from each sensor to determine the difference in intensity and therefore determining the STEERING value to drive the robot toward the light.

Download the driver: DiffLight-driver.h
Download this too: mathext.h

Purpose

One of the challenges I ran into was the many things a robot can do with two light sensors combined in this configuration.

  • check the intensity of each light sensor separately.
  • calculate the difference between the sensors for applying a steering value.
  • determine which sensor sees the most light at a given time.
  • determine which sensor sees the least amount of light at a given time.
  • auto calibrate a dark/light threshold value for each sensor.
  • what is the maximum intensity each sensor has recorded?
  • what is the minimum intensity each sensor has recorded?
  • determine an overall average light from the sensors.
  • determine if the robot is close to a light source.
  • determine if the robot is facing a light or not.

So you can see, this list screams – Create a driver!  So I did.

The Driver Implementation

The differential light sensor driver consolidates the logic and data necessary to accomplish the above tasks.  The following represents the current functionality within the differential light sensor driver class I created.

//FUNCTION PROTOTYPES ---------------------------------------------------
void DiffLight_init();          //INITIALIZE THE SENSORS
int DiffLight_LeftThreshold();  //CALC'D RIGHT THRESHOLD VALUE
int DiffLight_RightThreshold(); //CALC'D RIGHT THRESHOLD VALUE
int DiffLight_Threshold();      //CALC'D THRESHOLD BETWEEN LIGHT & DARK
int DiffLight_Average();        //AVERAGE CURRENT LIGHT VALUE
int DiffLight_Maximum();        //LOWEST OF LOW READING FROM SENSORS
int DiffLight_MaximumAvg();     //AVERAGE OF LEFT & RIGHT MIN VALUES
int DiffLight_Minimum();        //HIGHEST READING FROM EITHER SENSOR
int DiffLight_MinimumAvg();     //AVERAGE OF LEFT & RIGHT MAX VALUES
int DiffLight_Difference();     //DIFFERENCE BETWEEN LEFT & RIGHT VALUES
typLightSensorBool DiffLight_State(); //FACING LIGHT SOURCE OR NOT
bool DiffLight_IsHome();              //IS AT THE LIGHT SOURCE OR NOT
//-----------------------------------------------------------------------

One of the interesting aspects of this driver, is its auto-calibration feature.  I was getting tired of setting and setting constants for light and dark values.  I wanted to robot to build a knowledge  base of its environment and calculate decisions on that data.  All of the functions above take into account data the sensors collect and return values relative to the environment, no matter how light or dark home base and the ambient light are.  This is accomplished by storing min and max values for each sensor giving the robot a basis for understanding light and dark thresholds.

The work horses driver functions for the collector robot code are DiffLight_Difference, DiffLight_State() and DiffLight_IsHome().

DiffLight_Difference() is a simple function that returns the difference between the current values of the two light sensors.  This value shows if a light source is on the left or right side of the robot.

DiffLight_State() uses an algorithm to determine if the virtual sensor is facing toward or away from a light source (home).  You might think this is an easy task, but experimentation showed me it can be more difficult to implement.  I wound up implementing hysteresis into the function to prevent the sensor from oscillating back and forth near border zones.  Once locked into IS_LIGHT or IS_DARK, the sensor needs to overcome a hysteresis factor to switch states.

DiffLight_IsHome() is another useful function I implemented to determine if the robot is very close to the light source.  I wanted a generic method for determining this, but again it turned out to be a little more complicated than expected.  I wanted to know when I was ~90% to the maximum light value to determine “HOME” success.  With auto-calibration, the sensor is unable to make a good decision until it gathers enough information about its environment.  I implemented a minimum difference factor that makes sure the min and max values are at least 30 before allowing home to be calculated.

In addition, I added a structure to capture several values of interest about the sensors that can be used in internal calculations.

typedef struct {
  ubyte rtMax;  //RIGHT LIGHT SENSOR MAX RECORDED VALUE SINCE START
  ubyte rtMin;  //RIGHT LIGHT SENSOR MIN RECORDED VALUE SINCE START
  ubyte rtVal;  //RIGHT LIGHT SENSOR CURRENT VALUE
  ubyte ltMax;  //LEFT LIGHT SENSOR MAX RECORDED VALUE SINCE START
  ubyte ltMin;  //LEFT LIGHT SENSOR MIN RECORDED VALUE SINCE START
  ubyte ltVal;  //LEFT LIGHT SENSOR CURRENT RECORDED
} sDiffLight;
sDiffLight _dlSensor;

A task that continually runs to read the values and populate the structure.  The functions utilize the structure values and return appropriate values.  The base code is encapsulated to keep the results consistent for all behaviors that require values.  I am a fan of hiding complexity and doing things once.

To use the driver, include the file in your robot code and start the task.

#include "driver\DiffLight-driver.h"

StartTask(DifferentialLightSensor);

That’s it.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: