Filters
Close

Frobo V2 Programming Lesson- Part 6

Welcome to part 5 of Froboduino/Arduino programming lessons. In the previous lessons, we learnt about controlling LEDs as output device, and reading values from Ultrasonic sensors and LDR light sensors. You made quite a progress. Congratulations!

In this lesson, we will learn about  IR (Infrared) proximity sensor.

What is Infrared?

Infrared is a part of light spectrum, but human eye cannot see this light. Infrared wavelength is from 800 nanometers (nm) to 1 millimeter. Our eyes can see light with wavelength between 400 nm to 700 nm. Almost all heated objects emit some amount of infrared light. Do you know about nighvision cameras. These cameras are designed to react to infrared. At night, when all lights are off, these cameras can see all objects wchich emit infrared and take photographs. Try looking for night vison photographs of humans. Human body temperature is 98.4 F and our bodies emit infrared in the range .75 to 1000 micron ( 1 micron = 10^-6 meters) wavelength.

IR proximity sensor

This sensor is pair of IR Led and IR sensitive diode. This works by emitting IR light in a direction, if there is an object nearby, the IR gets reflected and IR sensitive diode senses the reflected IR and passes the data to the micro controller( Froboduino/Arduino). Actually, IR diode when connected in reverse bias (Cathode to +5V and anode to GND through a resistor of 300 Ohm), creates small current when exposed to light. This current is then flown through a high value resistance (We are using 10000 ohm). This creates a small voltage difference across the resistance. This voltage is still too small to be directly read by Froboduino. This voltage is fed to a voltage amplifier (Op Amp) LM358. LM358 then sends a signa to micro controller, when the diode current crosses a certain value. See the picture below of IR pair. The white is IR Led and the darker is IR photo sensitive diode. Frobo V3 kit contains two such pairs.

IR photo sensitive proximity pair sensor

As you can notice, both the Led and diode have two legs each of different lengths. The longer one is Anode (normally connected to +ve voltage) and the shorter one is cathode (normally connected to -ve or ground of power supply).

Mount both IR pairs to the hole mounts in lower chassis of Frobo frame in the front. so that both face downwards. Please see picture.

Connect left IR led anode to I1+ and cathode to I1-. Connect left IR diode cathode (remember reverse bias for diodeto D1+ and anode to D1-. Similarly connect right IR to I2 and D2 ports.

Are you also thinking what we are going to do with this IR pair on Frobo? Actually, on the Frobo chassis, we have provided 4 locations for the IR pairs to mount. Two in the front on lower frame and one on middle top of top frame and one at the back of lower chassis. But we can use only two at a given time because our Froboduino op-amp LM358 can be conncted to maximum two. In this lesson, we will only talk about the front two pair usage.

Can you believe that we can use this two pairs to detect colour difference? Well, yes, but not really very correctly, but we can certainly detect light on dark or dark on light. We use the reflection properties of light and dark surface. Let us try to make a line following or rather colour contrast indicating robot with these IR pairs. Excited?? Use your imagination for other uses for this. What we are teaching here is just the beginning, we trust that you will create your own masterpiece of a robot.

So lets get going. Below is the code to train frobo to look for a black line on a white floor (surface). Draw is thick (about 15mm line with ablack marker) line on a light colour surface. The code below is meant for setting your frobo to detect black from white.

// On your Froboduino board, connect one of the left IR LED to I1 +ve and -ve ports, IR Diode to D1+ and D1- in reverse bias. Similarly connect right IR LED and diode to I2 and D2.

// Connect left motor +ve terminal to M1+ and -ve to M1- ports and similarly connect M2.

//Connect Leds to L1+ and L1-, L2+ and L2-.

// Declare constants.

const int IRD1 = A6;

const int IRD2 = A7;

const int leftLed = 9;

const int rightLed = 10;

// accelerator is used to control Frobo speed. Remember PWM!

const int accelerator = 5;

const int leftMotorFwd = A0;

const int leftMotorRev = A1;

const int rightMotorFwd = A2;

const int rightMotorRev = A3;

//Define vaiables left and right states as boolean ( 0 or 1 state) reading of IR diodes.

int leftState = 0;

int rightState =0;

//Define states for different stages of searching.

//First step is to search left for 5 seconds. So, we define if left search has been done.

int searchLeft = 0;

//After left search, we move right for the line and keep searching until line is found. so we define right search here.

int searchRight = 0;

//Here we define line found.

int lineFound = 0;

// Here we define time variable to track search time. Time variables are usually defined as unsigned long.

unsigned long searchStartTime = 0;

unsigned long searchNowTime = 0;

unsigned long searchTime = 0;

// Define Led state to light up Leds.

int ledState = 0;

//Define led time as unsigned long.

unsigned long ledStartTime = 0;

unsigned long ledNowTime = 0;

unsigned long ledTime = 0;

//We need not define pinMode as all pins are taken as INPUT by default. Setup code runs only once when program starts.

void setup()

{

// Define LEDs and Motors as outputs. Inputs are defined by default.

pinMode(leftLed, OUTPUT);

pinMode(rightLed, OUTPUT);

pinMode(accelerator, OUTPUT);

pinMode(leftMotorFwd, OUTPUT);

pinMode(leftMotorRev, OUTPUT);

pinMode(rightMotorFwd, OUTPUT);

pinMode(rightMotorRev, OUTPUT);

// Let us open the serial ports with data rate 9600 bits /second

Serial.begin(9600);

}

//This loop code runs repeatedly

void loop()

{

leftState = analogRead(IRD1);

rightState = analogRead(IRD2);

//Draw a black thick line on white surface and leave robot over the line.

//Bring frobo left side over the black line.

Serial.print("left ");

Serial.println(leftState);

Serial.print("right ");

Serial.println(rightState);

if (leftState <= 699){

digitalWrite(leftLed, HIGH);

Serial.println("Left side sees black line");

}

// Move frobo away from line and put it white surface.

if (leftState >= 700){

digitalWrite(leftLed, LOW);

Serial.println("No black line on left side");

}

//The code above doesn't work as expected.

//Turn the small blue pot on LM293 pin3 Froboduino board, till Frobo starts working as adjusted.

// Now, let us repeat the same thing for right side.

if (rightState <= 699){

digitalWrite(leftLed, HIGH);

Serial.println("Right side sees black line");

}

// Move frobo away from line and put it white surface.

if (rightState >= 700){

digitalWrite(leftLed, LOW);

Serial.println("No black line on right side");

}

delay(1000);

}

Here is the video for reference...

After you have set your IR diode to detect black line on white surface. Let us complete the code to train Frobo to follow black line.

 

// On your froboduino board, connect one of the left IR LED to to I1 +ve and -ve ports, IR Diode to D1+ and D1- in reverse bias. Similarly connect right IR LED and diode to I2 and D2.
// Connect left motor +ve terminal to M1+ and -ve to M1- ports and similarly connect M2.
//Connect Leds to L1+ and L1-, L2+ and L2-.
// Place your Frobo over a thich black line facing any direction, Frobo will find the line and follow it.
// Declare constants.
#include <Servo.h>
//delare servo as object.
Servo steeringServo;
const int IRD1 = A6;
const int IRD2 = A7;
const int leftLed = 9;
const int rightLed = 10;
// accelerator is used to control Frobo speed. Remember PWM!
const int accelerator = 5;
const int leftMotorFwd = A0;
const int leftMotorRev = A1;
const int rightMotorFwd = A2;
const int rightMotorRev = A3;
const int buzzer = 1;
//Define vaiables left and right states as boolean ( 0 or 1 state) reading of IR diodes.
int leftRead = 0;
int rightRead =0;
// Define variable left and right State to mark last time FRobo swa line on left or right .
int leftState = 0;
int rightState = 0;

int servoPos;

//Here we define line found.
int lineFound = 0;
// Here we define time variable to track search time. Time variables are usually defined as unsigned long.
unsigned long searchStartTime = 0;
unsigned long searchNowTime = 0;
unsigned long searchTime = 0;
// Define Led state to light up Leds.
int ledState = 0;
//Define led time as unsigned long.
unsigned long ledStartTime = 0;
unsigned long ledNowTime = 0;
unsigned long ledTime = 0;
//We need not define pinMode as all pins are taken as INPUT by default. Setup code runs only once when program starts.

void setup()

{
// Define LEDs and Motors as outputs. Inputs are defined by default.
pinMode(leftLed, OUTPUT);
pinMode(rightLed, OUTPUT);
pinMode(accelerator, OUTPUT);
pinMode(leftMotorFwd, OUTPUT);
pinMode(leftMotorRev, OUTPUT);
pinMode(rightMotorFwd, OUTPUT);
pinMode(rightMotorRev, OUTPUT);
pinMode(buzzer, OUTPUT);

// Let us open the serial ports with data rate 9600 bits /second

Serial.begin(9600);
steeringServo.attach(6);

steeringServo.write(90);
}

//This loop code runs repeatedly

void loop()

{
// We use analogRead here as Pins A6 and A7 can only perform analogRead but not digitalRead as with other pins.
leftRead = analogRead(IRD1);
rightRead = analogRead(IRD2);
//Serial.println(leftRead);
//Serial.println(rightRead);
//Draw a black thick line with dull black electricity tape on white surface and leave robot over the line.
if (lineFound == 0){
if(leftRead <= 100 || rightRead <= 100){
Serial.println("line seen");
Serial.println("leftRead");
Serial.println(leftRead);
Serial.println("rightRead");
Serial.println(rightRead);
lineFound = 1;
}

}
//Serial.println("Following line");
if (lineFound == 1){
// When left photodiode sees black line, we turn Frobo left by runnong only right motor.
if (leftRead <=100 && rightRead >100){
// We call leftLed function to show Frobo seeing line in the left side.
Serial.println("seeing line on left");

leftLedBlink();
steeringServo.write(85);
digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, LOW);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, HIGH);
digitalWrite (rightMotorRev, LOW);
Serial.println("leftRead");
Serial.println(leftRead);
Serial.println("rightRead");
Serial.println(rightRead);
//delay(1000)*/
leftState = 1;
rightState = 0;
Serial.println("left State");
Serial.println(leftState);
}
// When right photodiode sees black line, we turn Frobo right by running only left motor.

else if (leftRead > 100 && rightRead <= 100){
// We call rightLed function to show Frobo seeing line in the right side.
Serial.println("seeing line on right");

rightLedBlink();
steeringServo.write(95);

digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, HIGH);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, LOW);
digitalWrite (rightMotorRev, LOW);
Serial.println("leftRead");
Serial.println(leftRead);
Serial.println("rightRead");
Serial.println(rightRead);
//delay(1000);
leftState = 0;
rightState = 1;
Serial.println("right State");
Serial.println(rightState);
}
//When both left and right photodiodes see black line, Frobo moves forward.
else if (leftRead <= 100 && rightRead <= 100 ){
// WE call bothLed function to show both bright eyes with slow blinks.
Serial.println("seeing line on both");

bothLed();
steeringServo.write(90);
digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, HIGH);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, HIGH);
digitalWrite (rightMotorRev, LOW);



Serial.println("leftRead");
Serial.println(leftRead);
Serial.println("rightRead");
Serial.println(rightRead);
//delay(1000);

}
else if (leftRead > 100 && rightRead > 100 ){
//When none of the photodiodes see black line, we set lineFound to 0 and lookLeft() and lookRight() programs will run to find the line.
//lineFound =0;
Serial.println("Can't see line");
Serial.println("leftRead");
Serial.println(leftRead);
Serial.println("rightRead");
Serial.println(rightRead);
// We now call ledBlink function to light left and right Leds aleternately to show confusion.
ledBlink();
if(leftState ==1 ){
steeringServo.write(75);
digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, LOW);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, HIGH);
digitalWrite (rightMotorRev, LOW);
}
if (rightState == 1){
steeringServo.write(105);
digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, HIGH);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, LOW);
digitalWrite (rightMotorRev, LOW);
}
if (leftState == 0 && rightState == 0){
steeringServo.write(105);
digitalWrite(accelerator, HIGH);
digitalWrite(leftMotorFwd, HIGH);
digitalWrite (leftMotorRev, LOW);

digitalWrite(rightMotorFwd, LOW);
digitalWrite (rightMotorRev, LOW);
}
}
//delay(1000);

}
}

void ledBlink(){
// This code uses timer function millis() to set time intervals for leds to switch on and off after 200 milli seconds.
// Notice how we manipulate ledState by assigning it different values to decide which led will go on and off after defined intervals.
ledTime = ledNowTime - ledStartTime;
if (ledState == 0){
ledStartTime = millis();
digitalWrite(leftLed, HIGH);
digitalWrite(rightLed, LOW);
ledState =1;

}
if (ledState == 1){
ledNowTime = millis();
if(ledTime >= 200){
digitalWrite(leftLed, LOW);
digitalWrite(rightLed, HIGH);
ledNowTime = 0;
ledStartTime = millis();
ledState =2;
}
}
if (ledState == 2){
ledNowTime = millis();
if (ledTime >=200){
digitalWrite(rightLed, LOW);
ledNowTime = 0;
ledStartTime = ledNowTime;
ledState = 0;
}
}
}

void leftLedBlink(){
// This code uses timer function millis() to set time intervals for leds to switch on and off after 200 milli seconds.
// Notice how we manipulate ledState by assigning it different values to decide which led will go on and off after defined intervals.
ledTime = ledNowTime - ledStartTime;
if (ledState == 0){
ledStartTime = millis();
digitalWrite(leftLed, HIGH);
digitalWrite(rightLed, LOW);
ledState =1;

}
if (ledState == 1){
ledNowTime = millis();
if(ledTime >= 500){
digitalWrite(leftLed, LOW);
digitalWrite(rightLed, LOW);
ledNowTime = 0;
ledStartTime = millis();
ledState =0;
}
}

}
void rightLedBlink(){
// This code uses timer function millis() to set time intervals for leds to switch on and off after 200 milli seconds.
// Notice how we manipulate ledState by assigning it different values to decide which led will go on and off after defined intervals.
ledTime = ledNowTime - ledStartTime;
if (ledState == 0){
ledStartTime = millis();
digitalWrite(leftLed, LOW);
digitalWrite(rightLed, HIGH);
ledState =1;

}
if (ledState == 1){
ledNowTime = millis();
if(ledTime >= 500){
digitalWrite(leftLed, LOW);
digitalWrite(rightLed, LOW);
ledNowTime = 0;
ledStartTime = millis();
ledState =0;
}
}

}
void bothLed(){
// This code uses timer function millis() to set time intervals for leds to switch on and off after 200 milli seconds.
// Notice how we manipulate ledState by assigning it different values to decide which led will go on and off after defined intervals.
ledTime = ledNowTime - ledStartTime;
if (ledState == 0){
ledStartTime = millis();
digitalWrite(leftLed, HIGH);
digitalWrite(rightLed, HIGH);
ledState =1;

}
if (ledState == 1){
ledNowTime = millis();
if(ledTime >= 1000){
digitalWrite(leftLed, LOW);
digitalWrite(rightLed, LOW);
ledNowTime = 0;
ledStartTime = millis();
ledState =0;
}
}

}
//Improve thos code for different situations. Like when Frobo is not placed over the line drawn. Think and let us know.

Here is the video for reference...

Copy the codes above and paste it in your arduino IDE and compile. After compiling, you are niow ready to upload the code to the Froboduino board. Let us know how was your experience so far. If any questions, please write in the comment section below.

Leave your comment