Guten Abend!
Ich hoffe, daß einer von euch mir helfen kann. Ich dachte ja, daß ich
die Anwendung von "volatile" verstanden hätte, aber das ist wohl nicht
der Fall :( .
Ich habe hier ein Programm für eine Stromregelung. Das läuft auf einem
Attiny45. Ich gebe eine PWM auf einen Step-Up-Wandler und beim Overflow
vom PWM-Timer startet der ADC.
Abgetastet wird zum einen der Strom, und zum anderen ein Poti
(Strom-Sollwert, immer abwechselnd).
Innerhalb der ISR rufe ich erst eine Routine zum Filtern der Messwerte
auf und dann den Regler.
Ich hab fast alle Variablen (erstmal) global angelegt, also so Dinge wie
Stromsoll- und istwert, Momentanwerte, auch die beiden Arrays für die
gefilterten Werte...
Jetzt kommt das Putzige: die lokalen Variablen, in meiner Filterroutine
muß ich volatile machen, damit es funktioniert! Und ich begreife
wirklich nicht, warum!
Die ISR sieht so aus:
Joachim B. schrieb:> Jetzt kommt das Putzige: die lokalen Variablen, in meiner Filterroutine> muß ich volatile machen, damit es funktioniert!
Was heißt "damit es funktioniert" oder in welcher Form äußert sich das
Nichtfunktionieren?
Und wie sind die globalen Variablen definiert? Aus dem Ausschnitt lässt
sich nicht viel folgern.
volatile in lokalen variablen? Ne, DAS ist nicht üblich und DAS ist auch
nicht dein problem / Fehler.
Les dir mal durch, wie lange lokale Variablen existieren. Sollte
eigentlich in jedem C-Buch das etwas von sich hält in den ersten
Kapiteln zu finden sein. Die kurze Antwort, bis zu der schließenden
geschwellten Klammer. D.h. deine Variablen verlieren am Ende der
Funktion ihre Werte und beim nächsten Eintritt haben sie wieder die
Default-Werte. Und dann funzt dein Program natürlich nicht.
Was du suchst ist das Stichwort "static". Damit veränderst du den
Gültigkeitbereich von Variablen (bzw. wenn es sich um globale Variable
handelt, ihre Sichtbarkeiten). Am Besten liest du das aber auch in einem
C-Buch nach (ist schon spät und ich bin müde).
gruß
Mobius
Hi und danke erstmal für die Antworten!
Andreas B. schrieb:> Was heißt "damit es funktioniert" oder in welcher Form äußert sich das> Nichtfunktionieren?
Stimmt, etwas genauer hätte ich das Problem beschreiben können :) .
Hatte nur Angst euch da evtl. auf eine falsche Fährte (?) zu locken...
Mit "damit es funktioniert" meine ich folgendes: wenn ich die
Optimierung ausschalte dann funktioniert die Regelung ohne Probleme
(stabiler, als ich dachte :) ). Das heißt der Soll-Istwert-Vergleich
generiert das PWM-Tastverhältnis und die Istwerte von Strom und vom Poti
werden in das dafür vorgesehene Array gespeichert. Zumindest nehme ich
das mal recht stark an, dann "es funktioniert" ja.
Wenn ich nun die Optimierung einschalte passiert bei der PWM nichts
sinnvolles mehr. Da kann ich am Poti drehen, bis ich schwarz werden, die
PWM ist entweder bei 0% oder bei 50% (Begrenzung per SW). Da die
Begrenzung auch funktioniert scheint die Routine für die Regelung auch
halbwegs korrekt durchlaufen zu werden (hier findet ja die Begrenzung
statt). So kam ich darauf, daß der Fehler wohl bei der Filterung der
Werte drinsteckt... Und dann hab ich irgendwann das mit den "lokalen
volatiles" gemacht...
Laszlo H. schrieb:> Les dir mal durch, wie lange lokale Variablen existieren. Sollte> eigentlich in jedem C-Buch das etwas von sich hält in den ersten> Kapiteln zu finden sein. Die kurze Antwort, bis zu der schließenden> geschwellten Klammer.
Danke für den Hinweis, ich bin ja bei Weitem kein Profi, aber das war
wirklich schon bekannt :) .
Die Sache ist aber die, daß ich die lokalen Variablen in der
Filter-Funktion ja für nichts anderes brauche. Meine Arrays für die
Ist-Werte sind global und die minimalen und maximalen Werte innerhalb
des Arrays will ich mir doch gar nicht dauerhaft merken. Und da hilft
mir auch kein "static" weiter. Schließlich sind die Extremwerte ja nach
jeder neuen Messung anders.
> D.h. deine Variablen verlieren am Ende der> Funktion ihre Werte und beim nächsten Eintritt haben sie wieder die> Default-Werte. Und dann funzt dein Program natürlich nicht.
s.o. ... genau das brauche ich aber. Jedes mal, wenn einer neuer
Messwert vorliegt soll ja erneut nach den Extremwerten gesucht werden.
Da macht das Laden mit den Default-Werten (1 und 0xffff) schon Sinn.
"filterwert" ist oben noch mit "2" angelegt. Das hab ich nur zum
ausprobieren gemacht, weil ich dachte, daß das dann nicht so strickt
wegoptimiert wird, wie mit "0". Brachte aber nix...
Oliver schrieb:> Ich vermute, dass du die entscheidenden globalen Variablen nicht> volatile deklariert hast. Welche das sind, musst du selber rausfinden.
Hab ich ja versucht, aber da kam ich nicht weiter. Ich habe nach und
nach JEDE glaobale Variable als volatile deklariert, aber das bracuhte
alles nichts! darum schreibe ich ja hier, weil ich selbst nicht
weiterkam. Alle Variablen sind global (außer die in der Regelung und in
der Filterung).
OHNE Optimierung funktioniert die Regelung wie erwartet auch OHNE
volatile bei den Filter-Variablen.
MIT Optimierung hilft kein "volatilisieren" der globalen Variablen, nur
der lokalen in der Filterung...
> Ohne kompletten Sourcecode ist das schwierig.
Ich bereite den mal so auf, daß ihr was damit anfangen könnt :)
Freue mich über noch mehr Vorschläge!
Gruß
naja, wer lokale Variablen als "volatile" declariert, der hat leider
"volatile" und das Problem, das damit gelöst werden soll nicht
verstanden.
"volatile" bedeutet: "He Compiler, diese Variable kann sich ändern, ohne
daß Du bei der Analyse sagen könntest wo". Das passiert z.B. wenn ein
Interrupt eine globale Variable andert. Eine parallel laufende
Hauptschleife darf diese Variable dann nicht in ein Register plazieren,
sonst sieht sie die Änderung durch die ISR nämlich nicht.
Weiter Vorschläge erst bei komplettem SourceCode, den die PWM wird ja
wohl von "stromregler()" bestimmt, den wir noch gar nicht kennen.
Vielleicht mal ""stromregler() { return FIXED_DEBUG_WERT; }"
Oder aber: .lss mit/ohne Optimierung vergleichen.
Oh, sorry, stimmt! Stromregler() hab ich vergessen, das sollte
eigentlich mit rein...
Im Anhang mal die vollständige Datei. Ich finds echt nett, daß sich
einige schon Gedanken gemacht haben. Wenn ich selbst ne Lösung hätte
wäre ich ja nicht hier... :( .
Wie schon gesagt, ich hatte nach und nach jede einzelne globale Variable
mal volatilisiert, auch mal alle auf einmal. Das halb aber nichts... :(
.
JW schrieb:> naja, wer lokale Variablen als "volatile" declariert, der hat leider> "volatile" und das Problem, das damit gelöst werden soll nicht> verstanden.
naja, das hab ich ja nicht von vern herein so gemacht. Ich hatte an
anderen Stellen auch nachgelesen, wo z.B. stand, daß lokale Variablen eh
nicht volatilisiert werden müßten. Ist ja nicht so, daß ich da nicht
schon selbst versucht habe hiner zu kommen ;) ...
Mir kommt das auch bescheuert vor, aber das war eben das, was half! Da
mein Hauptprogramm ja nichts tut, außer auf den ADC-Interrupt zu warten,
hatte ich ursprünglich gar keine volatile-Variable, weil ja
schließlich kein Variable an anderer Stelle als im Interrupt benutzt
wird.
Ich hätte ja gefühlsmäßig alle Variablen, die in der ISR verändert
werden, volatile gemacht. Aber ich sagte ja schon... das brachte
nichts...
Danke nochmal und Gruß!
Ähm... der Timer für die PWM läuft mit Systemtakt -> 16 MHz. Da ich mit
symmetrischer 8-Bit-PWM arbeite würde also der Overflow-Interrupt alle
32 µs (31,2 kHz) auftreten. So schnell ist aber der ADC und die ISR
nicht. Der ADC läuft mit 250 kHz, er würde also theoretisch ca. 19 kSps
schaffen. Der ADC bekäme also nur ungefähr jeder zweiten Timer-Overflow
mit.
Aber was spielt das für eine Rolle? Die Interrupts können sich doch gar
nicht in die Quere kommen. Ich benutze ja nur einen einzigen: den des
ADC, dessen Wandlungen durch den Timer-Overflow getriggert werden. Eine
erneute Triggerung ist ja erst möglich, wenn ich das Flag, was den
Interrupt ausgelöst hat, resette...
Funktioniert in der optimierten Version überhaupt irgendwas oder geht
der gleich ab in den Nirvana? Du hast ja einen Testpin in der ISR, der
müsste das anzeigen.
Ich würde raten, übersetzbaren Code reinzustellen. Damit man das durch
den Compiler jagen kann ohne selber rumbasteln zu müssen. Und bei der
Gelegenheit verrätst du und dann hoffentlich auch mal den Controller und
welche Version des Compilers du verwendest.
Hi und danke nochmal für die bisherigen Bemühungen!
Also ich hab mir nochmal ein paar Gedanken gemacht und auch einen
Verdacht. Das werde ich aber nochmal selbst auseinandernehmen und
ausprobieren. Wenn es das dann war, dann werd ich den kompletten Code
nochmal posten. Hab ja eigentlich nix zu verbergen... Könnte ja
vielleicht einer was mit anfangen ;) .
ach ja,
@ A. K.
den Controllertyp hab ich doch im ersten Post schon preisgegeben :) ...
Gruß!