Witam, mam problem z napisaniem algorytmu regulatora PID w języku C++ (choć język nie ma tu znaczenia) aby pokrywał się z wynikami zamodelowanego układu w MatLab Simulink (lub uzasadnić dlaczego się nie pokrywa).
Kod algorytmu regulatora (testowany w jdoodle):
#include <iostream>
using namespace std;
double dt = 0.5;
double Kp = 0.1;
double Ki = 0.1;
double Kd = 0.1;
double pre_error = 0;
double integral = 0;
double calculate(double setpoint, double pv) {
double error = setpoint - pv;
//P
double Pout = Kp * error;
//I
integral = integral + (error * dt);
double Iout = Ki * integral;
//D
double derivative = (error - pre_error) / dt;
double Dout = Kd * derivative;
//PID
double out = Pout + Iout + Dout;
pre_error = error;
return out;
}
int main() {
double setpoint = 20;
double pv = 0;
for (float t = 0; t <= 50; t++) {
cout << pv << endl;
double syg_ster = calculate(setpoint, pv);
//cout << "sygnal sterujacy: " << syg_ster << endl;
pv += syg_ster;
}
}
Otrzymujemy przykładowo dla 120 punktów z wartością zadaną 20 oraz warunkiem początkowym 0.

Natomiast zamodelowany regulator PID w MatLab Simulink przedstawia inny wykres:

Na wykresie z Simulink nie ma żadnego przesterowania.

Oraz ustawienia Solvera:

Nie mogę dojść, jaka jest różnica. Pomimo, że regulator z mojego algorytmu działa prawidłowo to nie pokrywa się z tym z MatLaba pomimo tych samych wartości nastaw i nie wiem jak to logicznie uzasadnić. Duży wpływ na wyniki ma zmienna dt (czas próbkowania) ale zmiana sample time w MatLab nie zmienia za wiele. Czy to wina Solvera i użytego w niej Eulera?
Sprawdziłem też inne gotowe algorytmy ale również się nie pokrywają:
https://gist.github.com/bradley219/5373998
https://github.com/pms67/PID
Liczę na waszą pomoc i z góry dziękuje.