Hello,
I am trying to figure out how to implement closed-loop systems in Arduino (Due) that were designed initially designed in Simulink. The closed-loop system designed in Simulink (see attached picture or this Gyazo) has unity gain and the plant Gp(z) takes the following form:
Gp(z) = (0.1288z - 0.06234)/(z^2 - 0.7813z +0.1817);
The closed-loop system was implemented on Arduino with the following code:
int iteration(0);
double y(0), e(0);
double Gp_y_0(0), Gp_y_1(0), Gp_y_2(0), Gp_x_0(0), Gp_x_1(0), Gp_x_2(0);
void setup() {
Serial.begin(115200);
for (int j = 0; j < 3; j++) Serial.println(); // clc
}
double Gp_z (double Gp_x_0) {
Gp_y_0 = (0.128767938742003 * Gp_x_1) + (-0.062336933973903 * Gp_x_2) - (-0.781272292546052 * Gp_y_1) - (0.181746970098960 * Gp_y_2);
Gp_x_2 = Gp_x_1;
Gp_x_1 = Gp_x_0;
Gp_y_2 = Gp_y_1;
Gp_y_1 = Gp_y_0;
return Gp_y_0;
}
void loop() {
delay(1000);
e = 20.0 - y;
y = Gp_z(e);
Serial.print(iteration++); Serial.print('\t');
Serial.print(e, 9); Serial.print('\t');
Serial.print(y, 9); Serial.print('\t');
Serial.println();
}
The plant, Gp(z), was implemented correctly. I tested the open-loop response and compared the values to those generated in the Simulink model; they were identical upto 12 digits of precision. However, when I close the loop, the values start to differ after the 1st iteration.
Here are first 10 samples (Iteration, Error, Output):
Arduino
0 20.000000000 0.000000000
1 20.000000000 2.575358775
2 17.424641225 3.340676550
3 16.659323450 3.138910827
4 16.861089173 2.904174249
5 17.095825751 2.831139893
6 17.168860107 2.834391925
7 17.165608075 2.844978145
8 17.155021855 2.847686323
9 17.152313677 2.846717691
Simulink
0 20.000000000000000 0
1 17.424641225159935 2.575358774840067
2 16.990947091447396 3.009052908552605
3 17.015483465319324 2.984516534680677
4 17.083280988271159 2.916719011728840
5 17.124589277883938 2.875410722116062
6 17.143447412039610 2.856552587960392
7 17.150819802325874 2.849180197674125
8 17.153378468604828 2.846621531395171
9 17.154167672101366 2.845832327898634
Step 0 is identical in both cases with an Error of 20.00 and a Output of 0.00, which is correct. However, Step 1 (Arduino) still has an error of 20.00, while Step 1 (Simulink) it shows 17.42. This kind of makes sense to me since the current output going into Step 1 is 0.00 meaning that the error should remain 20.00. However in Simulink, the error in Step 1 is updated already to 17.42. Notice the error 17.42 does eventually appear in Step 2 (Arduino).
Also, since this is an error table, the error + output should equal the reference 20. In Simulink, this is the case, in Arduino this is not.
I am convinced that this discrepancy is caused by order of operations, but I don't know how to fix it. My goal is get the output of Arduino identical to Simulink.
If anyone is interested how I implemented the discrete transfer function, you can see my original post on StackExchange.
Thank you,
