Introduction: PID CONTROLLED LINE FOLLOWER BOT PCB
This is a PID controlled line follower bot which is fully autonomous bot. This PCB itself is a bot, we have mounted all components( motors, wheels and power supply) directly on PCB. This robot controlled PCB board contains customized IR array containing 8 IR senosor, Arduino NANO microcontroller and L298N motor driver. Of course, it is no different from other line follower bot made using external line sensing array but it is more beneficial as because it does not need any hardware changes in it. It is free from jumper and almost every component are soldered. You can further add ultrasonic if you want to make it in obstacle avoiding mode.
Step 1: Understanding the Logic
The principle of an IR sensor working as an Object Detection Sensor can be explained using the following figure. An IR sensor consists of an IR LED and an IR Photodiode; together they are called as Photo – Coupler or Opto – Coupler. When the IR transmitter emits radiation, it reaches the object and some of the radiation reflects back to the IR receiver. Based on the intensity of the reception by the IR receiver, the output of the sensor is defined. Now this is output is given to any comparator circuit, here we construct comparator circuit using LM358 ic. When the light emitted by the IR LED is incident on the photodiode after hitting an object, the resistance of the photodiode falls down from a huge value. One of the input of the op – amp is at threshold value set by the potentiometer. The other input to the op-amp is from the photodiode’s series resistor. When the incident radiation is more on the photodiode, the voltage drop across the series resistor will be high. In the IC, both the threshold voltage and the voltage across the series resistor are compared. If the compared voltage is greater than threshold voltage output of the comparator. This range of output can be controlled using potentiometer for better understanding give a look to the given comparator circuit. Now the output of the circuit is given to microcontroller and by taking line value of combining effect of eight IR sensor the motor condition are provided to motors.
Step 2: Required Hardware
You will be requiring these components and instruments if you want to duplicate this instructable.
Components:
- 8 Comparator IC
- 8 IR sensor LED's
- 8 Photodiode
- 8 330E Resistor
- 8 10K Resistor
- 8 220E Resistor
- 9 LED's
- L298N motor driver
- 1 Arduino Nano
- 12V battery
- 2 bo motors
- 2 Wheels
- Ball caster
- Dot Matrix (zero) PCB
- Male and female bug strips
- Switch
Instruments:
- Soldering gun, soldering wire, soldering paste.
- Digital Multimeter.
Step 3: Schematic Diagram and File
In this project, I have choosen EasyEDA to draw schematic diagram.
Products Details:
- Board type : Dot matrix(Zero) PCB
- Size : 153.3mm x103mm
- Layers : Single Layers
Download the schematic in PDF format provided below.
Step 4: Get the Hardware Ready!
As given in the Schematic now place every components on the PCB and apply solder.The components are soldered on dot matrix PCB as shown. Firstly we will make the IR array after its completion it will be better to check its output to verify the sensor circuit. After that make connections of microcontroller(NANO) fix the female headers and complete the connection. As you know dot matrix PCB does not have connected lines to join the circuit so we need to solder the connection as shown in the given figure, further solder all the circuit as shown in schematic. My personal recommendation is to use jumpers properly otherwise it will unnecessarily make circuit complicated and difficult to solder.
Step 5: Uploading Code
The code is written in Arduino IDE platform after getting hardware ready just upload the code in Arduino NANO using nano cable.
int s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0, s6 = 0, s7 = 0; int line_value = 0, sum = 0; const int mrp = 11, mr1 = 9, mr2 = 10, ml1 = 6, ml2 = 5, mlp = 3; int j = 0, junction = 0; int StopTrigger=0; double error = 0, p_error = 0, d_error = 0, last_error = 0, pid_error = 0; double kd=31 ,kp=1.91; int left_pwm = 65, right_pwm = 60; void setup() { // put your setup code here, to run once: pinMode(mlp, OUTPUT); pinMode(ml1, OUTPUT); pinMode(ml2, OUTPUT); pinMode(mr1, OUTPUT); pinMode(mr2, OUTPUT); pinMode(mrp, OUTPUT); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: //// CheckEnd(); // if(StopTrigger>20) // stop_(); j = read_sensors(); go_straight(); if (j > 4) { // delay(50); junction = check_junction(); Serial.print(" jN** "); Serial.println(junction); // stop_(); if (!junction) { left(); } else if (junction == 1) { go_straight(); } } if (j == 0) { right(); } // if (j==8) // { // delay(200); // if(j==8) // { // stop_(); // Serial.print("stop"); // } // // } // Serial.print(" sens: "); // Serial.print(s0); // Serial.print(" "); // Serial.print(s1); // Serial.print(" "); // Serial.print(s2); // Serial.print(" "); // Serial.print(s3); // Serial.print(" "); // Serial.print(s4); // Serial.print(" "); // Serial.print(s5); // Serial.print(" "); // Serial.print(s6); // Serial.print(" "); // Serial.print(s7); // Serial.print(" s="); // Serial.print(sum); // Serial.print(" s_num="); // Serial.print(j); // Serial.print(" | E="); // Serial.print(error); // Serial.print(" DE "); // Serial.print(d_error); // Serial.print(" PD_er="); // Serial.print(p_error + d_error); // Serial.print(" L="); // Serial.print(left_pwm); // Serial.print(" R="); // Serial.print(right_pwm); // Serial.print(" "); // Serial.println(line_value); } int read_sensors() { s0 = analogRead(A0) / 10; s1 = analogRead(A1) / 10; s2 = analogRead(A2) / 10; s3 = analogRead(A3) / 10; s4 = analogRead(A4) / 10; s5 = analogRead(A5) / 10; s6 = analogRead(A6) / 10; s7 = analogRead(A7) / 10; sum = s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7; line_value = (((10 * s0) + (20 * s1) + (30 * s2) + (40 * s3) + (50 * s4) + (60 * s5) + (70 * s6) + (80 * s7)) / sum); line_value = constrain(line_value, 0, 80); int i = 0; if (s0 > 5) i++; if (s1 > 5) i++; if (s2 > 5) i++; if (s3 > 5) i++; if (s4 > 5) i++; if (s5 > 5) i++; if (s6 > 5) i++; if (s7 > 5) i++; return i; } void go_straight() { error = line_value - 40; p_error = kp * error; // i_error = ki * d_error = kd * (error - last_error); last_error = error; pid_error = p_error + d_error; left_pwm = 70 - pid_error; right_pwm = 60 + pid_error; left_pwm = constrain(left_pwm, 0, 255); right_pwm = constrain(right_pwm, 0, 255); digitalWrite(ml1, HIGH); digitalWrite(ml2, LOW); digitalWrite(mr1, HIGH); digitalWrite(mr2, LOW); analogWrite(mlp, left_pwm); analogWrite(mrp, right_pwm); // StopTrigger=0; } void stop_() { digitalWrite(ml1, LOW); digitalWrite(ml2, LOW); digitalWrite(mr1, LOW); digitalWrite(mr2, LOW); delay(3000); stop_(); } int check_junction() { if ((!((s6 > 5) || (s7 > 5))) && (s0 > 5)) { return 1; // go straight } else { return 0; // take left } }void left() { digitalWrite(ml1, LOW); digitalWrite(ml2, HIGH); digitalWrite(mr1, HIGH); digitalWrite(mr2, LOW); analogWrite(mlp,0); analogWrite(mrp, 0); delay(20); // Serial.print(" \n Entered in left \n "); digitalWrite(ml1, LOW); digitalWrite(ml2, HIGH); digitalWrite(mr1, HIGH); digitalWrite(mr2, LOW); analogWrite(mlp, 60); analogWrite(mrp, 90); delay(200); while (1) { // Serial.print(" \nleft "); // Serial.println(line_value); digitalWrite(ml1, LOW); digitalWrite(ml2, HIGH); digitalWrite(mr1, HIGH); digitalWrite(mr2, LOW); analogWrite(mlp, 60); analogWrite(mrp, 90); j = read_sensors(); if ((line_value >= 30 && line_value <= 50 && ( j < 3)) ) { Serial.print("left"); break; } } }void right() { digitalWrite(ml1, LOW); digitalWrite(ml2, HIGH); digitalWrite(mr1, HIGH); digitalWrite(mr2, LOW); analogWrite(mlp, 0); analogWrite(mrp, 0); delay(20); // Serial.print(" \n Entered in right\n "); digitalWrite(ml1, HIGH); digitalWrite(ml2, LOW); digitalWrite(mr1, LOW); digitalWrite(mr2, HIGH); analogWrite(mlp, 70); analogWrite(mrp, 65); while (1) { // Serial.print(" \nright \n"); digitalWrite(ml1, HIGH); digitalWrite(ml2, LOW); digitalWrite(mr1, LOW); digitalWrite(mr2, HIGH); analogWrite(mlp, 65); analogWrite(mrp, 60); j = read_sensors(); if ((line_value >= 30 && line_value <= 50 && ( j < 3)) ) { break; } } } //void CheckEnd() //{ // if( j==8) // StopTrigger++; //} <br>
This code contains PID which is an algorithm to minimize error. To make it more precise change values according to ziegler-nichols method or by trial and error.
Get the Source Code:
Attachments
Step 6: Success!
The project is almost done. I have tested it many times by changing its PWM and got good results. I have uploaded a video which is the max speed covered till date. When you try to increase the speed it will destabilize the bot so you need to change the PID values simultaneously using zigler-nichols method or trial and error. In given video I used SMPS as a power supply, you can use battery instead of SMPS. So the project is ready!