Errors in implementing a closed-loop system into Arduino designed in Simulink

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,

It has to do with the order the code is executed. You're absolutely sure that above output is generated by the code in your post? In this case the compiler reorder some stuff and does this in a wrong way. The output is displaced, The error of iteration 3 corresponds to the result of line 2 (16.659323450 + 3.340676550 = 20). I have no Due to check it but I don't see an easy solution. Are you using the newest IDE (1.8.3)?

pylon:
It has to do with the order the code is executed. You're absolutely sure that above output is generated by the code in your post? In this case the compiler reorder some stuff and does this in a wrong way. The output is displaced, The error of iteration 3 corresponds to the result of line 2 (16.659323450 + 3.340676550 = 20). I have no Due to check it but I don't see an easy solution. Are you using the newest IDE (1.8.3)?

pylon,

Sorry, I just fixed it. The snippet of code I had was old code I was testing to try and fix this problem - I changed it to the correct code to generate that output. Now the code in the post generates the results in the post.

I am using 1.8.2.

That code produces the error because the two lines

  e = 20.0 - y;
  y = Gp_z(e);

are in the wrong order. You first calculate the error (e) and then you recalculate the result (y), so the result is ahead one iteration.

Switching those two calculation produce the following results:

Iteration, Error, Output, Error + Output

0	20.000000000	0.000000000	20.000000000	
1	20.000000000	0.000000000	20.000000000	
2	17.424641225	2.575358775	20.000000000	
3	16.659323450	3.340676550	20.000000000	
4	16.861089173	3.138910827	20.000000000	
5	17.095825751	2.904174249	20.000000000	
6	17.168860107	2.831139893	20.000000000	
7	17.165608075	2.834391925	20.000000000	
8	17.155021855	2.844978145	20.000000000	
9	17.152313677	2.847686323	20.000000000

The results look a bit better, however now there is an extra iteration of initial conditions. And yes although the Error and Output add up to the reference (20), but the numbers are different than what was derived from Simulink - maybe precision is causing this?

Post the code that generated that output. I don't want to guess anymore. The posted code outputs just two numbers so you must have changed more than the two lines. If you're picky about the results, I have to be picky about the code.