Taylor Turner
Member
I am wanting to code PID control.
Thus far I have a functional PID without a ramp rate.
In examples that I've seen the time component in the term equations are just the time derivation between error calculations and not controlling the rate at which the control variable is increased. Not worried about decreasing the value yet.
I have seen where the set point is controlled by a theoretical value which increases at rate and a few units added above the process variable.
I'd like to get away from that if possible and have the rate directly factored with the PID.
I have made some open loop ramping profiles, used on VFDs and pressure control, by taking a time duration's accumulation divided by it's preset value.
The ratio of time can be scaled from it's 0-1 to an output span, pressure say 0-3000psi, for a linear ramp.
Also the ratio of time can be applied to the x component in a polynomial constrained from 0-1 resulting in an s-curve..
y = -2(dx/dt)^3 + 3(dx/dt)^2, accelerating.
y = 2(dx/dt)^3 - 3(dx/dt)^2, decelerating.
Then the y component scaled with what the span of your output set point, 0-3000psi.
For open loop motion control this is great, but it's not good enough.
My first attempt was to multiply the ratio of time directly to the PID terms.
Which would just increase the terms at a percentage proportional to the expected time duration.
It kind of made sense in the P term, but the I term runs away easily.
Increasing the terms as you're getting closer to the set point creates troubles too.
I know this is not correct, but at this point I'm plugging and chugging with minimal references.
I'd like to get it to where the ramp rate doesn't have to be linear and polynomial functions can be enabled.
Example code in brief:
//This is so the terms are multiplied by 1 when the time duration is complete. At half the the time the term will be half.
PID.tRamp.PRE := abs((PID.rSetpoint - PID.rProcessVariable))/PID.rRamp*60*1000; //Error/Degrees per minute*1000
PID.rProportionalTerm := PID.rProportionalGain * (PID.rSetpoint - PID.rProcessVariable) * (PID.tRamp.ACC/PID.tRamp.PRE);
PID.rIntegralTerm := PID.rIntegralGain * PID.rIntegrator * (PID.tRamp.ACC/PID.tRamp.PRE);
PID.rDerivativeTerm := (PID.rDerivativeGain * (PID.rDeviation - PID.rProcessVariable)) * (PID.tRamp.ACC/PID.tRamp.PRE);
Code in full:
https://github.com/TTControls/PIDDutyCycle/blob/master/PIDPWM
I know the use of timers sucks and an interrupt should be used, but one step at a time.
Thus far I have a functional PID without a ramp rate.
In examples that I've seen the time component in the term equations are just the time derivation between error calculations and not controlling the rate at which the control variable is increased. Not worried about decreasing the value yet.
I have seen where the set point is controlled by a theoretical value which increases at rate and a few units added above the process variable.
I'd like to get away from that if possible and have the rate directly factored with the PID.
I have made some open loop ramping profiles, used on VFDs and pressure control, by taking a time duration's accumulation divided by it's preset value.
The ratio of time can be scaled from it's 0-1 to an output span, pressure say 0-3000psi, for a linear ramp.
Also the ratio of time can be applied to the x component in a polynomial constrained from 0-1 resulting in an s-curve..
y = -2(dx/dt)^3 + 3(dx/dt)^2, accelerating.
y = 2(dx/dt)^3 - 3(dx/dt)^2, decelerating.
Then the y component scaled with what the span of your output set point, 0-3000psi.
For open loop motion control this is great, but it's not good enough.
My first attempt was to multiply the ratio of time directly to the PID terms.
Which would just increase the terms at a percentage proportional to the expected time duration.
It kind of made sense in the P term, but the I term runs away easily.
Increasing the terms as you're getting closer to the set point creates troubles too.
I know this is not correct, but at this point I'm plugging and chugging with minimal references.
I'd like to get it to where the ramp rate doesn't have to be linear and polynomial functions can be enabled.
Example code in brief:
//This is so the terms are multiplied by 1 when the time duration is complete. At half the the time the term will be half.
PID.tRamp.PRE := abs((PID.rSetpoint - PID.rProcessVariable))/PID.rRamp*60*1000; //Error/Degrees per minute*1000
PID.rProportionalTerm := PID.rProportionalGain * (PID.rSetpoint - PID.rProcessVariable) * (PID.tRamp.ACC/PID.tRamp.PRE);
PID.rIntegralTerm := PID.rIntegralGain * PID.rIntegrator * (PID.tRamp.ACC/PID.tRamp.PRE);
PID.rDerivativeTerm := (PID.rDerivativeGain * (PID.rDeviation - PID.rProcessVariable)) * (PID.tRamp.ACC/PID.tRamp.PRE);
Code in full:
https://github.com/TTControls/PIDDutyCycle/blob/master/PIDPWM
I know the use of timers sucks and an interrupt should be used, but one step at a time.
Last edited: