| |
"A Storm in a Coffee Cup"
Vol. 6, Issue 10, p. 82
Listing 1
/**
* Controls a JCX with a light sensor and two motors to follow a line.
* The line follower has two guiding rules. First if it crosses the line,
* it will change the direction to find the line again. Second,
* if it doesn't cross the line after a specified amount of time,
* it is probably in error and will again flip to find the line.
*/
package linefollower;
import com.ajile.jcx.*;
import com.ajile.components.OneShotTimer;
import com.ajile.events.*;
public class LineFollower implements TriggerEventListener {
// Create left hand side motor
Motor leftMotor = new Motor(Motor.MOTOR_PORT_0);
// Create right hand side motor
Motor rightMotor = new Motor(Motor.MOTOR_PORT_1);
// Create the light sensor
LightSensor lightSensor = new LightSensor(LightSensor.SENSOR_PORT_2);
// Create one shot timer
OneShotTimer timer = new OneShotTimer();
// Indicates last turn direction.
public static final int LEFT = 0;
public static final int RIGHT = 1;
int direction = RIGHT;
/**
* Main entry point. Creates one instance of this class
*/
public static void main(String[] args) {
LineFollower instance = new LineFollower();
}
/**
* Initializes all JCX components and registers event handlers
*/
public LineFollower() {
// turn motors on
leftMotor.setState(Motor.MOTOR_FORWARD);
rightMotor.setState(Motor.MOTOR_FORWARD);
// initialize light sensor so on the line is in range (0-2000)
lightSensor.setLowerLimit(0);
lightSensor.setUpperLimit(1000);
// initialize the timer for a .5 second delay
timer.setIntervalMillis(500);
// register the flip triggerEvent method when a timeout occurs
timer.addTimerListener(this);
// use inner class to register the leavingLine method when the
// light sensor moves out of range
lightSensor.addOutOfRangeListener( new TriggerEventListener() {
public void triggerEvent() {
leavingLine();
}
});
// use inner class to register the enteringLine method when the
// light sensor moves in range
lightSensor.addInRangeListener( new TriggerEventListener() {
public void triggerEvent() {
enteringLine();
}
});
}
/**
* Called by the light sensor when light intensity
* increases past the upper threshold indicating that we
* are moving from dark to light. We lost a line.
*/
void leavingLine() {
// the line has been lost, so reverse turn
triggerEvent();
// reset the timer in case line is not refound
timer.start();
}
/**
* Called by the light sensor when light intensity
* decreases past the upper threshold indicating that we
* are moving from light to dark. We found a line
*/
void enteringLine() {
// stop the timer
timer.stop();
// Line found, move forward
leftMotor.setState(Motor.MOTOR_FORWARD);
rightMotor.setState(Motor.MOTOR_FORWARD);
}
/**
* Causes the JCX to turn in the opposite direction.
* If the JCX is presently going straght, this routine
* will still cause it to turn in the opposite direction
* as last time this routine was called.
*/
synchronized public void triggerEvent() {
if (direction == LEFT) {
direction = RIGHT;
leftMotor.setState(Motor.MOTOR_REVERSE);
rightMotor.setState(Motor.MOTOR_FORWARD);
} else {
direction = LEFT;
leftMotor.setState(Motor.MOTOR_FORWARD);
rightMotor.setState(Motor.MOTOR_REVERSE);
}
}
}
|
|