Estoy tratando de descubrir cómo reproducir sistemas de circuito cerrado en Arduino que fueron diseñados inicialmente en Simulink.
Tome el siguiente sistema de circuito cerrado con retroalimentación de unidad y ganancia:
DondeGp(z)esunafuncióndetransferenciadiscreta,quetomalaformade:
\$Gp(z)=\frac{0.1288z-0.06234}{z^2-0.7813z+0.1817}\$
ElsistemadecircuitocerradosereplicóenArduinoconelsiguientecódigo:
intiteration(0);doubley(0),e(0);doubleGp_y_0(0),Gp_y_1(0),Gp_y_2(0),Gp_x_0(0),Gp_x_1(0),Gp_x_2(0);voidsetup(){Serial.begin(115200);}doubleGp_z(doubleGp_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;returnGp_y_0;}voidloop(){delay(500);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.println();iteration++;}
Laplanta,Gp,seimplementacorrectamenteenArduino.Probéquesurespuestadebucleabiertoseprobóconunpasodeentrada:losvaloresadquiridoscoincidíanconMATLABcon12dígitosdeprecisión.
Sinembargo,cuandocierroelbucle,observoquedespuésdelaprimeraiteraciónlasalidaesdiferentealasalidaenSimulink.ArduinomuestramásoscilacionesenlarespuestaalescalónquelasmostradasenSimulink.Estoyconvencidodequeelrazonamientoparaestoeselordendelasoperaciones.MiobjetivoeshacercoincidirlasalidadeArduinoconlassimulacionesqueobtengodeSimulink.Parecequenopuedohacerlascoincidir.
Aquíestánlas10primerasmuestras(númerodeinteración,error,salida):
Arduino
020.0000000000.000000000120.0000000002.575358775217.4246412253.340676550316.6593234503.138910827416.8610891732.904174249517.0958257512.831139893617.1688601072.834391925717.1656080752.844978145817.1550218552.847686323917.1523136772.846717691
Simulink
020.0000000000000000117.4246412251599352.575358774840067216.9909470914473963.009052908552605317.0154834653193242.984516534680677417.0832809882711592.916719011728840517.1245892778839382.875410722116062617.1434474120396102.856552587960392717.1508198023258742.849180197674125817.1533784686048282.846621531395171917.1541676721013662.845832327898634
Almirarlosnúmeros,puedequenoparezcaunagrandiferencia,peroaldiseñaruncontrolador,esMUYimportante,casihacequelasherramientasdediseñodeSimulinkseaninútilescuandoseimplementanenArduino.
Gracias,
EDITAR:AclaracióndelafunciónGp_z()enArduino.Paraimplementarunafuncióndetransferenciadiscreta,comoGp(z)enArduino.RealicéunatransformadaZinversaenGp(z):
- MultiplicaGp(z)por\$\frac{z^{-2}}{z^{-2}}\$:
\$\frac{Y(z)}{X(z)}=\frac{0.1288z^{-1}-0.06234z^{-2}}{1-0.7813z^{-1}+0.1817z^{-2}}\$
\ $ Y (z) = X (z) 0.1288z ^ {- 1} - X (z) 0.06234z ^ {- 2} + Y (z) 0.7813z ^ {- 1} - Y (z) 0.1817z ^ {- 2} \ $
- Transformada Z inversa:
\ $ y [n] = 0.1288x [n-1] - 0.06234x [n-2] + 0.7813y [n-1] - 0.1817y [n-2] \ $
Esta fórmula se implementó en la función Gp_z ().
ACTUALIZACIÓN: cambiando el orden de ejecución de e y y en Arduino:
void loop() {
delay(500);
y = Gp_z(e);
e = 20.0 - y;
Serial.print(iteration); Serial.print('\t');
Serial.print(e, 9); Serial.print('\t');
Serial.print(y, 9); Serial.print('\t');
Serial.println();
iteration++;
}
Aquí está la salida resultante:
0 20.000000000 0.000000000
1 20.000000000 0.000000000
2 17.424641225 2.575358775
3 16.659323450 3.340676550
4 16.861089173 3.138910827
5 17.095825751 2.904174249
6 17.168860107 2.831139893
7 17.165608075 2.834391925
8 17.155021855 2.844978145
9 17.152313677 2.847686323
Hay una iteración adicional de las condiciones iniciales y los números se ven mejor pero aún con un exceso importante en comparación con Simulink. No creo que esta sea la solución al problema.