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
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?
//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:
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.
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
charrmsg1[50]="C-Control PRO ready for receiving\r\n";// Message Command
>> 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
>charrmsg1[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
>charrmsg1[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...