Hallo Kollegen,
wir haben in der Uni ein Projekt für eine Vorschubregelung einer Turbine
gemacht. Die Regelung funktioniert auch wunderbar.
Als Zusatz haben wir nun eine Verbindung zu Matlab hergestellt, dass wir
bis jetzt in einem Extra-Programm implementiert haben. Auch das
funktioniert wunderbar, wir senden einen Befehl, dann wird der
Ventilator manuell mit einem gewissen Dutycyle angesteuert. Für die
manuelle Steuerung setzen wir eine globale auf eins, dass gleiche machen
wir für die Regelung.
Nun zum Problem: Jetzt wollten wir "nur" noch den Code für den PID
Regler in das andere Programm einsetzen, so dass das die globale
Variable für die Regelung entscheidet, ob geregelt wird.
Nach 3h vergeblichen Versuchen konnte wir die Ursache auf Debug Messages
verkleinern, aber sind nicht sicher obs die wirklich sind....
Die Funktion RS232 liest die Kommandos aus und setzt je nach Kommando
die globalen Variablen flagPWM und flagCTRL.
Und wie gesagt, der PID Regler an sich funktioniert auch, allerdings nur
wenn diese Debug Messages mit drin sind........
hier der Code
1 | // Predefined compiler symbols:
| 2 | #define LEDgreen 24
| 3 | #define LEDred 25
| 4 | #define LEDyellow 26
| 5 |
| 6 | #define RS232 0
| 7 | #define CR 0x0D
| 8 |
| 9 | #define PERIOD 492
| 10 |
| 11 | // Declaration of global variables:
| 12 | // 100 bytes send + 100 bytes receive RS232Buffer + 6 bytes int.FIFO management
| 13 | byte RS232Buffer[206]; // TxD/RxD buffer RS232
| 14 | byte Linebuffer[101]; // hier wird das gelesene Zeug reingeschrieben
| 15 | byte RxCount; // Number of received characters
| 16 |
| 17 |
| 18 | // Linebuffer will be decoded into this command elements:
| 19 | byte CMD[20]; // Raw command
| 20 | byte PAR1[20]; // Command line paramter 1
| 21 | byte PAR2[20]; // Command line paramter 2
| 22 | byte PAR3[20]; // Command line paramter 3
| 23 |
| 24 | // Test-Message:
| 25 | char rmsg1[5]; // Message Command
| 26 |
| 27 |
| 28 | //Globals for Pulse Width Modulation (PWM)
| 29 | byte flagPWM; //Schalter für PWM ein oder aus
| 30 | byte flagCTRL; //Schalter für Regelung ein oder aus
| 31 | float RS232output; //Verhältnis ein zu ausschaltzeit von RS232 vorgeben oder von PID ctrl
| 32 | //float PIDoutput; //Verhältnis ein zu ausschaltzeit von PID controller
| 33 | float PWMwidth;
| 34 |
| 35 |
| 36 | int period; //period of the PWM
| 37 |
| 38 | float PID_output,pwm_output;
| 39 | word ADC_Value;
| 40 | word ang_ref;
| 41 | float ang_msurd,err,err_prev,err_acc,err_diff;
| 42 | float Kp;
| 43 | float Ki;
| 44 | float Kd;
| 45 |
| 46 | // Function of PWM previous version
| 47 |
| 48 | void pwm(float PID_output){ //function pwm //////////////////////
| 49 | //help variables///////////////////////////7
| 50 |
| 51 | int PWM_Counter_A; //pulswidth of the PWM in a promille scale
| 52 | //////////////////
| 53 | period=492;
| 54 | PWM_Counter_A=period*PID_output;
| 55 |
| 56 | Timer_T1PWM(period,PWM_Counter_A,PS_1);
| 57 | }
| 58 |
| 59 | //////////////////////////////////////////////////////////////////
| 60 | float adc2angel(word ADC_Value)
| 61 | {
| 62 | float ang_tmp;
| 63 | if(ADC_Value>425)
| 64 | {
| 65 | ang_tmp=-0.008*ADC_Value-4.6;
| 66 | }
| 67 | if(ADC_Value<=425 && ADC_Value>300)
| 68 | {
| 69 | ang_tmp=-0.016*ADC_Value-1.2;
| 70 | }
| 71 | if(ADC_Value<=300 && ADC_Value>222)
| 72 | {
| 73 | ang_tmp=-0.025*ADC_Value+1.692;
| 74 | }
| 75 | if(ADC_Value<=222 && ADC_Value>170)
| 76 | {
| 77 | ang_tmp=-0.038*ADC_Value+4.538;
| 78 | }
| 79 | if(ADC_Value<=170 && ADC_Value>130)
| 80 | {
| 81 | ang_tmp=-0.05*ADC_Value+6.5;
| 82 | }
| 83 | if(ADC_Value<=130 && ADC_Value>105)
| 84 | {
| 85 | ang_tmp=-0.08*ADC_Value+10.4;
| 86 | }
| 87 | if(ADC_Value<=105 && ADC_Value>86)
| 88 | {
| 89 | ang_tmp=-0.105*ADC_Value+13.05;
| 90 | }
| 91 | if(ADC_Value<=86 && ADC_Value>73)
| 92 | {
| 93 | ang_tmp=-0.153*ADC_Value+17.23;
| 94 | }
| 95 | if(ADC_Value<=73 && ADC_Value>59)
| 96 | {
| 97 | ang_tmp=-0.142*ADC_Value+16.42;
| 98 | }
| 99 | if(ADC_Value<=59 && ADC_Value>52)
| 100 | {
| 101 | ang_tmp=-0.285*ADC_Value+24.85;
| 102 | }
| 103 | if(ADC_Value<=52 && ADC_Value>46)
| 104 | {
| 105 | ang_tmp=-0.333*ADC_Value+27.33;
| 106 | }
| 107 | if(ADC_Value<=46 && ADC_Value>42)
| 108 | {
| 109 | ang_tmp=-0.5*ADC_Value+35;
| 110 | }
| 111 | if(ADC_Value<=42)
| 112 | {
| 113 | ang_tmp=-1.0*ADC_Value+56;
| 114 | }
| 115 | return ang_tmp;
| 116 |
| 117 |
| 118 | }
| 119 |
| 120 | /////////////main//////////////////////////////
| 121 | void main(void)
| 122 | {
| 123 | //****************************
| 124 | //Declaration of variables
| 125 | int i,PWMwidth;
| 126 |
| 127 | //*****************************
| 128 | //Dafault settings of variables
| 129 | i=0;
| 130 | PWMwidth=1;
| 131 | RS232output=1;
| 132 | flagPWM=0;
| 133 | flagCTRL=0;
| 134 |
| 135 | //************
| 136 | //Initializing
| 137 | Port_DataDirBit(16,1); //Define PortD.0 as output
| 138 | Port_DataDirBit(17,1); //Define PortD.1 as output
| 139 | Port_DataDirBit(LEDyellow,1); //Define PortD.2 as output
| 140 | Timer_T1PWM(PERIOD,1,PS_1); //Define PWM with duration of 1 (0 not allowed!!)
| 141 | Serial_Init_IRQ(RS232,RS232Buffer,100,100,SR_8BIT|SR_1STOP|SR_NO_PAR,SR_BD19200);
| 142 | // Initialize RS232: 19200 bps, 8 Bit, 1 Stop, NP
| 143 | // 100 bytes receive RS232Buffer - 100 bytes send RS232Buffer
| 144 |
| 145 | //***************************
| 146 | //Send Test-Message to MATLAB
| 147 | rmsg1="C-Control PRO ready for receiving\r\n";
| 148 |
| 149 | for(i=0;i<2;i++)
| 150 | Serial_WriteText(RS232,rmsg1); // Serielle Schnittstelle Test senden
| 151 |
| 152 |
| 153 | //*********************************************************************************************
| 154 |
| 155 | PID_output=0.0;
| 156 | ang_ref=0.0;
| 157 | err_acc=0;
| 158 | err_prev=0.0;
| 159 | ADC_Set(ADC_VREF_VCC, ADC0);
| 160 | //Kp=0.01;
| 161 | //Ki=0.005;
| 162 | //Kd=0.5;
| 163 | //Zigler Nicolas method
| 164 | /*Kp=0.0360;
| 165 | Ki=0.0411;
| 166 | Kd=0.0079;*/
| 167 | Kp=0.01;
| 168 | Ki=0.005;
| 169 | Kd=0.5;
| 170 |
| 171 | while (1)
| 172 | {
| 173 | ////////// PID regler///////////////////////////////////////////////
| 174 | ADC_Value=ADC_Read();
| 175 | ang_msurd=adc2angel(ADC_Value);
| 176 | if(ang_msurd>15) ang_msurd=15;
| 177 | if(ang_msurd<-10) ang_msurd=-10;
| 178 | //Msg_WriteHex(ADC_Value);
| 179 | err=ang_ref+ang_msurd;
| 180 | err_acc=err_acc+err;
| 181 | err_diff=err-err_prev;
| 182 | if(err_acc>20) err_acc= 20.0;
| 183 | if(err_acc<-20) err_acc= -20.0;
| 184 | PID_output=Kp*err+Ki*err_acc+Kd*err_diff;
| 185 | pwm_output=(PID_output+0.5);
| 186 | //Msg_WriteChar(CR); // HIER FEHLER WAHRSCHEINLICH
| 187 | //Msg_WriteFloat(err_acc); // HIER FEHLER WAHRSCHEINLICH
| 188 | if(pwm_output<0.05) pwm_output=0.05;
| 189 | if(pwm_output>0.95) pwm_output=0.95;
| 190 |
| 191 | //Msg_WriteInt(100);
| 192 | PWMwidth=PERIOD*pwm_output; // PWMwidth = hole periode*PIDoutput[0.00-1.00]
| 193 | //Timer_T1PWA(PWMwidth); // PWM with value PIDoutput
| 194 | Timer_T1PWM(PERIOD,PWMwidth,PS_1);
| 195 |
| 196 | // pwm(pwm_output); // Previous version
| 197 | err_prev=err;
| 198 | // AbsDelay(10); // Previous version
| 199 |
| 200 |
| 201 | //////////////////////////////////////////////////////////////////////////////
| 202 |
| 203 | readRS232(); // Read out RS232
| 204 |
| 205 | if(flagPWM & !flagCTRL) // PWM switch on/off
| 206 | { PWMwidth=RS232output*PERIOD*0.01;
| 207 | Timer_T1PWA(PWMwidth); // PWM with value PWMwidth
| 208 | Port_WriteBit(16,1);
| 209 | }
| 210 | else
| 211 | Port_WriteBit(16,0);
| 212 |
| 213 | if(flagCTRL) // Control switch on/off
| 214 | { PWMwidth=PERIOD*pwm_output; // PWMwidth = hole periode*PIDoutput[0.00-1.00]
| 215 | Timer_T1PWA(PWMwidth); // PWM with value PIDoutput
| 216 | Port_WriteBit(17,1);
| 217 | }
| 218 | else
| 219 | Port_WriteBit(17,0);
| 220 |
| 221 | if(!flagCTRL & !flagPWM) // PWM value --> zero
| 222 | {
| 223 | Timer_T1PWA(1); // (0 not allowed!)
| 224 | }
| 225 |
| 226 | AbsDelay(10);
| 227 | }
| 228 | }
|
Sollte jemand die Lösung finden, würd ich vor Freude in die Luft
springen!!!!!
gruss Daniel
Schwer zu sagen, da ich das Programm etwas, naja, unübersichtlich finde.
Insofern kann es gut sein, daß ich jetzt falsche spekuliere, weil ich
es einfach auch nach 15 min lesen nicht so ganz verstehe.
---
Zumindest ein mittleres Problem sehe ich darin, daß in main()
wohl die PID-Regelung gemacht wird; die ist zeitabhängig:
ob ich die Schleife alle 10 msec oder alle 10 min durchlaufe, ist
relevant für das Zeitverhalten. Insbesondere der I-Anteil
muß ja die Abweichung mit der verstrichenen Zeit multiplizieren.
Ich kann aber kein festes Zeitraster erkennen, in dem die
Schleife durchlaufen wird.
Mehr oder weniger Debugausgaben können also die Regelung
beeinflussen.
Zudem wird ja auch die Regelung angehalten, bis etwas über RS232 kommt.
Soll das so sein?
---
Daniel Mayr schrieb:
> Für die
> manuelle Steuerung setzen wir eine globale auf eins, dass gleiche machen
> wir für die Regelung.
flagPWM und flagCTRL?
Das Programm wäre lesbarer, wenn man am Namen erkennen würde,
welcher Wert welche Bedeutung hat.
Daß das eine irgendwas mit PWM zu tun hat, sieht man, aber wie
wirkt sich welcher Wert aus?
Und was flagCTRL bewirkt, kann ich am Namen auch nicht erkennen.
Das if-Gewurschtel am Ende ist auch nicht gerade durchsichtig.
---
In adc2angel() wird wohl ein ADC-Wert in einen Engel verwandelt;
mit ein paar else könnte man das entlasten - es wird ja immer nur
einer der Zweige genutzt.
---
Daniel Mayr schrieb:
> Die Funktion RS232 liest die Kommandos aus
RS232 ist zu 0 #definiert.
---
Daniel Mayr schrieb:
> Nach 3h vergeblichen Versuchen...
Dann wären 10 min für eine vernünftige Beschreibung und sinnvolle
Kommentare auch noch drin gewesen...
:-)
---
Ich sehe nicht, wo pwm() aufgerufen wird.
---
Was machen Funktionen wie Timer_T1PWA, Timer_T1PWM ?
---
Solche Kommentare sind zwecklos:
Port_DataDirBit(16,1); //Define PortD.0 as output
Port_DataDirBit(17,1); //Define PortD.1 as output
Interessant wäre ein dürrer Satz dazu, was D.0 und D.1 bewirken
sollen.
Oder rauswerfen, wenn man es hier nicht braucht.
---
0 scheint nicht zu gehen, warum auch immer: 1 | Timer_T1PWM(PERIOD,1,PS_1); //Define PWM with duration of 1 (0 not allowed!!)
|
Ist sicher, daß hier dann auch keine 0 gesetzt wird? 1 | PWMwidth=PERIOD*pwm_output; // PWMwidth = hole periode*PIDoutput[0.00-1.00]
| 2 | //Timer_T1PWA(PWMwidth); // PWM with value PIDoutput
| 3 | Timer_T1PWM(PERIOD,PWMwidth,PS_1);
|
---
Daniel Mayr schrieb:
> Und wie gesagt, der PID Regler an sich funktioniert auch, allerdings nur
> wenn diese Debug Messages mit drin sind........
"funktionieren" und "nicht funktionieren" heißt für Nichthellseher
wie mich was?
-------------
Das ist das, was mir beim Lesen so auffiel.
Aber wie gesagt finde ich es nicht besonders deutlich programmiert.
Es werden also schon noch ein paar Böcke drin sein.
Hi Klaus,
danke für den "Anschiss". Wir haben leider nicht so viel Erfahrung mit
Microcontroller geschichten und sind von unserer Uni iwie ins kalte
Wasser geschmissen worden.
Mein syrischer Kollege hat den PID-Regler gemacht, und wir haben jetzt
das Programm nochmal kommentiert und unwichtige Stellen draußen
gelassen.
Das Problem ist immer noch mit den Debug messages: 1 | //////////////////////////////////////////////////////////////////
| 2 | Msg_WriteChar(CR); //Carry return message
| 3 | Msg_WriteFloat(err_acc); //Display of err_acc //
| 4 | // OHNE DIESE DEBUG MESSAGES FUNKTIONIERTS NICHT!!!!
| 5 | ///////////////////////////////////////////////////////////////////
|
Beschreibung im Manual siehe Anhang....
Hier noch der PID-Regler als C-code: 1 | #define CR 0x0D
| 2 |
| 3 | int period; //period of the PWM
| 4 |
| 5 | float PID_output,pwm_output; //output value of controller
| 6 | word ADC_Value; //ADC value
| 7 | word ang_ref; //Reference Angel value
| 8 | float ang_msurd,err,ang_msurd_prev,err_acc,err_diff; //Controller variables
| 9 | float Kp; //Propotional Coefficient
| 10 | float Ki; //Integrater Coefficient
| 11 | float Kd; //Diffirential Coefficient
| 12 | void pwm(float PID_output){ //function pwm //////////////////////
| 13 | //help variables///////////////////////////7
| 14 | int PWM_Counter_A; //pulswidth of the PWM in a promille scale
| 15 | //////////////////
| 16 | period=492;
| 17 | PWM_Counter_A=period*PID_output;
| 18 |
| 19 | Timer_T1PWM(period,PWM_Counter_A,PS_1);
| 20 | }
| 21 | //////////////////////////////////////////////////////////////////
| 22 | float adc2angle(word ADC_Value)
| 23 | {
| 24 | float ang_tmp;
| 25 | if(ADC_Value>425)
| 26 | {
| 27 | ang_tmp=-0.008*ADC_Value-4.6; //1st interval equation
| 28 | }
| 29 | if(ADC_Value<=425 && ADC_Value>300)
| 30 | {
| 31 | ang_tmp=-0.016*ADC_Value-1.2; //2nd interval equation
| 32 | }
| 33 | if(ADC_Value<=300 && ADC_Value>222)
| 34 | {
| 35 | ang_tmp=-0.025*ADC_Value+1.692; //3rd interval equation
| 36 | }
| 37 | if(ADC_Value<=222 && ADC_Value>170)
| 38 | {
| 39 | ang_tmp=-0.038*ADC_Value+4.538; //4th interval equation
| 40 | }
| 41 | if(ADC_Value<=170 && ADC_Value>130)
| 42 | {
| 43 | ang_tmp=-0.05*ADC_Value+6.5; //5th interval equation
| 44 | }
| 45 | if(ADC_Value<=130 && ADC_Value>105)
| 46 | {
| 47 | ang_tmp=-0.08*ADC_Value+10.4; //6th interval equation
| 48 | }
| 49 | if(ADC_Value<=105 && ADC_Value>86)
| 50 | {
| 51 | ang_tmp=-0.105*ADC_Value+13.05; //7th interval equation
| 52 | }
| 53 | if(ADC_Value<=86 && ADC_Value>73)
| 54 | {
| 55 | ang_tmp=-0.153*ADC_Value+17.23; //8th interval equation
| 56 | }
| 57 | if(ADC_Value<=73 && ADC_Value>59)
| 58 | {
| 59 | ang_tmp=-0.142*ADC_Value+16.42; //9th interval equation
| 60 | }
| 61 | if(ADC_Value<=59 && ADC_Value>52)
| 62 | {
| 63 | ang_tmp=-0.285*ADC_Value+24.85; //10th interval equation
| 64 | }
| 65 | if(ADC_Value<=52 && ADC_Value>46)
| 66 | {
| 67 | ang_tmp=-0.333*ADC_Value+27.33; //11th interval equation
| 68 | }
| 69 | if(ADC_Value<=46 && ADC_Value>42)
| 70 | {
| 71 | ang_tmp=-0.5*ADC_Value+35; //12th interval equation
| 72 | }
| 73 | if(ADC_Value<=42)
| 74 | {
| 75 | ang_tmp=-1.0*ADC_Value+56; //13th interval equation
| 76 | }
| 77 | return ang_tmp;
| 78 |
| 79 |
| 80 | }
| 81 |
| 82 | /////////////main//////////////////////////////
| 83 | void main(void)
| 84 | {
| 85 | PID_output=0.0; //Initialization
| 86 | ang_ref=0.0; //Assigning Reference angel value
| 87 | err_acc=0; //Initialization of error value
| 88 | ang_msurd_prev=ang_ref; //Initialization of previous error value
| 89 | ADC_Set(ADC_VREF_VCC, ADC0); //Setting ADC Configurations
| 90 | //Kp=0.01;
| 91 | //Ki=0.005;
| 92 | //Kd=0.5;
| 93 | //Zigler Nicolas method
| 94 | /*Kp=0.0360;
| 95 | Ki=0.0411;
| 96 | Kd=0.0079;*/
| 97 | Kp=0.01; //Propotional Coefficient value
| 98 | Ki=0.005; //Integrater Coefficient value
| 99 | Kd=0.5; ////Diffirential Coefficient value
| 100 |
| 101 | while (1)
| 102 | {
| 103 | ADC_Value=ADC_Read(); //Reading ADC value
| 104 | ang_msurd=adc2angle(ADC_Value); //Calculating Angel value
| 105 | if(ang_msurd>15) ang_msurd=15; //Limiting Angel value
| 106 | if(ang_msurd<-10) ang_msurd=-10;
| 107 | //Msg_WriteHex(ADC_Value);
| 108 | err=ang_ref+ang_msurd; //Computing the error
| 109 | err_acc=err_acc+err; //Accumlating the error
| 110 | err_diff=ang_msurd-ang_msurd_prev; //computing the diffirential error
| 111 | if(err_acc>20) err_acc= 20.0; //Limitting Accumulation error
| 112 | if(err_acc<-20) err_acc= -20.0;
| 113 | PID_output=Kp*err+Ki*err_acc+Kd*err_diff; //PID equation
| 114 | pwm_output=(PID_output+0.5); //Nolmalizing PID Output
| 115 | //////////////////////////////////////////////////////////////////
| 116 | Msg_WriteChar(CR); //Carry return message
| 117 | Msg_WriteFloat(err_acc); //Display of err_acc
| 118 | //// OHNE DIESE DEBUG MESSAGES FUNKTIONIERTS NICHT!!!!
| 119 | ///////////////////////////////////////////////////////////////////
| 120 | if(pwm_output<0.05) pwm_output=0.05; //Limitting PWM Output
| 121 | if(pwm_output>0.95) pwm_output=0.95;
| 122 |
| 123 | pwm(pwm_output); //Transfering PWM to Motor
| 124 | ang_msurd_prev=ang_msurd; //Assigning current angle value to the previous angel value
| 125 | AbsDelay(10); //10 ms Interval Time
| 126 | }
| 127 | }
|
Zur Beschreibung des Problems:
Wenn wir den Regler aus dem Compiler starten, dann funktioniert er, aber
nur wenn die Debug messages drin sind.
Wenn wir nun die REset Taste drücken, dann funktioniert der Regler nicht
(was ich komisch finde, da bei REset das Programm doch wieder bei void
main (void) beginnt.
Danke schon im Vorraus für eure Hilfe!!
Gruss Luiz
Klingt für mich alles noch dem Problem, welches Klaus schon angesprochen
hat: Ihr habt im Regler keinen definierten Zeittakt. Die Durchlaufzeit
durch 1 Regelschleife ist mehr oder weniger von irgendwelchen
Umgebungsbedingungen abhängig. Und wenn ihr die Umgebung entsprechend
langsam genug macht, dann kommen die Regelparameter in einen Bereich in
dem der Regler dann auch tatsächlich regelt. Lässt ihr aber alles mit
'Full-Speed' laufen, funktionieren diese Parameter nicht mehr.
Den ganzen PID Regler in eine Timer ISR verschieben und so für einen
regelmässigen immer gleichen Zeittakt sorgen. Die Regelparameter müssen
dann natürlich wieder neu abgeglichen werden.
Hallo Karl Heinz,
danke für den Tip. Haben den Regler jetzt in eine ISR geschoben und
jetzt funktioniert die Sache (fast) perfekt.
Unser Projekt ist zwar jetzt schon abgegeben, aber eine weitere Frage zu
unserer ISR:
1. Wir haben die Zeitdauer dieser ISR gemessen, und kommen auf knappe
2ms.
(Einen Ausgang auf High geschaltet, wenn die ISR läuft )
ist das nicht ein bisschen lang?
Wir haben zwei Programme, eins, in dem nur der PID regler läuft ohne
Schnick Schnack. Der Sollwert wird fast perfekt erreicht und gehalten.
Das andere Programm beinhaltet eine interrupt getriebene Auslesung der
seriellen Schnittstelle, um zwischen Regelbetrieb und Manueller
Ansteuerung zu unterscheiden. In jedem Durchlauf der while schleife wird
die serielle SS gelesen... wenn keine Bytes im Puffer sind, kehrt die
Funktion direkt wieder aus dem interrupt zurück.
Hier jedoch mussten wir für den Sollwert 5 Grad mehr einstellen, um auf
0 Grad sollwert zu regeln.
Liegt das an mehr Rechenaufwand wg. der seriellen SS?
Wahrscheinlich könnt ihr das ohne programm nicht sagen, das programm ist
glaub ich zu groß, ums hier reinzustellen. Hab auch keine Ahnung, was
jetzt wirklich diesen kleinen Schönheitsfehler ausmacht, deswegen müsst
ich alles reinstellen
Gruss und danke für die super tipps!
daniel
Der Interrupt darf auch 10 Sekunden dauern wenn dieser nur alle 10
Minuten auftritt und keine andere Funktionalität eine Unterbrechnung von
10 Sek nicht Tolerieren kann.
Wegen Serielle Schnittstelle: Die würde ich nicht im Interrupt auslesen,
sondern in der Hauptschleife, weil sonst je nachdem (Daten da/nicht da)
das Zeitverhalten möglicherweise negativ beeinflusst wird.
@auszug_manual.jpg Sowas nächstmal besser als PNG jpeg eignet sich
nicht wirklich für Text.
Hi Läubi,
danke für deinen Antwort.
Ich glaube jedoch, dass ich den interrupt Betrieb brauch, da ich in
Matlab eine GUI geschrieben habe, und ich ja nicht beeinflussen kann,
wann welcher Schalter gedrückt wird... Deswegen muss ich immer lesen,
wenn nix da is, kehr ich wieder zurück.
im anhängsel noch der auszug aus dem Manual......für entweder interrupt
betrieb oder ohne.
Aber das auslesen oder besser gesagt hören auf die serielle SS kann doch
nicht so zeitkritisch sein, dass mein Regler im Interruptbetrieb (
Schleife alle 10 ms beeinflusst wird).
Gruss daniel
Für die Serielle selbst wieder einen Interrupt Betrieb zu benutzen ist
schon ok.
Was gemeint ist:
Du sollst zb nicht eine Serielle AUsgabe aus einer ISR heraus machen.
Deine Berechnung des PID Reglers in der ISR soll tatsächlich nur das
machen: einen Durchgang durch die Reglergleichungen und den Ausgang
ansteuern. Mehr nicht.
Dann dauert deine ISR auch keine 2ms mehr.
Grundsätzlich: In einer ISR willst du
* nicht warten
* nichts machen, was länger dauert
* nur das Allernotwendigste durchführen
Das heißt jetzt nicht, das man in einer ISR gar nichts tun darf, sondern
dass man ein wenig überlegen soll, was man alles in eine ISR steckt und
was nicht.
Grundsätzlich hätte man gerne, dass man aus einer ISR möglichst schnell
seine Arbeit erledigt und wieder aus der ISR rauskommt. Eine Ausgabe
über eine serielle Schnittstelle ist da kontraproduktiv.
Das ist böse:
Daniel Mayr schrieb:
> // Test-Message:
> char rmsg1[5]; // Message Command
>
> ...
>
> rmsg1="C-Control PRO ready for receiving\r\n";
>
> for(i=0;i<2;i++)
> Serial_WriteText(RS232,rmsg1); // Serielle Schnittstelle Test senden
>
>
>
Vlad Tepesch schrieb:
> Das ist böse:
>
> Daniel Mayr schrieb:
>> // Test-Message:
>> char rmsg1[5]; // Message Command
>>
>> ...
>>
>> rmsg1="C-Control PRO ready for receiving\r\n";
>>
>> for(i=0;i<2;i++)
>> Serial_WriteText(RS232,rmsg1); // Serielle Schnittstelle Test senden
>>
>>
>>
Ja, dass ist schon länger behoben..... unser feld hat ist jetzt char
rmsg1[50].
Aber das Programm ging trotzdem!!!,
Daniel Mayr schrieb:
> unser feld hat ist jetzt char rmsg1[50].
> Aber das Programm ging trotzdem!!!,
Rubrik "spekulatives Programmieren", soweit es nur um die Feldlänge
geht.
So wie es da steht, ist es aber nicht mal kompilierbar.
Daniel Mayr schrieb:
> Aber das Programm ging trotzdem!!!,
Falsch.
Es sah nur so aus als ob.
Nur weil ein Fehler nicht unmittelbar Unheil anrichtet, heißt das noch
lange nicht, dass es in Ordnung ist.
aha,
und warum ist das nicht kompilierbar??
mein Compiler meckert nicht bei 1 | char rmsg1[50]; // Message Command
|
aber dann hoffentlich bei: 1 | rmsg1="C-Control PRO ready for receiving\r\n";
|
Grund: ein Feld ist ein konstanter Zeiger auf die Elemente, und
kann durch eine Zuweisung nicht mehr geändert werden.
Einen String ins Feld bekommt man entweder durch Initialisierung,
oder strcpy().
Hallo Klaus,
Ich möcht hier nicht mein Kopf aus der Schlinge ziehn, jedoch ein paar
Anmerkungen.
Meine Unerfahrenheit at mich ins Manual schauen lassen und den
angehängten Ausschnitt hab ich somit angewendet.
Die Sache mit String copy steht schon drin.... aber auch das meine
Deklaration nicht falsch ist.
DIe Programmiersprache CompactC hat vllt etwas damit zu tun?!.
Gruss
p.s. der verwendete string ist constant wird nicht geändert, und nur
einmal verwendet.
Daniel Mayr schrieb:
> Meine Unerfahrenheit at mich ins Manual schauen lassen und den
> angehängten Ausschnitt hab ich somit angewendet.
>
> Die Sache mit String copy steht schon drin.... aber auch das meine
> Deklaration nicht falsch ist.
> DIe Programmiersprache CompactC hat vllt etwas damit zu tun?!.
Wenn deine Anleitung stimmt, dann ist das kein Standard-C.
Weder nach C89 noch nach C99 noch nach irgendwelchen C++ ist das
erlaubt.
Da du den String ja nur einmal setzen willst, gibt es eine kleine
Änderung, die wieder standardkonform ist, nämlich eine saubere
Initialisierung: 1 | char rmsg1[50]="C-Control PRO ready for receiving\r\n"; // Message Command
|
So ist es mit jedem Compiler richtig.
>
> Wenn deine Anleitung stimmt, dann ist das kein Standard-C.
> Weder nach C89 noch nach C99 noch nach irgendwelchen C++ ist das
> erlaubt.
wie gesagt CompactC ( siehe Projectboard MEGA32 von Conrad)
>
> Da du den String ja nur einmal setzen willst, gibt es eine kleine
> Änderung, die wieder standardkonform ist, nämlich eine saubere
> Initialisierung:
> 1 | > char rmsg1[50]="C-Control PRO ready for receiving\r\n"; // Message
| 2 | >
|
> So ist es mit jedem Compiler richtig.
Und genau das unterstützt der Compiler nicht.......habs gerade
durchlaufen lassen... es geht wirklich nur der eine Weg...
> 1 | > char rmsg1[50];
| 2 | rmsg="C-Control PRO ready for receiving\r\n"; // Message
| 3 |
| 4 | >
|
Der Compiler übrigens heisst "C Control Pro IDE".
Das hat mit C wohl schon noch Ähnlichkeit, aber nicht mehr 100%....
Was an dem Compiler auch komisch ist, dass ich im Ausgabefenster nur
globale Variablen anschauen kann...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|