Digital PID regulator implementation, q15_t output to register - Page 1
Forum section: electronics / general

author: Yansi
author_rank: Super Contributor
timestamp: May 23, 2017, 11:55:46 pm
content: 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 thearm_pid_q15function)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:Code: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:Code: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

author: Jeroen3
author_rank: Super Contributor
timestamp: May 24, 2017, 05:57:49 am
content: You can't pretend q15 is q3.12, the implementation ofarm_pid_q15needs to have different arithmetics for that.You can change itarm_pid_q12though, the source is open.

author: Yansi
author_rank: Super Contributor
timestamp: May 24, 2017, 08:58:32 am
content: But noone talked about Q3.12. (you have missed a bit there)However I do understand your point. But the question wasn't how to or shall I modify the function, but how to use a regulator function with gains up to 1 in a real application, as I couldn't really figure out.Otherwise you telling me the function is useless in the original format? That would be odd.

author: Jeroen3
author_rank: Super Contributor
timestamp: May 24, 2017, 09:15:25 am
content: You also normalize what enters the system. Your setpoint and error are q15 as well.Having gains above 1 doesn't make sense, because you'll turn the system in an on/off controller.

author: Yansi
author_rank: Super Contributor
timestamp: May 24, 2017, 11:34:37 am
content: QuoteStrongly doubt that. Can you make a proof?How do you make an "on/off regulator" by amplifying the error input by more than 1? That's pure nonsense, isn't it? I am really no expert on control theory, but I am not aware of any theorem saying you cannot use gains larger than 1.

author: Jeroen3
author_rank: Super Contributor
timestamp: May 24, 2017, 12:36:06 pm
content: This is the implementation and you can perfectly set Kx to maximum of q15. But, it saturates the output as well.Code:y = y[n-1] + (Kp + Ki + Kd) * x + ((-Kp ) - (2 * Kd )) * x[n-1] + Kd * x[n-2]There is however nothing preventing you from using any other number as base for your q15.Such as 240 instead of 1. However, you have to convert the error to this range as well.