Line Follower Robot Issues - Robot slow to respond to sensors, no turn no stop.

Hello,

I have built a simple line follower Robot with 2 IR sensors, 4 DC BO motors, L298N controller, Arduino Uno Board and LED indicators to show which side (Left or right) is in the black line. The plan is to increase the Left Motor speed if the Right IR sensor is on the Black line or Increase speed or Right Motors if Left IR sensor is on the line, go straight if Both L and R sensors are not on the line and Stop when both sensors are on a black line. The code is attached below. the code works and checks the sensor inputs and control the speed of the left or right motors as needed to change directions if I move the Robot by hand slowly.

The problem is if the motors are running (Enable A and B at 255 full speed or at 120 half speed) the IR sensor inputs are not timely processed. The Robot is unable to increase speed of left motor or Right motors in response to IR sensor inputs. Or if both sensors sees a black line then it is unable to stop and move forward. I have tried changing the DELAY time during the IT sensor input checks and also speed of the motors.

Can any one please suggest how to make the robot react in time to IR sensor input or how to record the IR sensor input at a fast speed in accordance to the speed of the motors.

Arduino Code:

int IR_SensorR=10;
int IR_SensorL=11;
int LEDL_Red=13, LEDR_Green=12;
int ENA_LeftMotorSpeed=9;
int IN1_LeftMotorBkwd=8;    //Left Bkwd Clockwise
int IN2_LeftMotorFwd=7;    //Left Fwd Anti-Clockwise
int IN3_RightMotorBkwd=6;    //Right Bkwd Clockwise
int IN4_RightMotorFwd=5;    //Right Fwd Anti-Clockwise
int ENB_LeftMotorSpeed=3;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);

pinMode(IR_SensorL,INPUT);
pinMode(IR_SensorR,INPUT);
pinMode(LEDR_Green,OUTPUT);
pinMode(LEDL_Red,OUTPUT);

pinMode(ENA_LeftMotorSpeed,OUTPUT);
pinMode(IN1_LeftMotorBkwd,OUTPUT);
pinMode(IN2_LeftMotorFwd,OUTPUT);
pinMode(IN3_RightMotorBkwd,OUTPUT);
pinMode(IN4_RightMotorFwd,OUTPUT);
pinMode(ENB_LeftMotorSpeed,OUTPUT);


  digitalWrite(IN1_LeftMotorBkwd,0);
  digitalWrite(IN2_LeftMotorFwd,0);
  digitalWrite(IN3_RightMotorBkwd,0);
  digitalWrite(IN4_RightMotorFwd,0);
 
}

void loop() {
  //1 means IR light OFF, On Black Tape, o/p=1 - LED is OFF in Code
  //0 means IR light ON, NOT on Black Tape, o/p=0 - LED is ON in code
  //RED LED is LEFT IR
  //GREEN LED RIGHT IR
 
  // put your main code here, to run repeatedly:
Serial.println("IR_SensorL:");
Serial.println(digitalRead(IR_SensorL));
Serial.println("IR_SensorR:");
Serial.println(+digitalRead(IR_SensorR));
Serial.println("...............");

    int RunSpeed = 120;
    int TurnSpeed = 140;
    int StopSpeed = 0;
    int dtime = 5000;
    int dtimer = 2000;
   
if(digitalRead(IR_SensorL) == 1 & digitalRead(IR_SensorR) == 1)  //STOP
  {
    Serial.println("BOTH Left and Right Side ON Black Line, Red and Green LED OFF : STOP");
    digitalWrite(LEDR_Green,LOW);
    digitalWrite(LEDL_Red,LOW);
    //STOP all Motors
    analogWrite(ENA_LeftMotorSpeed,StopSpeed);
    analogWrite(ENB_LeftMotorSpeed,StopSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,0);    //Left STOP
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,0);    //Right STOP
    delay(dtime);
   }
else if(digitalRead(IR_SensorL) == 0 & digitalRead(IR_SensorR) == 1 )  //Turn Right
  {
    Serial.println("Right Side ON Black Line, Green LED OFF : Turn Left Wheel");
    digitalWrite(LEDR_Green,LOW);
    digitalWrite(LEDL_Red,HIGH);
   
    analogWrite(ENA_LeftMotorSpeed,TurnSpeed);
    analogWrite(ENB_LeftMotorSpeed,RunSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,1);    //Left Fwd Clockwise
    digitalWrite(IN3_RightMotorBkwd,1);    //Right Bkwd AntiClockwise    
    digitalWrite(IN4_RightMotorFwd,0);
    delay(dtime);
  }
 else if(digitalRead(IR_SensorL) == 1 & digitalRead(IR_SensorR) == 0 )  //Turn Left
  {
    Serial.println("Left Side ON Black Line, Red LED OFF : Turn Right Wheel");
    digitalWrite(LEDR_Green,HIGH);
    digitalWrite(LEDL_Red,LOW);
   
    analogWrite(ENA_LeftMotorSpeed,RunSpeed);
    analogWrite(ENB_LeftMotorSpeed,TurnSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,1);    //Left Bkwd AntiClockwise
    digitalWrite(IN2_LeftMotorFwd,0);
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,1);    //Right Fwd Clockwise    
    delay(dtime);
  }
 else //Go Straight
  {
    Serial.println("BOTH Left and Right Side NOT on Black Line, Red and Green LED ON : Go Straight");
    digitalWrite(LEDR_Green,HIGH);
    analogWrite(ENA_LeftMotorSpeed,RunSpeed);
    digitalWrite(LEDL_Red,HIGH);
    analogWrite(ENB_LeftMotorSpeed,RunSpeed);
    //RUN All Motors
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,1);    //Left Fwd Clockwise
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,1);    //Right Fwd Clockwise  
    delay(dtimer);
  }
  //delay(3000);
}

Thanks for posting your code properly, in your first post! Karma++

Statements like these kill the robot. They tell the Arduino to “do absolutely nothing”, in this case for 5 seconds. And there are lots of those statements in your code.

    delay(dtime);

You will need to learn a completely different programming style to have a responsive robot – one that preferably uses no delays at all.

The basic idea is encapsulated in the Blink Without Delay Arduino example, explained in this excellent tutorial: Blink without delay() explained line-by-line.

@jremington, Just read your blink without delay page. I like it! And I learned something as well. Good on ya!

-jim lee

This might work. I put in some other comments on good changes.
Another is to use Ctrl-t in the IDE to auto-format the code.

// all of these ints that will never hold > 255 should be byte variables.

int IR_SensorR=10;
int IR_SensorL=11;
int LEDL_Red=13, LEDR_Green=12;
int ENA_LeftMotorSpeed=9;
int IN1_LeftMotorBkwd=8;    //Left Bkwd Clockwise
int IN2_LeftMotorFwd=7;    //Left Fwd Anti-Clockwise
int IN3_RightMotorBkwd=6;    //Right Bkwd Clockwise
int IN4_RightMotorFwd=5;    //Right Fwd Anti-Clockwise
int ENB_LeftMotorSpeed=3;

// declare once, not inside of loop()
    int RunSpeed = 120;
    int TurnSpeed = 140;
    int StopSpeed = 0;
//    int dtime = 5000;    // 5 seconds? Ignore sensors for 5 whole seconds??
//    int dtimer = 2000;   // is this ever used?
    int dtime = 10;    // why is there any delay anyway?


unsigned long startWait, waitWait;  // these are replacing those delay() calls


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);  //  better to use 115200 or faster to clear the serial output buffer quicker

pinMode(IR_SensorL,INPUT);
pinMode(IR_SensorR,INPUT);
pinMode(LEDR_Green,OUTPUT);
pinMode(LEDL_Red,OUTPUT);

pinMode(ENA_LeftMotorSpeed,OUTPUT);
pinMode(IN1_LeftMotorBkwd,OUTPUT);
pinMode(IN2_LeftMotorFwd,OUTPUT);
pinMode(IN3_RightMotorBkwd,OUTPUT);
pinMode(IN4_RightMotorFwd,OUTPUT);
pinMode(ENB_LeftMotorSpeed,OUTPUT);


  digitalWrite(IN1_LeftMotorBkwd,0);
  digitalWrite(IN2_LeftMotorFwd,0);
  digitalWrite(IN3_RightMotorBkwd,0);
  digitalWrite(IN4_RightMotorFwd,0);
 
}

void loop() {
  //1 means IR light OFF, On Black Tape, o/p=1 - LED is OFF in Code
  //0 means IR light ON, NOT on Black Tape, o/p=0 - LED is ON in code
  //RED LED is LEFT IR
  //GREEN LED RIGHT IR
 
  // put your main code here, to run repeatedly:
Serial.println("IR_SensorL:");
Serial.println(digitalRead(IR_SensorL));
Serial.println("IR_SensorR:");
Serial.println(+digitalRead(IR_SensorR));
Serial.println("...............");

    RunSpeed = 120;
    TurnSpeed = 140;
    StopSpeed = 0;
   
if ( waitWait > 0 )
{
  if ( millis() - startWait >= waitWait )
  {
    waitWait = 0; // next time through, read the sensors, etc
  }
}
else
{
  if(digitalRead(IR_SensorL) == 1 & digitalRead(IR_SensorR) == 1)  //STOP
  {
    Serial.println("BOTH Left and Right Side ON Black Line, Red and Green LED OFF : STOP");
    digitalWrite(LEDR_Green,LOW);
    digitalWrite(LEDL_Red,LOW);
    //STOP all Motors
    analogWrite(ENA_LeftMotorSpeed,StopSpeed);
    analogWrite(ENB_LeftMotorSpeed,StopSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,0);    //Left STOP
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,0);    //Right STOP

//    delay(dtime);
    startWait = millis();
    waitWait = dtime; // next bunch of times through, wait
   }
  else if(digitalRead(IR_SensorL) == 0 & digitalRead(IR_SensorR) == 1 )  //Turn Right
  {
    Serial.println("Right Side ON Black Line, Green LED OFF : Turn Left Wheel");
    digitalWrite(LEDR_Green,LOW);
    digitalWrite(LEDL_Red,HIGH);
   
    analogWrite(ENA_LeftMotorSpeed,TurnSpeed);
    analogWrite(ENB_LeftMotorSpeed,RunSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,1);    //Left Fwd Clockwise
    digitalWrite(IN3_RightMotorBkwd,1);    //Right Bkwd AntiClockwise   
    digitalWrite(IN4_RightMotorFwd,0);
//    delay(dtime);
    startWait = millis();
    waitWait = dtime; // next bunch of times through, wait
  }
  else if(digitalRead(IR_SensorL) == 1 & digitalRead(IR_SensorR) == 0 )  //Turn Left
  {
    Serial.println("Left Side ON Black Line, Red LED OFF : Turn Right Wheel");
    digitalWrite(LEDR_Green,HIGH);
    digitalWrite(LEDL_Red,LOW);

    analogWrite(ENA_LeftMotorSpeed,RunSpeed);
    analogWrite(ENB_LeftMotorSpeed,TurnSpeed);
   
    digitalWrite(IN1_LeftMotorBkwd,1);    //Left Bkwd AntiClockwise
    digitalWrite(IN2_LeftMotorFwd,0);
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,1);    //Right Fwd Clockwise   
//    delay(dtime);
    startWait = millis();
    waitWait = dtime; // next bunch of times through, wait
  }
 else //Go Straight
  {
    Serial.println("BOTH Left and Right Side NOT on Black Line, Red and Green LED ON : Go Straight");
    digitalWrite(LEDR_Green,HIGH);
    analogWrite(ENA_LeftMotorSpeed,RunSpeed);
    digitalWrite(LEDL_Red,HIGH);
    analogWrite(ENB_LeftMotorSpeed,RunSpeed);
    //RUN All Motors
    digitalWrite(IN1_LeftMotorBkwd,0);
    digitalWrite(IN2_LeftMotorFwd,1);    //Left Fwd Clockwise
    digitalWrite(IN3_RightMotorBkwd,0);
    digitalWrite(IN4_RightMotorFwd,1);    //Right Fwd Clockwise 
//    delay(dtimer);
    startWait = millis();
    waitWait = dtime; // next bunch of times through, wait
  }
 }
}

You, OP, is the second questioner in a very short time that uses IR detectors. Change them to light sencitive sensors. IR radiation from a black surface and a white surface might be very much the same!

Thank you everyone for the quick reply, appreciate the help.

@jremington - I will try the without delay option. I had 5 sec of delay just to check the Arduino reaction time, I thought if it needs time to process the IR sensor input before executing the next command.

@GoForSmoke - I will run your code and check if it works in my set up. Delay time 5sec was a test to see if Arduino can react if it does not get any other signal from sensor and process the one it had, as the problem I was facing was at fast speed the IR inputs were not reacted to. I agree “dtimer” was never used, I intended it for the going straight part of the IF statement to differentiate between turn vs straight delays. I learnt something new from your code.

Thank you.

Back in 2012 I found that my black magic marker reflected IR led light about as well as white paper. It's very likely a chemical thing where some other black might absorb led near-IR and give back IR that is not near-IR detectable.

Is this a kit line follower bot?

How many working line-follower bots use near-IR sensors? My guess only but if it can't work the fact would be known here.

How thick is the line? How are you illuminating the line besides the leds being IR?

I think I'd want a center sensor that the sketch tries to keep over the line instead of bouncing right-left-right-left trying to find it and not cross it at the same time. The models I've seen with 5 sensors in a > shape look even better, they can all be read in a single byte variable = port register and processed with a switch-case statement.

Will the line ever cross itself? Be prepared to model all different situations the bot may encounter.