Mikrocontroller und Digitale Elektronik
›
Thread
Implementierung eines Zustandreglers mit Beobachter
B
Buell24
Gast
11.12.2011 14:15
#2454079
Ich habe in Matlab-Simulink einen Zustandregler mit Beobachter für ein
inverses Pendel ausgelegt und diskretisiert.
http://www.library.cmu.edu/ctms/ctms/state/obs.gif
Ich bin dabei analog zu:
http://www.library.cmu.edu/ctms/ctms/examples/pend/diginvss.htm
vorgegangen.
Nun möchte ich diesen Zustandsregler auf einem Mikrocontroller (Arduino
Mega) implementieren.
Folgende Gleichungen habe ich aufgestellt:
x[n + 1] = Ax[n] + Bu[n]
wobei u[n] = - Kx[n] (negativ rückgekoppelt)
x[n + 1] = Ax[n] - BKx[n] = (A-BK)x[n]
Mit dem Beobachter sieht das ganze so aus:
x^[n + 1] = (A-BK)x^[n] - L(y^-y)
x^ = predicted state, y^ = predicted output, y= measured outputs
Implementiert habe ich das ganze volgendermassen:
.
.
.
.
//matrix A-B*K
const double matr_A_BK[4][4] = {
1.0013, 0.0112, -0.0061, -0.0020,
0.2633, 1.2461, -1.2260, -0.4024,
0.0012, 0.0012, 0.9947, 0.0081,
0.2489, 0.2326, -1.0661, 0.6201 };
const double matr_L[2][4] = {
2.6319, -0.0108,
173.1476, -1.3975,
-0.0086, 2.6289,
-1.1521, 172.8517 };
const double matr_K[4] = {
-65.9759, -61.7565, 314.0219, 100.8610 };
double state[4] = {
0, 0, 0, 0}; //state vector
double nstate[4] = {
0, 0, 0, 0}; //temporarly stores new state
.
.
.
.
p[0] = state[0]; //two predicted states (x^ and theta^)
p[1] = state[2];
read_current_distance_m1();
s[1] = (distanceM1-initDistanceM1)/6573.75; //two sensors (x and
theta)
s[2] = (analogRead(10)-513.0);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) { // (A-BK)*state
nstate[i] = nstate[i] + matr_A_BK[i][j]*state[j];
}
for(int j = 0; j < 2; j++) { //-L*pred + L*measures
nstate[i] = nstate[i] + matr_L[i][j]*( s[j] - p[j] );
}
}
//update states
for(int i = 0; i<4; i++) {
state[i] = nstate[i];
nstate[i] = 0; //init for following cycle
}
.
.
.
.
Leider muss aber ein Fehler im Code vorhanden sein, die Variable
nstate[i] ist nämlich immer 0.00. Könnt Ihr mir sagen, ob dieser Ansatz
der Implementierung überhaupt richtig ist?
B
Buell24
Gast
16.12.2011 06:24
#2460884
Kann mir niemand einen Rat dazu geben?
Ich wäre schon um einen Literaturverweis für die Implementierung eines
Zustandsreglers dankbar...
D
dunno..
Gast
16.12.2011 07:58
#2460908
dein code sieht aber nicht so aus, oder...?
poste mal alles, und benutze die code- einbettungsfunktion des forums..
oder wenns zuviel wird, häng die datei an..
B
Buell24
Gast
16.12.2011 16:27
#2461658
Der Code wurde für einen Arduino Mega geschrieben und besteht aus zwei
Dateien:
StateSpaceControl.ino:
Beinhaltet den Regel Algorithmus
RoboClaw.ino:
Beinhaltet die Kommunikation zum Motor Controller.
StateSpaceControl.ino: 1 #define SERIAL_BAUD 57600
2 #define INPUT_COUNT 5 //number of analog inputs
3 #define VDD 5000.0f //Analog reference voltage in mV
4 #define PI 3.14159265358979f
5
6 //DIGITAL OUTPUT
7 int ledGREENpin = 2 ;
8 int ledREDpin = 3 ;
9 int oscilloscopePin = 8 ; //oscilloscope pin to work out the program loop time
10 boolean oscilloscopeState = false ;
11
12 //Analog Input
13 float poti8 = 0 ;
14 float poti9 = 0 ;
15
16
17 //Global variables Motor Controller-----------------------------------------------------------------------------------------------
18 float level = 0 ;
19 int speedMotor1 ;
20 long distanceM1 = 0 ;
21 long initDistanceM1 = 0 ;
22
23 //matrix A-B*K
24 const double matr_A_BK [ 4 ][ 4 ] = {
25 1 . 0013 , 0 . 0112 , - 0 . 0061 , - 0 . 0020 ,
26 0 . 2633 , 1 . 2461 , - 1 . 2260 , - 0 . 4024 ,
27 0 . 0012 , 0 . 0012 , 0 . 9947 , 0 . 00 81 ,
28 0 . 2489 , 0 . 2326 , - 1 . 0661 , 0 . 6201 };
29
30 const double matr_L [ 2 ][ 4 ] = {
31 2 . 6319 , - 0 . 010 8 ,
32 173 . 1476 , - 1 . 3975 ,
33 - 0 . 00 86 , 2 . 6289 ,
34 - 1 . 1521 , 172 . 8517 };
35
36 const double matr_K [ 4 ] = {
37 - 65 . 9759 , - 61 . 7565 , 314 . 021 9 , 100 . 8610 };
38
39 double state [ 4 ] = {
40 0 , 0 , 0 , 0 }; //state vector
41
42 double nstate [ 4 ] = {
43 0 , 0 , 0 , 0 }; //temporarly stores new state
44
45
46 void setup () {
47 Serial . begin ( SERIAL_BAUD );
48 setupRoboClaw ();
49
50 //digital outputs
51 pinMode ( ledREDpin , OUTPUT );
52 pinMode ( ledGREENpin , OUTPUT );
53 pinMode ( oscilloscopePin , OUTPUT );
54
55 digitalWrite ( ledREDpin , HIGH );
56 digitalWrite ( ledGREENpin , LOW );
57 Serial . println ( "start" );
58 read_current_distance_m1 ();
59 initDistanceM1 = distanceM1 ;
60 }
61
62 void loop () {
63
64 double p [ 2 ] = {
65 0 , 0 }; //two predicted state
66 double s [ 2 ] = {
67 0 , 0 }; //two outputs
68 double force = 0 ; //force that must be applied to motor
69 long now = millis ();
70 long last = millis ();
71
72
73 while ( 1 ) { //-------------CYCLE
74 digitalWrite ( ledREDpin , LOW );
75 digitalWrite ( ledGREENpin , HIGH );
76 now = millis ();
77
78 while ( last == now ) { //wait until 1 microsecond elapses
79 // sample time = 1 ms
80 now = millis ();
81 }
82 last = now ;
83
84 // -L*pred + L*measures
85 p [ 0 ] = state [ 0 ]; //two predicted states (x^ and theta^)
86 p [ 1 ] = state [ 2 ];
87 read_current_distance_m1 ();
88 s [ 0 ] = ( distanceM1 - initDistanceM1 ) / 6573 . 75 ; //two sensors (x and theta)
89 s [ 1 ] = ( analogRead ( 10 ) - 511 . 0 ) * 0 . 00405 890523719604651162790697674 ;
90
91
92 for ( int i = 0 ; i < 4 ; i ++ ) {
93 for ( int j = 0 ; j < 4 ; j ++ ) { // _________(A-BK)*state
94 nstate [ i ] = nstate [ i ] + matr_A_BK [ i ][ j ] * state [ j ];
95 }
96 for ( int j = 0 ; j < 2 ; j ++ ) { //-L*pred + L*measures
97 nstate [ i ] = nstate [ i ] + matr_L [ i ][ j ] * ( s [ j ] - p [ j ] );
98 }
99 Serial . print ( " nstate[" );
100 Serial . print ( i );
101 Serial . print ( "]= " );
102 printDouble ( nstate [ i ], 10 );
103 }
104 Serial . println ( " end for" );
105
106
107 //update states
108 for ( int i = 0 ; i < 4 ; i ++ ) {
109 state [ i ] = nstate [ i ];
110 nstate [ i ] = 0 ; //init for following cycle
111 }
112
113
114 // controller action
115 force = 0 ;
116 for ( int i = 0 ; i < 4 ; i ++ ) { //controller action
117 force = force + ( state [ i ] * matr_K [ i ]);
118 }
119 level = force * 6666 . 6 ;
120 set_motor ();
121
122 } //end of while(1)
123 }
124
125 void printDouble ( double val , byte precision ){
126 // prints val with number of decimal places determine by precision
127 // precision is a number from 0 to 6 indicating the desired decimial places
128 // example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)
129
130 Serial . print ( int ( val )); //prints the int part
131 if ( precision > 0 ) {
132 Serial . print ( "." ); // print the decimal point
133 unsigned long frac ;
134 unsigned long mult = 1 ;
135 byte padding = precision - 1 ;
136 while ( precision -- )
137 mult *= 10 ;
138
139 if ( val >= 0 )
140 frac = ( val - int ( val )) * mult ;
141 else
142 frac = ( int ( val ) - val ) * mult ;
143 unsigned long frac1 = frac ;
144 while ( frac1 /= 10 )
145 padding -- ;
146 while ( padding -- )
147 Serial . print ( "0" );
148 Serial . print ( frac , DEC ) ;
149 }
150 }
RoboClaw.ino: 1 #define address 128
2 #define ROBOCLAW_BAUD 38400
3
4 signed char Motor1percent = 0 ;
5 signed char Motor2percent = 0 ;
6 int incomingByte = 0 ;
7
8 void setupRoboClaw ()
9 {
10 Serial1 . begin ( ROBOCLAW_BAUD );
11 delay ( 100 );
12 set_min_main_voltage_value ( 15 ); //9V formula: (voltage-6)*5
13 set_max_main_voltage_value ( 82 ); //16V formula: voltage*5.25
14 set_min_logic_voltage_value ( 15 ); //9V formula: (voltage-6)*5
15 set_max_logic_voltage_value ( 82 ); //16V formula: voltage*5.25
16 delay ( 100 );
17 set_speed_m1_m2 ( 0 , 0 );
18
19 }
20
21 /*
22 ** 2 - Set Minimum Main Voltage
23 ** Sets main battery (B- / B+) minimum voltage level. If the battery voltages drops below the set
24 ** voltage level Robo Claw will shut down. The value is cleared at start up and must set after each
25 ** power up. The voltage is set in .2 volt increments. A value of 0 sets the minimum value allowed which
26 ** is 6V. The valid data range is 0 - 120 (6V - 30V). The formula for calculating the voltage is: (Desired
27 ** Volts - 6) x 5 = Value. Examples of valid values are 6V = 0, 8V = 10 and 11V = 25. Example with
28 ** Robo Claw address set to 128:
29 **
30 ** Serout P15, i19200, [128, 2, 25, (165 & 0X7F)]
31 */
32
33 void set_min_main_voltage_value ( byte min_main_battery_voltage )
34 {
35 byte serial_data [ 4 ];
36 serial_data [ 0 ] = address ;
37 serial_data [ 1 ] = 2 ;
38 serial_data [ 2 ] = min_main_battery_voltage ;
39 serial_data [ 3 ] = ( serial_data [ 0 ] + serial_data [ 1 ] + serial_data [ 2 ]) & 0x7F ;
40
41 Serial1 . write ( serial_data , sizeof ( serial_data ));
42 }
43
44 /*
45 ** 3 - Set Maximum Main Voltage
46 ** Sets main battery (B- / B+) maximum voltage level. The valid data range is 0 - 154 (0V - 30V). If
47 ** you are using a battery of any type you can ignore this setting. During regenerative breaking a back
48 ** voltage is applied to charge the battery. When using an ATX type power supply if it senses anything
49 ** over 16V it will shut down. By setting the maximum voltage level, Robo Claw before exceeding it will
50 ** go into hard breaking mode until the voltage drops below the maximum value set. The formula for
51 ** calculating the voltage is: Desired Volts x 5.12 = Value. Examples of valid values are 12V = 62, 16V
52 ** = 82 and 24V = 123. Example with Robo Claw address set to 128:
53 **
54 ** Serout P15, i19200, [128, 3, 82, (213 & 0X7F)]
55 */
56
57 void set_max_main_voltage_value ( byte max_main_battery_voltage )
58 {
59
60 byte serial_data [ 4 ];
61 serial_data [ 0 ] = address ;
62 serial_data [ 1 ] = 3 ;
63 serial_data [ 2 ] = max_main_battery_voltage ;
64 serial_data [ 3 ] = ( serial_data [ 0 ] + serial_data [ 1 ] + serial_data [ 2 ]) & 0x7F ;
65
66 Serial1 . write ( serial_data , sizeof ( serial_data ));
67 }
68
69
70 void set_min_logic_voltage_value ( byte min_logic_battery_voltage )
71 {
72 byte serial_data [ 4 ];
73 serial_data [ 0 ] = address ;
74 serial_data [ 1 ] = 26 ;
75 serial_data [ 2 ] = min_logic_battery_voltage ;
76 serial_data [ 3 ] = ( serial_data [ 0 ] + serial_data [ 1 ] + serial_data [ 2 ]) & 0x7F ;
77
78 Serial1 . write ( serial_data , sizeof ( serial_data ));
79 }
80
81 void set_max_logic_voltage_value ( byte max_logic_battery_voltage )
82 {
83 byte serial_data [ 4 ];
84 serial_data [ 0 ] = address ;
85 serial_data [ 1 ] = 27 ;
86 serial_data [ 2 ] = max_logic_battery_voltage ;
87 serial_data [ 3 ] = ( serial_data [ 0 ] + serial_data [ 1 ] + serial_data [ 2 ]) & 0x7F ;
88
89 Serial1 . write ( serial_data , sizeof ( serial_data ));
90 }
91
92 void set_speed_m1_m2 ( long speedM1 , long speedM2 ) {
93 byte ab [ 11 ];
94 ab [ 0 ] = address ;
95 ab [ 1 ] = 37 ;
96 ab [ 2 ] = ( speedM1 >> 24 ) & 0xff ;
97 ab [ 3 ] = ( speedM1 >> 16 ) & 0xff ;
98 ab [ 4 ] = ( speedM1 >> 8 ) & 0xff ;
99 ab [ 5 ] = ( speedM1 >> 0 ) & 0xff ;
100 ab [ 6 ] = ( speedM2 >> 24 ) & 0xff ;
101 ab [ 7 ] = ( speedM2 >> 16 ) & 0xff ;
102 ab [ 8 ] = ( speedM2 >> 8 ) & 0xff ;
103 ab [ 9 ] = ( speedM2 >> 0 ) & 0xff ;
104 ab [ 10 ] = ( ab [ 0 ] + ab [ 1 ] + ab [ 2 ] + ab [ 3 ] + ab [ 4 ] + ab [ 5 ] + ab [ 6 ] + ab [ 7 ] + ab [ 8 ] + ab [ 9 ]) & 0x7f ;
105 Serial1 . write ( ab , sizeof ( ab ));
106 }
107
108 void read_current_distance_m1 ()
109 {
110 byte ab [ 2 ];
111 ab [ 0 ] = address ;
112 ab [ 1 ] = 16 ;
113 Serial1 . write ( ab , sizeof ( ab ));
114 delay ( 10 );
115
116 byte distanceM1_byte [ 4 ];
117 // send data only when you receive data:
118 int i = 0 ;
119 while ( Serial1 . available () > 0 ) {
120 if ( i < 4 ){
121 distanceM1_byte [ i ] = Serial1 . read ();
122 }
123 i ++ ;
124 }
125 distanceM1 = (( long ) distanceM1_byte [ 0 ]) << 24 ;
126 distanceM1 |= (( long ) distanceM1_byte [ 1 ]) << 16 ;
127 distanceM1 |= (( long ) distanceM1_byte [ 2 ]) << 8 ;
128 distanceM1 |= distanceM1_byte [ 3 ];
129 }
Der debug output sieht wie folgt aus:
1 start
2 nstate [ 0 ] = 0 . 000302 8782 nstate [ 1 ] = 0 . 0737256000 nstate [ 2 ] = - 12 . 03 98380160 nstate [ 3 ] = 0 . 0000000000 end for
3 nstate [ 0 ] = 0 . 00722 83688 nstate [ 1 ] = 48 . 0991425344 nstate [ 2 ] = - 787 . 0603735 872 nstate [ 3 ] = 13 . 0303 843360 end for
4 nstate [ 0 ] = - 3 . 0112114600 nstate [ 1 ] = 3091 . 0715704576 nstate [ 2 ] = 16104 . 0000000000 nstate [ 3 ] = 858 . 1392766592 end for
5 nstate [ 0 ] = - 194 . 064 8187712 nstate [ 1 ] = - 2546 . 0000000000 nstate [ 2 ] = - 21931 . 0000000000 nstate [ 3 ] = - 11586 . 0000000000 end for
6 nstate [ 0 ] = - 12197 . 015 9733968 nstate [ 1 ] = - 11260 . 0000000000 nstate [ 2 ] = - 32240 . 0000000000 nstate [ 3 ] = - 22153 . 0000000000 end for
7 nstate [ 0 ] = 20980 . 0000000000 nstate [ 1 ] = - 21632 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 3568 . 0000000000 end for
8 nstate [ 0 ] = 1824 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
9 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
10 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
11 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
12 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
13 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
14 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
15 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
16 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
17 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
18 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
19 nstate [ 0 ] = 0 . 0000000000 nstate [ 1 ] = 0 . 0000000000 nstate [ 2 ] = 0 . 0000000000 nstate [ 3 ] = 0 . 0000000000 end for
B
Buell24
Gast
22.12.2011 18:17
#2469704
Kann mir damit niemand helfen? Ich denke der Fehler wird irgendein
Overflow sein. Ich kann ihn nur nicht finden!!
O
Oliver
Gast
22.12.2011 19:00
#2469761
Pack dein Programm in den Debugger, und steppe da Schritt für Schritt
durch. Da musst du selber durch, die Arbeit nimmt die keiner ab.
Oliver
↑ Nach oben
← Zurück zu Mikrocontroller und Digitale Elektronik
Antwort schreiben