Hello!
I am trying to implement a digital control loop for something, that requires a PI regulator. I have available already implemented optimized PID controller function, that takes both input and all gains (Kp, Ki, Kd) in a fractional Q1.15 format. The output of the regulator is also Q1.15 format. (It is the
arm_pid_q15 function)
What I am unable to figure out, is how to interface the regulator's output to a register, that controls for example a PWM signal, the correct way.
Imagine a register, that controls some kind of PWM and has the range of 0 to 240. The best thing I could come up with, is to scale the regulator output to 240 and saturate it for this range (i.e. not use the negative values at all). Looks like this:
q15_t err = setpoint - measured;
q15_t out = arm_pid_q15(&S, err);
/* Limit (only positive output) */
if (out < 0) out = 0;
/* Scale to 240 */
out = (out * 240UL) >> 15;
PWMREG = out;
This seems to me it might be correct to do it that way. However based on what the regulator does and how the Q/fractional format works, the regulator itself cannot have gain larger than 1. If I set Kp as MAX value (0.9999 or 32767 respectively) while leaving Ki = Kd = 0, the error input variable should be copied directly to the output. (Which it indeed seems to be doing, based on what I see). What is the correct way to implement gains larger than 1? One cannot regulate much if at all, at loop gains lower than 1.
It seems to me, that to implement gains > 1, I could pretend the regulator output is not Q1.15 but for example Q4.12 to obtain gain range of +-8. It should then look like this:
q15_t err = setpoint - measured;
q15_t out = arm_pid_q15(&S, err);
/* Limit to only positive output) */
if (out < 0) out = 0;
/* Scale to 240 */
out = (out * 240UL) >> 12; /* Q4.12 */
/* Limit the range to 240 */
if (out > 240) out = 240;
PWMREG = out;
Still this looks kind of silly to me. What have I missed?
Thanks for help,
Yan