I am trying to simulate a microcontroller controlled boost converter on Simulink. Because Simulink doesn't have a microcontroller, I wrote a MATLAB function that emulates one.
In case you're wondering why I'm doing this instead of using a PID control block (which is native to Simulink), it's because I'm going to make an STM32 controlled DC-DC converter, which is why I am trying to emulate a microcontroller.
Before I explain the problem, let me explain the MCU function. The MCU function has two inputs: ADC0 and ADC1. These inputs read an analog value and convert it into a 12-bit equivalent value (which you will see in a bit). I am feeding the output voltage to ADC0 and the reference voltage to ADC1.
The MUC function has one output: Dcontrol. This outputs a value between 0 and 1, which is fed to a PWM block. The output Dcontrol is calculated using a praportional-integral (PI) algorithm.
function Dcontrol = MCU(ADC0, ADC1)
%Initialising the integral error term to zero
err_I = 0;
%This, as I shall demonstrate, causes a problem.
%Converting inputs into 12-bit equivalent value
Vout = (ADC0/3.3)*4096;
Vref = (ADC1/3.3)*4096;
%Calculating the error, i.e., difference between set-point and
%measured-value
err = Vref - Vout;
%Calculating the proporational error
err_P = err;
%Calculating the integral error
err_I = err_I + err;
%Saturating err_I to prevent integral windup
if(err_I > 800)
err_I = 800;
end
if(err_I < 0)
err_I = 0;
end
%Saturating err_P
if(err_P > 100)
err_P = 100;
end
if(err_P < -100)
err_P = -100;
end
%Calculating PI
PI = err_I + err_P;
%Disallowing a negaive PI value
if(PI < 0)
PI = 0;
end
%The dutycycle control output is PI/1000, which gives a max dutycycle of 0.9
Dcontrol = PI/1000;
end
The equivalent circuit using the native PI control block looks like this: enter image description here
I'm just showing this for clarity.
Coming back to the microcontroller circuit, I've set the reference voltage to 3V, which should give me 30V at the output. But when I run the simulation, this happens:
My output voltage is around 26V. This is due to the following line in the code
%Initialising the integral error term to zero
err_I = 0;
Every time the MCU function runs, the integral error gets initialised to zero. This results in the error term (and hence Dcontrol) getting improperly calculated. If I change my input voltage, the output voltage also changes. This is due to the integral term getting reinitialised. If is remove that line, I get an error:
Undefined function or variable 'err_I'. The first assignment to a local variable determines its class.
So my question is - is there a way to initialise the integral error term during runtime only, the way it's possible with the native PID block?
In other words, I want to modify the code to have this effect
%Initialising the integral error term to zero
void setup()
{
err_I = 0;
}
void loop()
{
%Converting inputs into 12-bit equivalent value
Vout = (ADC0/3.3)*4096;
Vref = (ADC1/3.3)*4096;
%Calculating the error, i.e., difference between set-point and
%measured-value
err = Vref - Vout;
%Calculating the proporational error
err_P = err;
%Calculating the integral error
err_I = err_I + err;
%Saturating err_I to prevent integral windup
if(err_I > 800)
err_I = 800;
end
if(err_I < 0)
err_I = 0;
end
%Saturating err_P
if(err_P > 100)
err_P = 100;
end
if(err_P < -100)
err_P = -100;
end
%Calculating PI
PI = err_I + err_P;
%Disallowing a negaive PI value
if(PI < 0)
PI = 0;
end
%The dutycycle control output is PI/1000, which gives a max dutycycle of 0.9
Dcontrol = PI/1000;
end
}
1 Answer 1
Use an S-Function instead of .m code block.
With S-Function you can write C code with one-time-run-only functions, there you can declare variables once to initialize their values and then have them in the main loop function.
-
\$\begingroup\$ I shall try it. \$\endgroup\$Prathik Prashanth– Prathik Prashanth2021年09月30日 13:53:02 +00:00Commented Sep 30, 2021 at 13:53
Explore related questions
See similar questions with these tags.
err_I
is reset everytime the function is called, so if (if) it's called 100 times, it will be reset 100 times. Maybe it will help to seterr_i
as a global parameter that is initialized to zero before the simulation and then leave the function to do what it wills with it? \$\endgroup\$err_I=0
and useerr_I
as a global parameter, before the simulation starts. IIRC, it works that way, too. But only vague memories. \$\endgroup\$