4WD Light Following Robot

Hi all,

I created a light following robot with 3 LDR sensor modules mounted to the front to act as positioning sensors using an analog input into a DFROBOT Romeo V1.3 chip. I have the 3 light sensor modules going to analog pins A0, A1, and A2 on the chip. So the intention of this project is to have the robot “wake up” when it sees a light pathway come on (we laid LED strips into the grooves of a wooden board and filled in the grooves with glue so the entire “strip” lights up). The robot would then follow the lit pathway to the end and stop. I was able to get the robot to complete the test board that includes a straight, left turn, another straight, a right turn, and finally a last straight. I managed to get it to stop at the end when less light was detected. Can someone please help review my code to see if there are any opportunities for improvement? Thank you all very much.

Note: I am posting for help because sometimes the logic seems to “conflict” as the robot drives straight instead of turning, other times it will make one turn but not the other.

//Right (M1) and Left (M2) motors speed
int speed_M1 = 5;   
int speed_M2 = 6;

//Right (M1) and Left (M2) motors direction    
int direction_M1 = 4;     
int direction_M2 = 7;

//Light sensors for positioning 
int RightSensor = A2;
int MiddleSensor = A1;
int LeftSensor = A0;
int RightValue;
int MiddleValue;
int LeftValue;

void Forward(int leftSpeed,int rightSpeed){            
  analogWrite (speed_M2,leftSpeed);
  digitalWrite(direction_M1,LOW);    
  analogWrite (speed_M1,rightSpeed);    
  digitalWrite(direction_M2,LOW);
}

void Back(int leftSpeed,int rightSpeed){           
  analogWrite (speed_M2,leftSpeed);
  digitalWrite(direction_M1,HIGH);    
  analogWrite (speed_M1,rightSpeed);    
  digitalWrite(direction_M2,HIGH);
}

void Stop(){                
  digitalWrite(speed_M2,0); 
  digitalWrite(direction_M1,LOW);    
  digitalWrite(speed_M1,0);   
  digitalWrite(direction_M2,LOW);    
}   

void TurnRight(int leftSpeed,int rightSpeed){         
  analogWrite (speed_M2,leftSpeed);              
  digitalWrite(direction_M1,HIGH);    
  analogWrite (speed_M1,rightSpeed);    
  digitalWrite(direction_M2,LOW);
} 

void TurnLeft(int leftSpeed,int rightSpeed){     
  analogWrite (speed_M2,leftSpeed);
  digitalWrite(direction_M1,LOW);   
  analogWrite (speed_M1,rightSpeed);    
  digitalWrite(direction_M2,HIGH);
}

//Light sensor readings
int readLightSensors(){
  int RightValue= analogRead(A2);  
  int MiddleValue= analogRead(A1);
  int LeftValue= analogRead(A0);
  Serial.print(LeftValue);
  Serial.println("  LeftValue");
  Serial.print(MiddleValue);
  Serial.println("  MiddleValue");
  Serial.print(RightValue);
  Serial.println("  RightValue");

  if(LeftValue < 100 && LeftValue < MiddleValue && LeftValue < RightValue){
    return 1; 
  }
  else if(MiddleValue < 100 && MiddleValue < RightValue && MiddleValue < LeftValue){
    return 2;
  } 
  else if(RightValue < 100 && RightValue < MiddleValue && RightValue < LeftValue){
    return 3;
  }
  else if(RightValue > 300 && MiddleValue > 300 && LeftValue > 300){
    return 4;
  }
  }

int followLightPath(){
  int direct = readLightSensors(); 
  switch(direct){
    case 1: 
    TurnLeft(150,150);
    break;
    case 2:
    Forward(100,100);
    break;
    case 3:
    TurnRight(150,150);
    break;
    case 4:
    Stop();
    break;
    default: 
    Stop();
    break;
  }
}

void setup(){ 
  Serial.begin (9600);
  pinMode(RightSensor, INPUT);
  pinMode(MiddleSensor, INPUT);
  pinMode(LeftSensor, INPUT);
 }
 
void loop(){
  followLightPath();
  }

sometimes the logic seems to “conflict” as the robot drives straight instead of turning, other times it will make one turn but not the other.

Try to determine exactly when, and under what circumstances that happens. Otherwise, you just have to stare at the code until you see a problem.

Hint: “magic numbers” like these are almost always a disaster waiting to happen:

LeftValue < 100
int readLightSensors(){
  int RightValue= analogRead(A2);  
  int MiddleValue= analogRead(A1);
  int LeftValue= analogRead(A0);

Locals with same names as globals.
Also, you gave the pins nice names - why not use them?

AWOL:

int readLightSensors(){

int RightValue= analogRead(A2); 
  int MiddleValue= analogRead(A1);
  int LeftValue= analogRead(A0);


Locals with same names as globals.
Also, you gave the pins nice names - why not use them?

Fixed both, didn't even notice that.

I tested the code again this morning and it waits for the LED strip to turn on correctly but both turns it just drives past and stops once it is off track of the LED strip (as soon as it breaks the threshold of the light 300, it stops which is what I want it to do). Is this a logic issue? If it won't recognize it's supposed to turn.

jremington:
Try to determine exactly when, and under what circumstances that happens. Otherwise, you just have to stare at the code until you see a problem.

Hint: “magic numbers” like these are almost always a disaster waiting to happen:

LeftValue < 100

So I got this “100” from putting the LDR modules over the LED strip and when the LED strip is on, the analog values are sub 100. So I figured for the robot to follow the light, it should use 100 as a threshold before comparing the value of the other modules to make the turn.

Do you have any suggestions how to approach this threshold a different way?

Make the thresholds named constants.
Then, when you recalibrate, you only have to change one instance of each value.

AWOL:
Make the thresholds named constants.
Then, when you recalibrate, you only have to change one instance of each value.

Fixed by adding threshold value. It appears the issue is coming from the logic. I ran it a few times and kept an eye on the values. It appears at turns, the middle value is still the lowest value by about 15-20 so in my code one of the conditions for a turn is that the left or right sensor must be less than the middle sensor.

I added +50 to MiddleValue to case 1 and 3 and it completes the first turn without issue now. Still drives past the second turn and stops without turning.