I will appreciate your guidance in this. I have some previous posts on this, but now I'm showing the code. I'm designing an embedded PI controller using a STM32 Nucleo board. In the PWM configuration, a 0 means 0% duty and 800 means 100% duty. The objetive is to regulate the speed of a PMDC motor. I'm confused about the PI output and the duty cycle relationship. This is what I have:

int error=0;
int target_RPM=0;
int duty_cycle=0;
int Kp = 0;
int integral = 0;
int current_RPM = 0;
int Ki = 0;

I plan to execute the following PID loop every 5 ms (not sure yet) with an interrupt.

//Get current RPM
current_RPM = read_RPM();

//Get the error
error = target_RPM - current_RPM;

//Calculate the integral
integral = integral+error;

//Calculate the Control Variable
duty_cycle = (Kp*error) + (Ki*integral);

//Limit the Control Variable to within 0-800
    duty_cycle = 800;
else if (duty_cycle<0){
    duty_cycle = 0;
htim1.Instance->CCR1 = duty_cycle;

I still don't have the PI constants. First, I want to make sure that the algorithm is correct. Also, I know I need anti-wind up for the integral variable, but still not sure how to implement it.


It's a very basic PI controller with lot of issues. You should make an incremental type also known as velocity algorithm (Astrom et al.), you can use Simpson formula for integrator or similar trapezoidal numerical integration. With velocity algorithm it is not allowed to use it without the integrator, but anti-windup is quite easy to implement.

Other way is to construct an Astrom controller, with separate components. Then you can turn off the integrator, but you'll need a integral tracking control for anti-windup which is CPU demanding as it uses sqrt() function.

You'd better read at least some articles, strating with Astrom: Astriom

Due to lot of undervotes in the past I won't publish PID algorithms, at least until you won't read out some basics.

T0...sample time
Ti....integration time
ek....error = setpoint - process value

//at init or parameter change compute q0, q1 
q0 = KP*(1 + T0/2*Ti);
q1 = −KP*(1 − T0/2Ti);

//every sample time ISR compute output
ek = SP-PV;
uk = q0*ek + q1*ek_1 + uk_1;
if uk > max_value 
    uk = max_value;
elsif uk < min_value 
    uk = min_value;
uk_1 =uk;
ek_1 = ek;
  • \$\begingroup\$ Yes, I had read Astrom. But I still can't manage to program an effective PI controller in my microcontroller, that's why I'm asking for help \$\endgroup\$
    – user115094
    Nov 17 '18 at 15:54
  • \$\begingroup\$ Which way have you decided? The incremental or with separate parts? Here it is a good book about controllers and coresponding MATLAB implemenatation (search for STCSL). paginapessoal.utfpr.edu.br/erig/controle%20II/… \$\endgroup\$ Nov 17 '18 at 20:39
  • \$\begingroup\$ @XavierPachecoPaulino Then you have a code under zn2pi (page 250). q0 and q1 are coeficients derived from Kp, Ti, T0. u(k) is the output calculated every sample time T0. then copy u(k-1)=u(k); e(k-1)= e(k),....will edit the answer. \$\endgroup\$ Nov 17 '18 at 20:49
  • \$\begingroup\$ @XavierPachecoPaulino I have edited, watch out for type of variables, they have to be all float, not integers as from your example. \$\endgroup\$ Nov 17 '18 at 21:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy