Navigating a Simple Maze Using a Light Sensor

From ROBOTC API Guide
Jump to: navigation, search
ArduinoArduino Tutorials and Guided ProjectsLego + Arduino, Mobile Robotics Platform → Tutorials/Arduino Projects/Mobile Robotics/Lego/Navigating Simple Maze using a Light Sensor

Contents

Video

Lego+Arduino robot using the light sensor to navigate a maze


The Maze

What if the Maze you were trying to navigate had no vertical surfaces to detect? Say, each of the "walls" of the maze was actually a chasm that your robot would fall into if it didn't detect them. The touch sensor would be useless, and if you didn't know the size of the maze, you'd hardly want to risk your robot trying to figure out the correct distances to drive.

What you could do, however, is use the light sensor to detect the boundaries of these potential pits and avoid them.

For this maze, we are going to change the layout slightly from previous ones to accommodate the light sensor's properties.

The Maze

The robot's objective is to get from its starting place to the marked end zone.

Programming the Robot

In concept, this maze is fairly similar to the one that requires a touch sensor: the robot drives forward until it detects something, stops, backs up, turns, and continues forward, repeating this series until it hits the end of the maze.

What is different is that the light sensor has to be a bit more fine tuned to detect the boundary between open ground and the maze.

So, we're going to borrow a number of simple functions from our earlier project in order to help speed things along.

void DriveBackward()
{
  motor[leftServo] = -100;
  motor[rightServo] = -100;
  wait1Msec(400);
}
 
void TurnRight(int time)
{
  motor[leftServo] = 100;
  motor[rightServo] = -100;
  wait1Msec(time); 
}
 
void TurnLeft(int time)
{
  motor[leftServo] = -100;
  motor[rightServo] = 100;
  wait1Msec(time);  
}
 
void Stop()
{
  motor[leftServo] = 0;
  motor[rightServo] = 0;
}

Now, all we need is a function that will bring us up to the lines and detect them. We'll take the code we made for stopping at a line, and modify it a bit to also make the robot back away from the line when it is detected. (Remember to code this function last in order to allow it to call upon previous functions in the program.)

void driveForwardUntilDark ()
  {
    while (SensorValue[lightSensor] < 60) //drive forward until the sensor detects a line
      {
        motor[leftServo]=100;
        motor[rightServo]=100;
      }
     Stop(); //make sure to put stops in between actions to check the momentum of the last move
     DriveBackward(); // back away from the line in order to get room to turn
     Stop();
  }

Only one thing remains to be done. Whenever the robot detects the last line on the edge of the end zone, it doesn't have to turn. It needs to go straight into the endzone. Since this is a one time thing, it isn't worth making a function for driving straight. So we're just going to add this little piece of code to the end of the program:

 //One last straight drive to get us into the end zone
 motor[leftServo]=100;
 motor[rightServo]=100;
 wait1Msec(2000);

Now, when we put all of these things together, with turns in the correct direction and the correct place, we get a program that looks something like this:

#pragma config(CircuitBoardType, typeCktBoardUNO)
#pragma config(PluginCircuitBoard, typeShieldDFRobotMotor)
#pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, anlg0,  lightSensor,    sensorReflection)
#pragma config(Sensor, dgtl3,  lightLED,       sensorDigitalOut)
#pragma config(Motor,  motor_5,         rightServo,    tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl5, dgtl4)
#pragma config(Motor,  motor_6,         leftServo,     tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl6, dgtl7)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
void DriveBackward()
{
  motor[leftServo] = -100;
  motor[rightServo] = -100;
  wait1Msec(400);
}
 
void TurnRight(int time)
{
  motor[leftServo] = 100;
  motor[rightServo] = -100;
  wait1Msec(time);
}
 
void TurnLeft(int time)
{
  motor[leftServo] = -100;
  motor[rightServo] = 100;
  wait1Msec(time);
}
 
void Stop()
{
  motor[leftServo] = 0;
  motor[rightServo] = 0;
}
 
void driveForwardUntilDark ()
  {
    while (SensorValue[lightSensor] < 60) //drive forward until the sensor detects a line
      {
        motor[leftServo]=100;
        motor[rightServo]=100;
      }
     Stop(); //make sure to put stops in between actions to check the momentum of the last move
     DriveBackward(); // back away from the line in order to get room to turn
     Stop();
  }
 
 
 
task main()
{
 driveForwardUntilDark();
 TurnLeft(705);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnRight(650);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnRight(650);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnLeft(705);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnLeft(655);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 
 //One last straight drive to get us into the end zone
 motor[leftServo]=100;
 motor[rightServo]=100;
 wait1Msec(2000);
}

This should work, right?

But what's this? The robot's turning randomly at the beginning? We can't have that, now can we?

A problem that some programs that try to use the light sensor immediately often encounter is that the sensor is prone to giving off false readings for the first few milliseconds of a program. While this is not a problem in most cases, this particular program does not work properly if the sensor is not giving the correct reading.

There are multiple ways to solve this. One, of course, is to have the robot wait for a couple seconds at the beginning of the program. Another, the one we use here, is to have the robot move forward on a timed command for a less than a second, then switch over to the function that uses the sensor to detect lines.

With the addition of the short move at the start, our final program becomes this:

#pragma config(CircuitBoardType, typeCktBoardUNO)
#pragma config(PluginCircuitBoard, typeShieldDFRobotMotor)
#pragma config(UART_Usage, UART0, uartSystemCommPort, baudRate200000, IOPins, dgtl1, dgtl0)
#pragma config(Sensor, anlg0,  lightSensor,    sensorReflection)
#pragma config(Sensor, dgtl3,  lightLED,       sensorDigitalOut)
#pragma config(Motor,  motor_5,         rightServo,    tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl5, dgtl4)
#pragma config(Motor,  motor_6,         leftServo,     tmotorInternalHBridgeSinglePWM, openLoop, reversed, IOPins, dgtl6, dgtl7)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
 
void DriveBackward()
{
  motor[leftServo] = -100;
  motor[rightServo] = -100;
  wait1Msec(400);
}
 
void TurnRight(int time)
{
  motor[leftServo] = 100;
  motor[rightServo] = -100;
  wait1Msec(time);
}
 
void TurnLeft(int time)
{
  motor[leftServo] = -100;
  motor[rightServo] = 100;
  wait1Msec(time);
}
 
void Stop()
{
  motor[leftServo] = 0;
  motor[rightServo] = 0;
}
 
void driveForwardUntilDark ()
  {
    while (SensorValue[lightSensor] < 60) //drive forward until the sensor detects a line
      {
        motor[leftServo]=100;
        motor[rightServo]=100;
      }
     Stop(); //make sure to put stops in between actions to check the momentum of the last move
     DriveBackward(); // back away from the line in order to get room to turn
     Stop();
  }
 
 
 
task main()
{
  //slight drive forward to give the light sensor time to normalize
 motor[leftServo]=100;
 motor[rightServo]=100;
 wait1Msec(300);
 
 driveForwardUntilDark();
 TurnLeft(705);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnRight(650);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnRight(650);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnLeft(705);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 TurnLeft(655);  //will probably need to adjust time for your robot
 Stop();
 driveForwardUntilDark();
 
 //One last straight drive to get us into the end zone
 motor[leftServo]=100;
 motor[rightServo]=100;
 wait1Msec(2000);
}
Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox