Lab 6
Net ID: pp386
Objective: Closed Loop Control (PID)
To get experience with PID control and to try and make the robot stop 30 cm away from the wall (Task A).
Prelab
I added code to my bluetooth part through which I could start and stop my car through my laptop with the battery attached to the car. Code:
case START_CAR:
flag=1;
break;
case STOP_CAR:
flag=0;
break;
The above code sets a global variable called flag to be 0 or 1 to stop or start the car and the sensor ranging. I intend to get the other parts of the Bluetooth callback function for data collection working before Lab 7.
Lab Procedure
I had a major setback in this lab since one of my motor drivers stopped working and I had to change the motor drivers twice. It turns out I may have banged my car into the wall for measuring top speed in Lab 5 and the ground wire connecting the Artemis to the motor driver got cut and hence the driver died. After debugging for 3 lab sessions including Extra lab hours, I was able to get the new motor driver working. After that I had some problems with my ToF sensor. It still randomly starts on only some instances and then it doesnt work on some. I decided to resolder the whole sensor and then too the error didnt go away. For the mean time, I have made the system to work by resetting the artemis by shorting the VCC and GND on the sensor and hence the sensor starts working. I had asked the professor for and extension for this lab. PID control is a simple controller which is used in this lab to control the car. The sensor readings are taken from the front ToF sensor and passed to the PID controller as the input and then the motor outputs for the car are calculated by the PID function. The code for my PID loop is:
double Setpoint=300;
double prev_error=0.0;
double cur_error;
double Output;
double Kp=0.13, Ki=0., Kd=0.1;
double cur_time=0.0;
double prev_time=0.0;
double integrator_sum=0.0;
double current_point;
void PID_Controller(double Setpoint,double current_point)
{ cur_time=millis();
cur_error= Setpoint-current_point;
double p=Kp*cur_error;
integrator_sum+=cur_error;
double i= Ki*integrator_sum*(cur_time-prev_time);
double d=Kd*(cur_error-prev_error)/(cur_time-prev_time) ;
Output = p + i + d;
prev_error=cur_error;
prev_time=cur_time;
}
The output calculated from the above loop then goes through some post processing as shown below. If the motor value is greater than 127, the motor output is capped to 127. From lab 5 I found the deadband of the motor to be around 30-35 on low charge and hence if the output from the PID was less than 30, it was set to 30. For negative values, i.e. the car moving backwards, the corresponding code was set.
PID_Controller(300,current_point);
motor=Output;
if(motor>=127)
{
motor=127;
}
else if(motor<-127)
{
motor=-127;
}
else if(motor>0 && motor<30)
{
motor=30;
}
else if(motor>-30 && motor<0)
{
motor=-30;
}
if(motor<0)
{
motor=-motor;
analogWrite(16, 0);
analogWrite(14, motor);
analogWrite(7, 0);
analogWrite(3, motor);
}
else
{
P control
First I implemented a controller using only P or proportional control. For that I set Kp=0.1, Kd=0 and Ki=0. The below video shows an output with only P control.
As you can see from the video above, the car overshot, banged the wall and then came to the setpoint of 300 mm. The car also started oscillating a bit since there was only P control.
PD control
Kp=0.1 Kd=0.1
Since in PD control the car banged into the wall, I decided to lower the P value and implement a P controller again.
Kp=0.02 P control
As we can see in the above video, P control only works to bring the car near the setpoint though pretty slowly.