A common task in VEX competitions is to hold an arm at a specified height. However, due to the weight of most robot arms, the programmer can't just tell the motor power level to go to zero - the arm would fall. If the programmer tells the arm motor to constantly run at a certain power, that value may not work when the arm is holding something. In this post, I will introduce the concept of a proportional control loop, as well as the basic idea behind programming one.
What is a control loop?
Simply put, a control loop is a repeating program that will provide output to try to achieve a target input. A good example is a thermostat - when the temperature dips below the setpoint, the heater comes on, and when the temperature gets too far above the setpoint, the A/C comes on.
An important concept in a control loop is that of error. Error is the target value minus the current value. So, if the target value (setpoint) in the thermostat example is 68 deg F, and the thermometer reads 65, the error is +3 degrees (the temperature has to come up 3 degrees to meet the setpoint). If the thermometer reads 70, the error is -2 degrees (the temperature needs to go down 2 degrees).
Proportional control
A proportional control loop (sometimes abbreviated as a P loop) is a type of control loop in which the output is directly proportional to the error. Remembering from math class, directly proportional is when the dependent variable is equal to the independent variable multiplied by a constant. For example, y = kx, where k is a constant. In this case, k is called the proportionality constant, which I typically abbreviate as Kp. (K is a typical constant letter, in case you haven't noticed.)
So, here's the basic idea of a proportional loop in pseudo-code:
while(true){ //control loop
error = TARGET - SensorValue;
output = Kp * error; //Kp is a constant
}
Applying proportional control to an arm
At the beginning of this post, I posed the question of how to make an arm hold a specified height. Now I will apply proportional control to this problem. For this example, I will assume that the arm has a potentiometer on it, which will tell at what angle the arm is held. Here is the pseudo-code:
TARGET = <some number>
Kp = <some number>
while(true){ //Loop
error = TARGET - Sensor;
output = Kp * error;
motor[arm] = output;
}
Both the TARGET value and Kp are dependent upon the construction of the robot. Now, this loop will work, but some programmers may spot a potential flaw. When the error becomes large, the motors may reach their full power level. This is typically not something you want in an arm. So, we need to establish a maximum/minimum value for the motors. This is easy with a if/then statement:
TARGET = <some number>
Kp = <some number>
MAX_OUT = <some power>
while(true){ //Loop
error = TARGET - Sensor;
output = Kp * error;
if(abs(error) < MAX_OUT){
motor[arm] = output;
}
else{
motor[arm]=output/abs(output)*MAX_OUT;
}
}
MAX_OUT is the maximum power level you want the motors to attain. The "output/abs(output)*MAX_OUT" segment simply adds the sign of output to MAX_OUT.
Improving the Proportional loop
The proportional loop is the first part of a PID loop. I think that this article does a good job of explaining PID in simple terms.
No comments:
Post a Comment
Please keep comments clean! Thanks.
Note: due to comment moderation, it may take a while for a comment to display.