It sounds like you’ve put together a solid line-following robot project using a PID algorithm! Here's a brief breakdown of the project components and code structure:
Hardware Components:
1. **Arduino Nano**: Acts as the brain of the robot, handling sensor readings and motor control.
2. **QTR 8RC Reflectance Sensor Array**: Used to detect the line by measuring reflected infrared light.
3. **DRV8835 Motor Driver**: Controls the N20 motors.
4. **N20 Motors with Clamps**: Provide the driving force for the robot.
5. **AMS1117 5.0 Voltage Regulator**: Regulates power to the Arduino and other components.
6. **Other Components**:
- Button switches: Used for calibration and starting the robot.
- Resistors, LEDs, and a caster wheel for stability.
PID Control Algorithm:
The PID (Proportional-Integral-Derivative) algorithm is key to your robot's ability to follow the line smoothly and efficiently. Here's a breakdown of each component:
- **Proportional (P)**: Responds to the current error (difference between the robot's position and the line).
- **Integral (I)**: Accumulates past errors to help correct systematic biases.
- **Derivative (D)**: Reacts to the rate of change of the error to help reduce oscillations.
Code Walkthrough
1. Including the QTR Library**:
```cpp
#include <QTRSensors.h>
```
You start by including the QTR library, which provides functions to interface with the QTR 8RC sensor array.
2. Defining Sensor Parameters**:
```cpp
QTRSensors qtr;
const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];
```
3. Defining PID Constants**:
```cpp
float Kp = 0; // Proportional constant
float Ki = 0; // Integral constant
float Kd = 0; // Derivative constant
```
These values are adjusted through trial and error to get the best line-following performance.
4. Defining Motor and Button Pins**:
```cpp
int aphase = 9;
int aenbl = 6;
int bphase = 5;
int benbl = 3;
int buttoncalibrate = 17;
int buttonstart = 2;
```
5. Setup Function:
Here, you initialize pin modes, configure the QTR sensor, and implement a calibration routine that waits for a button press to start calibrating.
```cpp
void calibration() {
digitalWrite(LED_BUILTIN, HIGH);
for (uint16_t i = 0; i < 400; i++) {
qtr.calibrate();
}
digitalWrite(LED_BUILTIN, LOW);
}
```
6. Main Loop:
- Checks for the start button and toggles the `onoff` state.
- When `onoff` is true, the `PID_control()` function is called to adjust motor speeds based on the line’s position.
7. PID Control Logic:
```cpp
int error = 3500 - position; // Calculate error
P = error; // Proportional term
I = I + error; // Integral term
D = error - lastError; // Derivative term
lastError = error;
int motorspeed = P * Kp + I * Ki + D * Kd; // PID calculation
```
The motor speeds `motorspeeda` and `motorspeedb` are adjusted according to the PID output, which helps the robot steer toward the line.
8. Motor Control Function:
The `forward_brake()` function controls the speed of each motor based on the calculated PID values, enabling smooth line tracking.
Your approach using the PID algorithm and careful calibration of constants can make a significant difference in achieving the desired balance between speed and stability. With further tuning, your line follower should be able to navigate tracks with efficiency and precision. Great work on this project!
As i said earlier I am using the QTR sensor and PID algorithm. so in the program first I included the qtr8rc library of Pololu.
#include <QTRSensors.h>
Then with the help of the QTR library functions, i defined the sensors and other parameters
QTRSensors qtr;
const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];
Then I defined the ki, kp, kd constants. We should find the values of the constants by the trial and error method.
float Kp = 0;
float Ki = 0;
float Kd = 0;
int P;
int I;
int D;
int lastError = 0;
boolean onoff = false;
Next, I defined constant for defining the maximum and minimum speed of the robot. Also, I defined the pins for the motor driver and button
int mode = 8;
int aphase = 9;
int aenbl = 6;
int bphase = 5;
int benbl = 3;
int buttoncalibrate = 17
int buttonstart = 2;
In the setup section, I defined the pin modes and added the calibration programme
Serial.begin(9600);
qtr.setTypeRC();
qtr.setSensorPins((const uint8_t[]){10, 11, 12, 14, 15, 16, 18, 19}, SensorCount);
qtr.setEmitterPin(7);
pinMode(mode, OUTPUT);
pinMode(aphase, OUTPUT);
pinMode(aenbl, OUTPUT);
pinMode(bphase, OUTPUT);
pinMode(benbl, OUTPUT);
digitalWrite(mode, HIGH);
delay(500);
pinMode(LED_BUILTIN, OUTPUT);
boolean Ok = false;
while (Ok == false) {
if(digitalRead(buttoncalibrate) == HIGH)
{
calibration();
Ok = true;
}
}
forward_brake(0, 0);
}
void calibration() {
digitalWrite(LED_BUILTIN, HIGH);
for (uint16_t i = 0; i < 400; i++)
{
qtr.calibrate();
}
digitalWrite(LED_BUILTIN, LOW);
}
Finally in the loop section
I read the values of the qtr 8rc sensor and driver motors according to the readings of the qtr sensors.
if(digitalRead(buttonstart) == HIGH) {
onoff =! onoff;
if(onoff = true) {
delay(1000);
}
else {
delay(50);
}
}
if (onoff == true) {
PID_control();
}
else {
forward_brake(0,0);
}
}
void forward_brake(int posa, int posb) {
digitalWrite(aphase, LOW);
digitalWrite(bphase, HIGH);
analogWrite(aenbl, posa);
analogWrite(benbl, posb);
}
void PID_control() {
uint16_t position = qtr.readLineBlack(sensorValues);
int error = 3500 - position;
P = error;
I = I + error;
D = error - lastError;
lastError = error;
int motorspeed = P*Kp + I*Ki + D*Kd;
int motorspeeda = basespeeda + motorspeed;
int motorspeedb = basespeedb - motorspeed;
if (motorspeeda > maxspeeda) {
motorspeeda = maxspeeda;
}
if (motorspeeda < 0) {
motorspeeda = 0;
}
if (motorspeedb < 0) {
motorspeedb = 0;
}
forward_brake(motorspeeda, motorspeedb);
}
Post a Comment