The Maze/Spring/2019

Conducting Line following using a metal sensor

Author/s: Alonso Quintero & Steven Charles Tan
Verification: Steven Charles Tan (Project Manager)
Approval: Steven Charles Tan (Project Manager)

Introduction

Using the Metal sensor to conduct line following was a little tricky. Through research and a lot of experimentation, however, it was achieved.

Getting the Robot to Move

In order to have the 3DoT robot to follow a line, a couple things had to be done first. The first thing to be done was to get a threshold. Unfortunately, the threshold varies every time the sensors are used, the difference is never that great, plus or minus 5 mV. However, in the case for line following it can be significant. To remedy this issue, a subroutine was placed in the setup of the code to read the sensors one second, this test is done before the 3DoT robot is placed on the board, or while the robot is on the board with both coils of the sensor not above the copper tape. After the sensors are sampled for one second, the averages are taken as the threshold to be used for line following. The second thing that needed to be done was to have both wheels run at a fairly quickly speed to ensure the wheels are functional and also to dislodge them in case they got stuck. An issue that was encountered when testing the line following software on the robot was that the wheels tended to get stuck from time to time.

Threshold and Motor Calibration Test

int runningaverage(uint16_t whichsen){
  if (whichsen == 0){
    total -= readings[readIndex];
    // read from the sensor:
    readings[readIndex] = analogVal;
    // add the reading to the total:
    total += readings[readIndex];
    // calculate the average:
    average = total / samples;
    readIndex++;
    senstate = 1;
  } else if(whichsen==1){
    total2 -= readings2[readIndex];
    readings2[readIndex] = analogVal;
    total2 += readings2[readIndex];
    average2 = total2 / samples;
    senstate = 0;
  }
  // if we're at the end of the array...
  if (readIndex >= samples) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }
}
void readthres(){
  for (int a = 0; a<101;a++){
    pulsesen();
    delay(10);
  }
  //Serial.print("Reading Threshold");
  threshold = average-3;
  threshold2 = average2-3;
  Serial.println();
  Serial.print(threshold);
  Serial.println();
  Serial.print(threshold2);
}

void moveforward(){
  digitalWrite (STBY, HIGH);
  digitalWrite (AIN2,HIGH);
  digitalWrite(AIN1,LOW); 
  digitalWrite (BIN2,HIGH);
  digitalWrite(BIN1,LOW);
  analogWrite(PWMA,150);  // Have the right motor run for 1 second
  delay(1000);
  analogWrite(PWMA,0);
  analogWrite(PWMB,150);  // Have the left motor run for 1 second
  delay(1000);
  analogWrite(PWMA,150);  // Run both motors for 1 second
  delay(1000);
  analogWrite(PWMA,0);
  analogWrite(PWMB,0);
}

Line following

Finally the program is ready to go into the line following loop. The first thing to be done in the loop is to pulse the sensors and read the values. The values are then subtracted from the threshold and the differences saved. If the difference were positive, meaning the reading was below the threshold, then action is taken. Depending on whether only one sensor is below the threshold or both determined if the bot corrected itself or stopped at an intersection.

void init_motors(){
  pinMode(PWMB, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(STBY, OUTPUT);
  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  digitalWrite (STBY, HIGH);
  digitalWrite (AIN2,HIGH);
  digitalWrite(AIN1,LOW); 
  digitalWrite (BIN2,HIGH);
  digitalWrite(BIN1,LOW);
}

void set_left_speed(int dutyCycle){
  int newSpeed = (255*(dutyCycle*0.01));
  analogWrite (PWMA, newSpeed);
}
void set_right_speed(int dutyCycle){
  int newSpeed = (255*(dutyCycle*0.01));
  analogWrite (PWMB, newSpeed);
}

void loop(){
  digitalWrite (STBY, HIGH);
  digitalWrite (AIN2,HIGH);
  digitalWrite(AIN1,LOW); 
  digitalWrite (BIN2,HIGH);
  digitalWrite(BIN1,LOW);
  pulsesen(); //pulses the sensors and begins readings
  int rightSensor = threshold2-average2; //compares to threshold
  int leftSensor = threshold-average;
  Serial.print(leftSensor);
  Serial.print(" ");
  Serial.println(rightSensor);
  if (leftSensor > 0 && rightSensor > 0){ // Have both motors stop when reaching an intersection
    set_right_speed(0);
    set_left_speed(0);
    Serial.println("Stop");
    delay(2000);
  }
  else if (leftSensor > 0){ // If the left sensor has a reading, then speed up the right motor
    set_right_speed(50);
    Serial.println("Turning Left");
  }
  else if (rightSensor > 0){
    set_left_speed(50);
    Serial.println("Turning Right");
  }
  else{
    set_right_speed(20); // Motor speeds are offset to overcome the difference in the motors mechanically
    set_left_speed(26.5);
    Serial.println("Moving Forward");
  }
}

Conclusion

Using the custom sensor code referenced in “Controlling a Metal Detector Sensor” blog post, alongside both the threshold and line following code, the 3DoT PaperBot was capable of line following.