The first idea we had for the robot to line follow was to do as follows:
void followLine() {
int defaultLSpeed = leftMotorDefaultSpeed/1.6;
int defaultRSpeed = rightMotorDefaultSpeed/1.6;
leftMotorSpeed=defaultLSpeed;
rightMotorSpeed=defaultRSpeed;
int adjustment=1;
long lastAdjustmentTime = millis();
long timeActivated;
bool paperSensorActivated = false;
byte lastRead = 0;
while (1) {
Forward(); //sends new motor speed values to motor board
int currentRead = digitalRead(LineSensor); //line sensor value
if (currentRead!=lastRead){ //every time line is found/lost
adjustment = 5; //reset adjustment value
// lastAdjustmentDelta = 5;
leftMotorSpeed=defaultLSpeed; //reset motor speeds
rightMotorSpeed=defaultRSpeed;
}
if (millis()-lastAdjustmentTime>50) { //if adjustment hasn't been made in so long
adjustment = adjustment + 10; //adjust
lastAdjustmentTime=millis(); //update adjustment time
}
if (currentRead==LOW) { //no line, go right
rightMotorSpeed=constrain(defaultRSpeed+adjustment, -255, 255);
leftMotorSpeed=constrain(defaultLSpeed-adjustment, -255, 255);
}
else { //line, go left
rightMotorSpeed=constrain(defaultRSpeed-adjustment, -255, 255);
leftMotorSpeed=constrain(defaultLSpeed+adjustment, -255, 255);
}
lastRead=currentRead; //save current line state
if (digitalRead(PaperSensor)==LOW) { //check for paper sensor - waits for a time to prevent accidental triggering
if (paperSensorActivated == false) {
paperSensorActivated=true;
timeActivated = millis();
}
else if (millis()-timeActivated>1000) break; //after paper sensor has been activated for this amount of time, stop
} else {
paperSensorActivated=false;
}
}
Stop();
currentMenu = draw; //returns to main menu
}
The robot would do fine when the line curving to the right, However, when curving to the left, the robot did not react quick enough, and would leave the line on the right hand side. Since the robot assumes it is always on the left hand side of the line when it is not touching the line, it would then begin to turn in the wrong direction.
We tried adjusting the interval in which adjustments were made. We found that the best thing we could do was to slow the robot down as much as possible, and then turn away from the line quickly enough that it would never cross the line, but at the same time not make to drastic of an immediate adjustment everytime the line was touched.
void followLine() {
int defaultLSpeed = leftMotorDefaultSpeed/1.7;//1.7;
int defaultRSpeed = rightMotorDefaultSpeed/1.7;//1.7;
leftMotorSpeed=defaultLSpeed;
rightMotorSpeed=defaultRSpeed;
int adjustment=1;
//int baseAdjustment=5;
//int lastAdjustmentDelta = 5;
long lastAdjustmentTime = millis();
long timeSinceLine = millis();
long timeActivated;
bool paperSensorActivated = false;
byte lastRead = 0;
bool stopNow = false;
for (int i=0;i<4;i++) {
paperSensorMovingAverage[i]=analogRead(PaperSensor2);
}
int index = 0;
int total = 0;
for (int i=0;i<4;i++) {
total+=paperSensorMovingAverage[i];
}
while (1) {
if (useSave) saveData(useSave); //time to log some data!! :D
Forward(); //sends new motor speed values to motor board
int currentRead = digitalRead(LineSensor); //line sensor value
if (currentRead!=lastRead){ //every time line is found/lost
adjustment = 0; //reset adjustment value
leftMotorSpeed=defaultLSpeed; //reset motor speeds
rightMotorSpeed=defaultRSpeed;
timeSinceLine = millis();
}
if (millis()-lastAdjustmentTime>50) { //if adjustment hasn't been made in so long
adjustment += 6; //adjust
lastAdjustmentTime=millis(); //update adjustment time
}
if (currentRead==LOW) { //line, go right
leftMotorSpeed=constrain(defaultLSpeed+1.4*adjustment, -leftMotorDefaultSpeed, leftMotorDefaultSpeed);
rightMotorSpeed=constrain(defaultRSpeed-1.4*adjustment, -rightMotorDefaultSpeed, rightMotorDefaultSpeed);
}
else { //no line, go left
leftMotorSpeed=constrain(defaultLSpeed-1.0*adjustment, -leftMotorDefaultSpeed, leftMotorDefaultSpeed);
rightMotorSpeed=constrain(defaultRSpeed+1.0*adjustment, -rightMotorDefaultSpeed, rightMotorDefaultSpeed);
}
lastRead=currentRead; //save current line state
//moving average calculation for paper sensor (analog)
int reading = analogRead(PaperSensor2);
paperSensor = (total+=(reading-paperSensorMovingAverage[index]))/4;
paperSensorMovingAverage[index] = reading;
index=(index+1)%4;
//paper detection method
if (paperSensor>=paperActivationThreshold && paperSensor<100) {
if (paperSensorActivated == false) {
paperSensorActivated=true;
timeActivated = millis();
} else {
if (millis()-timeActivated>50) {
digitalWrite(ledPin, 244);
stopNow = true;
}
}
}
else if (!stopNow) {
paperSensorActivated=false;
}
//if you were on paper and approached the black tape, stop, as you should be on the paper
if (paperSensor>150 && stopNow==true || digitalRead(PaperSensor)==HIGH && stopNow==true) {
break;
}
if (stopNow || digitalRead(PaperSensor)==LOW || paperSensor>220) adjustment=0; //don't adjust while on the paper.
}
Stop();
currentMenu = draw; //returns to main menu
}
We discovered that if we tried to increase the speed of our robot to do this course faster, it would lose the line. So for now, it will have to go slow for now. Going to fast means the robot drives onto the wrong side of the line and loses any idea of where it is in the world.