This repository provides a tutorial-oriented simulation of a digital PI control loop applied to a discrete-time ARX model identified from experimental data.
The objective is to reproduce in simulation the same discrete behavior expected when the controller is later implemented on a microcontroller (Arduino, Teensy, ESP32, etc.), including actuator saturation.
⚠️ Note: This tutorial is for educational purposes only. It focuses on simulation and understanding discrete-time digital control with ARX models.
- Model a system using a discrete-time ARX model identified experimentally
- Implement a discrete PI controller using incremental form
- Add saturation limits to emulate real actuator constraints
- Compare reference tracking and control signal behavior
The discrete-time ARX model is defined as:
Where:
Matlab
a = [1 -1.9366 1.1523 -0.2144]; % note the sign for implementation
b = [0 0 0 -0.001961]; % B(z) with zeros for delaysPython
a = np.array([1, -1.9366, 1.1523, -0.2144], dtype=float) # note the sign for implementation
b = np.array([0, 0, 0, -0.001961], dtype=float) # B(z) with zeros for delaysThe discrete model implemented is:
Matlab
y(k) = -a(2)*y1 - a(3)*y2 - a(4)*y3 + b(1)*u1 + b(2)*u2 + b(3)*u3+ b(4)*u4;Python
y[k] = (-a[1] * y1 -a[2] * y2-a[3] * y3 + b[0] * u1 + b[1] * u2 + b[2] * u3 + b[3] * u4)- Sampling period:
$$T_s = 0.004 s$$ - This model was identified from experimental data using ARX method.
The discrete control law implemented is:
Matlab
error = Ref(k) - y(k);
u = u1 + K0*error + K1*error1;Python
error = Ref[k] - y[k]
u = u1 + K0 * error + K1 * error1With tuning parameters derived from:
- Proportional gain:
$$K_p$$ - Integral time:
$$T_i$$ - Sampling time:
$$T_s$$
Where
To emulate microcontroller behavior, the controller output is limited to a predefined range:
- Prevents unrealistic actuator commands
- Reflects PWM or DAC limits on embedded hardware
- Avoids integrator wind-up if actuator saturates
Example: -100% ≤ u(n) ≤ 100%
Without saturation, simulation results may falsely assume an ideal actuator with infinite authority, which never matches microcontroller deployments. To emulate real microcontroller behavior — such as PWM range or fixed DAC limits —
Matlab
if u > 100
u=100;
end
if u <-100
u=-100;
endPython
if u > Umax:
u = Umax
elif u < Umin:
u = UminBelow are example plots generated with the script:
Support me on Patreon https://www.patreon.com/c/CrissCCL
MIT License
