Line Follower Robot PID Control Android Setup PDF
Line Follower Robot PID Control Android Setup PDF
Line Follower Robot PID Control Android Setup PDF
Table of Contents
File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Step 10: Tuning the PID control using the Android App . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
File Downloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Related Instructables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Advertisements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Author:mjrovai MJRoBot.org
Engineer, Brazilian, Married to Ilza, Paula's father, Living in Santiago, Chile.
The purpose of this project is to build a Line Follower Robot with PID control. We will also use an Android device to easily setup the main control parameters for better
and fast tuning.
This project is the first of a 2 parts more complex project, exploring the potentiality of Line Follower Robots. On the 2nd part (Maze Solver Robot, using Artificial
Intelligence with Arduino), the robot will explore and solve Mazes, using artificial intelligence techniques.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 2: Setting the motors
For motors, 2 continuous servos (SM-S4303R) were used. They will be "glued" together forming a single and solid block as you can see at the photo (use the 3M
Command strip, glue or double face tape). Those servos will run on a speed depending of the pulse width received on its data input. For this servo, the pulse width goes
from 1.0ms to 2.0ms (other servos can work with different pulse width). Looking in details:
A pulse of 1.5ms will position the servo at Neutral position, or stopped.
A pulse of 1.0ms will command the servo to full speed (around 70 RPM) in one direction and 2.0ms full speed in the opposite direction.
Pulse between 1.0 and 1.5ms or 1.5ms and 2.0ms, will generate proportional speed.
The first thing that must be done, it is send a 1500ms pulse to verify if the motors are "stopped". If not, the servos must be adjusted to full stop (look for the yellow bolt,
bellow the servo). Of course if your servo does not have this adjustment, try change the "1500ms" value until you get the full stop.
#include Servo library // this line code must be changed, please look the attached code
Servo leftServo;
Servo rightServo;
Void setup()
leftServo.attach(5);
rightServo.attach(3);
leftServo.writeMicroseconds(1500);
rightServo.writeMicroseconds(1500);
void loop()
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 3: Assembly the Body and motors for movement test
1. With the 3M Command frame strip, fix the 2 Servos to the one of the squared wood piece.
2. Fix the 2nd squared wood to the above one using the Binder Clips. Adjust the length of the platform to your needs.
3. Fix the Ball Caster using the Binder Clip.
4. The Power Supply for the motors will come from one of the 5V set of batteries. This set of battery will be installed between the breadboard and the body frame.
5. Connect the Battery to be used with servos: Left one of lateral power grid exclusively for servos source
6. Connect the Arduino Nano to the breadboard
7. Connect the GND of Power Grid to Arduino GND.
8. Connect the Servos to Arduino: LEFT ==> Pin 5; RIGHT ==> Pin 3
9. Connect the LED to Arduino Pin 13
10. Connect the button to Arduino Pin 9
Note that due the way that the servos are mounted (in opposition) the speed range is:
Right Servo forward speed goes from 1,500us (stopped) to 2,000us (full speed)
Left Servo forward speed goes from 1,500us (stopped) to 1,000 (full speed)
An external LED is add to pin13, for signalization and test purposes (you can use the internal Arduino LED, instead an external if you want, but take in consideration that
will be hard to see it in the middle of the cables).
Also a button is connected to pin 9. This button is very useful for test purposes and for robot's start.
For example:
while(digitalRead(buttonPin)) { }
Note that the 2 lines that will command the Robot to turn LEFT, wait 500ms and turn RIGHT only will happen after you press the button (buttonPin = 0). Before that, the
program will be stopped in the infinite loop.
The code bellow, can be used as a base for a complete motor test (forward, Backward, Full stop, turn Left, turn right). If necessary you must adjust the delays for the
required turn angle depending of your motors (also, sometimes left and right pulse values should be a little bit different to compensate any lack of balance of the motors.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
File Downloads
Motor_Test.ino (1 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'Motor_Test.ino']
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 4: The Bluetooth module (optional)
The Bluetooth module HC-06 will be installed at breadboard. The Arduino library SoftSerial will be used.
The Robot will work with or w/o the Bluetooth. The code will be construct on a way that if you do not activate the BT, the default parameters will be used. So, do not worry
if you prefer do not install the HC-06 module, the code still will work fine. In the last part of this tutorial, I will explore how to use an Android App for sending data for better
tuning of the robot parameters and/or move the robot in manual mode. I will leave the use of the Bluetooth and the App as an optional in case someone would like to
explore more the use a Line Follower Robot for competitions, for example.
In my case I use a module with 4 sensors integrated + 1 extra. All of then are compatible. For simplicity, in the diagram I included 5 stand-alone sensors connect
together. The final result are the same in both configurations.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Image Notes
1. Photo 1
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 6: Implementing the Sensor Logic
The IR sensor consists of an individual IR LED and an IR photodiode. The IR light emitted by the LED strikes the surface and is reflected back to the IR photodiode. The
photodiode then gives an output voltage proportional to the reflectance of the surface (high value for light surface and low for black/dark surface). In the case of the
sensors used, an integrated circuit at the module generated as output a simple digital signal (HIGH: Dark; LOW: Light). A potentiometer installed at the module (see
photo) will adjust the correct level of light to be considered "dark" or not. It works on a way that when the reflected light color is black/dark, a HIGH ("1") level is generated
at its output and a LOW ("0") for another lighter color. I used here a integrated module with 4 sensors and and extra module with a sole sensor (different shape, but same
logic). The combination is an array of 5 sensors that i think is good for a nice control as explained bellow.
The array of 5 sensors is mounted on a way that if only one sensor is centered with relation to the black line, only that specific sensor will produce a HIGH. By other side,
the space between sensors should be calculated to allow that 2 sensors can cover the full width of the black line simultaneously, producing also a HIGH on both sensors
(see the pictures here).
00001
00011
00010
00110
00100
01100
01000
11000
10000
Having 5 sensors, permits a generation of an "error variable" that will help to control the robot's position over the line, as shown bellow.
Let's consider that the optimum condition is when the robot is centered, having the line just bellow the "middle sensor" (Sensor 2). The output of the array will be: 0 0 1 0
0 and in this situation, the "error" will be "zero". If the robot starts to driven to the left (the line "seems move" right") the error must increase with a positive signal. If the
robot start to move to the right (the line "seems move" left"), in the same way, the error must increase, but now with a negative signal.
The error variable, related with the sensor status will be:
0 0 0 0 1 ==> Error = 4
0 0 0 1 1 ==> Error = 3
0 0 0 1 0 ==> Error = 2
0 0 1 1 0 ==> Error = 1
0 0 1 0 0 ==> Error = 0
0 1 1 0 0 ==> Error = -1
0 1 0 0 0 ==> Error = -2
1 1 0 0 0 ==> Error = -3
1 0 0 0 0 ==> Error = -4
Looking at the Arduino code, each one of the sensors will be defined with a specific name (consider that the Line Follow Sensor more to the Left must be assigned with a
label "0"):
In order to storage the values of each sensor an array variable will created:
Each position of the array will be constantly updated with the output of each one of the sensors:
LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);
Having the value of each one of the sensors, a logic must be implemented to generate the error variable:
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
else if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&(LFSensor[4]== 0 )) error = -3;
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 7: Controlling direction (Proportional Control - P)
Perfect! At this point, our Robot is assembled and operational. You should perform some basic tests with the motors, read the output of sensors and testing them over a
line. What is missing is the real "brain", the first steps of an "artificial intelligence". We will get this, implementing a control logic that will guarantee that the Robot will be
kept following the line.
Suppose that the Robot is running over a line and the Sensor Array output is: "0 0 1 0 0 ". The correspondent error is "0". in this situation, both motors will be running
forward on a constant speed:
For example, with iniMotorSpeed = 250; means that LEFT Servo will receive pulses of 1,250us and RIGHT Servo 1,750us and the Robot will move forward at half speed.
Remember that the Right Servo forward speed will range with pulse length from 1,500us (stopped) to 2,000us (full speed) and the Left Servo from 1,500us (stopped) to
1,000us (full speed).
rightServo.writeMicroseconds(1500 + iniMotorPower);
leftServo.writeMicroseconds(1500 - iniMotorPower);
Suppose now that the Robot driven to the LEFT (it is like the "LINE goes to RIGHT") and covered also the sensor 3. The Array output will be: "0 0 1 1 0 " and the error =
1. In this situation what you need is turn the Robot to the right. To do that, you must Decrease the speed of Right Servo what means Decrease the length of the pulse".
Also, the speed of Left Servo must increase, what means decrease the length of the left servo pulse. To do that, we need to change the motor control function:
The above logic is correct, but it is ease to understand that adding or subtracting "1" microsecond at pulse length will not generate the required correction on a realistic
time. It is intuitive that the number to be add or subtracted should be greater. for example 50, 100, etc. To get that, the "error" must be multiplied by a constant "K". Once
the influence of this constant will be proportional to the error, we will name it "Proportional Constant: Kp).
int Kp = 50;
We can resume what will happen with the motors as shown bellow:
Sensor Array: 0 0 1 0 0 ==> error = 0 ==> Right Servo pulse length = 1,750us ==> Left Servo pulse length = 1,250us (both motors at same speed)
Sensor Array: 0 0 1 1 0 ==> error = 1 ==> Right Servo pulse length = 1,700us (slower) ==> Left Servo pulse length = 1,200us (faster)
If the situation is the opposite and the Robot driven to the right, the error would be "negative" and the speed of the servos should change:
Sensor Array: 0 0 1 0 0 ==> error = 0 ==> Right Servo pulse length = 1,750us ==> Left Servo pulse length = 1,250us (both motors at same speed)
Sensor Array: 0 1 1 0 0 ==> error = -1 ==> Right Servo pulse length = 1,800us (faster) ==> Left Servo pulse length = 1,300us (slower)
At this point is clear that as much the Robot driven to one side, bigger will be the error and faster it must return to center. The velocity with the Robot will react to the error
will be proportional to it.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 8: PID Control (optional)
In case you want jump this part, it is OK. You can stay with the Proportional control explained on the last step, or burn some brains to implement a more complex Control
system in your Robot, it is your choice. Let's go.
PID (proportional, derivative and integral) is one of the most common control schemes around. Most industrial control loops use some flavor of PID control. There are
many ways to tune a PID loop, including the manual technique used in this example.
Think of PID as a simple spring. A spring has an original length, which when disturbed, by expansion or contraction, tends to regain its original length in the shortest
possible time. Similarly, a PID algorithm in a system has a set-value of a particular physical quantity to be controlled, called a set point, which when altered due to
some reason, the system controls the other necessary features in it, to get back to the original set point in the shortest time possible. PID controllers are used wherever
there is a need to control a physical quantity and to make it equal to a specified value. Example, Cruise controller in cars, Robots, Temperature regulators, Voltage
regulators, etc.
The system calculates the error, or deviation of the physical quantity from the set point, by measuring the current value of that physical quantity using a sensor(s).
To get back to the set point, this error should be minimized, and should ideally be made equal to zero. Also, this process should happen as quickly as possible. Ideally,
there should be zero lag in the response of the system to the change in its set point.
More information can be found in many books and website including here:
http://en.wikipedia.org/wiki/PID_controller
Implementing PID
This is equal to the difference between the set point and the current value of the quantity being controlled.
error = set_point current_value (in our case is the error variable get from the position of Robot over the line
P = error
This value is responsible for the magnitude of change required in the physical quantity to achieve the set point. The proportion term is what determines the control loop
rise time or how quickly it will reach the set point.
I = I + error
This value is responsible for the quickness of response of the system to the change from the set point. The integral term is used the eliminate the steady state error
required by the proportional term. Usually, small Robots doesn't use the integral term because we are not concerned about steady state error and it can complicate the
loop tuning.
This term is the difference between the instantaneous error from the set point, and the error from the previous instant.
D = error - previousError
This value is responsible to slow down the rate of change of the physical quantity when it comes close to the set point. The derivative term is used the reduce the
overshoot or how much the system over corrects.
Equation:
Where:
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Kp is the constant, which used to vary the magnitude of the change required to achieve the set point.
Ki is the the constant, which is used to vary the rate at which the change should be brought in the physical quantity to achieve the set point.
One approach is to set the Kd variable to 0 and tune the Kp term alone first. Kp of 25 is a good place to start in our case here. At last step we used a Kp of 50 that works
very well with my Robot. If the robot reacts too slowly, increase the value. If the robot seems to react to fast and become unstable, decrease the value. Once the robot
responses reasonably, tune the derivative portion of the control loop. First set the Kp and Kd value each to the 1/2 of the Kp value. For example, if the robot responses
reasonable with a Kp = 50, then set Kp = 25 and Kd = 25 to start. Increase the Kd (derivative) gain to decrease the overshoot, decrease it if the robot become unstable.
One other component of the loop to consider is the actual sample/loop rate. Speeding this up or slowing this down can make a significant difference in the robot's
performance. This is set by the delay statements that you have in your code. It is a Try-error tentative metod to get the optimum result
void calculatePID()
{
P = error;
I = I + error;
D = error-previousError;
previousError = error;
The simple Kp constant used on the last step will be replaced for this more complete PIDvalue:
void motorPIDcontrol()
{
leftServo.writeMicroseconds(leftMotorSpeed);
rightServo.writeMicroseconds(rightMotorSpeed);
But note that if you have Kd and Ki =0, PIDvalue is only Kp*error as in the last step
void loop ()
readLFSsensors(); // read sensors, storage values at Sensor Array and calculate "error"
calculatePID();
motorPIDcontrol();
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
But for a more complete and real operation, It is important to add at least a couple of basics "commands" done "with the line". For example, let's introduce a new variable:
"mode". We will define 3 states for this variable:
mode:
#define STOPPED 0
#define FOLLOWING_LINE 1
#define NO_LINE 2
If all sensors find a black line, the Sensor Array output would be: 1 1 1 1 1. In this condition, we can define mode as "STOPPED" and the the Robot should perform a "full
stop".
void loop()
{
readLFSsensors();
switch (mode)
case STOPPED:
motorStop();
break;
case NO_LINE:
motorStop();
motorTurn(LEFT, 180);
break;
case FOLLOWING_LINE:
calculatePID();
motorPIDcontrol();
break;
The real final code will integrated some additional logic and also some variable must be initialized, etc. During the steps explanation, I left them out for simplicity, but
everything should be clear looking at final code.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
File Downloads
motorFuntions.ino (1 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'motorFuntions.ino']
sensorFuntions.ino (2 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'sensorFuntions.ino']
smart_MJRoBot_Line_Follower_V2.ino (1 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'smart_MJRoBot_Line_Follower_V2.ino']
generalFunctions.ino (2 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'generalFunctions.ino']
Step 10: Tuning the PID control using the Android App
In the previous code, you can find at "robotDefines.h" tab the following definitions for the constants to be used with the PID control.
float Kp=50;
float Ki=0;
float Kd=0;
As explained at previous step, the best way to define the correct constant to be use with the PID controller is using the "Try-error" methodology. The bad side of that is
that you must re-compile the program each time that you must change it. One way to speed-up the process is to use the Android App to send the constants at the set-up
phase.
Bellow you can find the .aia file that can be modified at MIT AppInventor and the .apk file to be installed directly in your Android device.
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
File Downloads
MJRoBot_Line_Follower_PID_Control.aia (2 MB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'MJRoBot_Line_Follower_PID_Control.aia']
MJRoBot_Line_Follower_PID_Control.apk (3 MB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'MJRoBot_Line_Follower_PID_Control.apk']
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Step 11: Changing the Code for PID remote tuning
During the Setup, we will introduce a loop where you can send the PID parameters to the Robot before you put him over the line:
command = "";
checkPIDvalues(); // send the PID constants to Android device (only for checking)
mode = STOPPED;
void manualCmd()
{
switch (command[0])
case 'g':
mode = FOLLOWING_LINE;
break;
case 's':
break;
case 'f':
motorForward();
break;
case 'r':
motorTurn(RIGHT, 30);
motorStop();
break;
case 'l':
motorTurn(LEFT, 30);
motorStop();
break;
case 'b':
motorBackward();
break;
case 'p':
Kp = command[2];
break;
case 'i':
Ki = command[2];
break;
case 'd':
Kd = command[2];
break;
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
In the video, you can see some tests using the Android App:
Bellow the final code including the PID setup via Android:
File Downloads
generalFunctions.ino (3 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'generalFunctions.ino']
motorFuntions.ino (1 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'motorFuntions.ino']
sensorFuntions.ino (2 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'sensorFuntions.ino']
smart_MJRoBot_Line_Follower_PID.ino (1 KB)
[NOTE: When saving, if you see .tmp as the file ext, rename it to 'smart_MJRoBot_Line_Follower_PID.ino']
Step 12: Conclusion
This is the first of a more complex project, exploring the potentiality of a line follower robot. In the next part, I will develop a Maze solve robot, based on this this project
here.
Hope I can contribute for others to learn more about electronics, robot, Arduino, etc.
https://github.com/Mjrovai/MJRoBot-Line-Follower
MJRoBot.org
Thanks
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/
Related Instructables
Raspberry Pi
Android Arduino bot Robot Voice Input Arduino 4WD
Aplication for Android remote controlled over Arduino Bi- rover bluetooth Simple Remote
Robot Control control II by color LED controlled by Data Plotting
Bluetooth by
Using HC-05 braserito66 Matrix Scrolling Android using Android /
and Arduino ( ZRob314 Text Display phone/tablet by Arduino /
Android Studio ) (Bluetooth + AppsByDavideV pfodApp by
by argadwi Android) by
drmpf
jollifactory
Advertisements
Comments
8 comments Add Comment
Great Instructable!
http://www.instructables.com/id/Line-Follower-Robot-PID-Control-Android-Setup/