Mein Projekt befasst sich mit der Regelung der Temperatur mittels
Thermostatventil.
Im Prinzip läuft die Regelung als PI-Regler schon nach meinen
Vorstellungen.
Ein Problem besteht allerdings darin, dass sich das Programm aufhängt,
wenn das Ventil bis zur Endstellung fahren will, aber der Anschlag
vorzeitig ereicht wird.
Verantwortlich mache ich die while schleife in der Funktion
void ventil_schliessen_regler(void)
{
ZU=1; //zähler zählt herunter
while(hub >(ventilstellung_alt-umdrehung_zu ))
P3OUT &=~BIT0; // ZU-fahren
P3OUT |=BIT0; // ZU-fahren HALT
ZU=0;
Zur Erklärung: Der hub entspricht der Anzahl der Umdrehungen eines
Zahnrades des Getriebes.
Beim Schließen wird herunter gezählt.
Alle 8s wird die Hubstellung (ventilstellung_alt) abgefragt und über die
Reglergleichung die Anzahl der Umdrehungen (umdrehung_zu) berechnet, die
notwendig sind, um die neue Hubstellung anzufahren. Bisher alles gut.
Das Problem des Aufhängens tritt m. E. dann auf, wenn der Lauf durch
Anschlag am Hubende nicht bis zum Ende erfolgen kann.
Gibt es eine Möglichkeit, die Schleife vorzeitig zu verlassen, obwohl
die errechnete Hubverstellung wegen Anschlag nicht erreichbar ist und
deshalb die while-schleife nicht beendet wird.
Versuche mit Strommessungen waren bei mir (programmiertechnisch) nicht
erfolgreich.
Aber vielleicht hat jemand eine Idee, wie das Aufhängen vermieden werden
kann.
fragt ein Programmierlaie
wolle g. schrieb:> Aber vielleicht hat jemand eine Idee, wie das Aufhängen vermieden werden> kann.
Eine while-Schleife wird genau dann unterbrochen, wenn die Bedingung
nicht mehr erfüllt ist. Also schreibe die Abbruchbedingung mit rein.
Mit dem Schlüsselwort "break" kannst du die Schleife vorzeitig
verlassen. Mit "continue" kannst du den aktuellen Durchlauf abbrechen
und mit dem nächsten (von oben an) fortfahren.
Wolfgang schrieb:> Eine while-Schleife wird genau dann unterbrochen, wenn die Bedingung> nicht mehr erfüllt ist. Also schreibe die Abbruchbedingung mit rein.
Quatsch. Das sind Weicheierschleifen.
Männerschleifen werden SO geschrieben:
Prozessor Dokter Schmunz schrieb:> Männerschleifen werden SO geschrieben:While(1) {> if(Abbruchbedingung)> {break;}> }
Schon wieder so ein C-Konstrukt, das irgendwo mitten aus einem Block
rausspringt ...
Wolfgang schrieb:> Schon wieder so ein C-Konstrukt, das irgendwo mitten aus einem Block> rausspringt ...
Hab doch geschrieben, nichts für Weicheier. Also bleib devot und lies,
was wir Männer schreiben.
... schrieb:> Was denkst Du, was hier passiert?
Ich weiß zwar nicht, was Du damit meinst, aber solange der Hubanschlag
nicht erreicht ist, wird die berechnete Hubstellung angefahren.
... schrieb:> hub >(ventilstellung_alt-umdrehung_zu
Woher kommen die Variablen?
Prozessor Dokter Schmunz schrieb:> Ganz einfach: Hier gibt es Antworter, die wissen noch weniger als der> Frager ;)
Genau ;)
Im Moment kenne ich nur den Codeschnipsel.
Und wenn der TO wirklich in einer Schleife immer wieder ein Bit löscht,
welches schon längst gelöscht ist, denke ich mir, dass es im restlichen
Programm ähnlich ausieht.
... schrieb:> Und wenn der TO wirklich in einer Schleife immer wieder ein Bit löscht,> welches schon längst gelöscht ist, denke ich mir
Manche Ecken bestehen nur aus Fett. Aber nur Joseph Beuys konnte damit
Geld machen. Es liegt also nicht am Fett, sondern am User.
Anderer Vorschlag, frei nach Beuys:
1
while(1){
2
if(Abbruchbedingung)
3
{digitalWrite(PIN,1);}// PIN ist ohne Widerstand mit Masse verbunden
4
}
Wenn die Abbruchbedingung erfüllt ist, wird ein Kurzschluss erzeugt. Der
Prozessor raucht ab, und die Schleife gilt damit als verlassen. In
meiner Funktion als Prozessor Dokter Schmunz darf ich das zwar nicht
schreiben, aber Beuys, wäre er Programmierer, würde das tun. Kurz darauf
würden das vermutlich alle tun.
... schrieb:> Im Moment kenne ich nur den Codeschnipsel.
deshalb als Anhang mal das gesamte Hauptprogramm, auch wenn es
vielleicht nicht allen Anforderungen entsprechen sollte.
Es enthält zusammen mit *.h Dateien u.a.:
Aufzeichnung von Daten auf SD-Karte
Uhrzeit
Temperaturmessung
Anzeige auf Flüssigkristallanzeige
Vielleicht könnte jemand die Abruchbedingungen an der richtigen Stelle
einfügen.
mit break
oder if (ADW_P6_3 > 24)... //steht für Stromstärke am Anschlag ZU
hatte ich es versucht --> Programm reagierte nicht mehr
deshalb mein Hilferuf
wolle g. schrieb:> Vielleicht könnte jemand die Abruchbedingungen an der richtigen Stelle> einfügen.
Bei solch chaotischer Tabulierung ..... nein danke.
wolle g. schrieb:> deshalb als Anhang mal das gesamte Hauptprogramm,
1
...
2
voidpause(void);
3
voidpause1(void);
4
voidpause2(void);
5
...
Du wiederholst oft aehnlichen Code. Statt 3 Funktionen kann du eine
verwenden, die Wartezeit uebergibst du als Parameter. Damit wird der
Code viel kuerzer und lesbarer/uebersichtlicher.
leo
Tim T. schrieb:> Wo kommt eigentlich hub her? Sehe dafür keine Deklaration... Und> wenn> sollte da ein volatile bei stehen.
Deklaration ist in DS10-g0107-LMK62-SD.h als volatile int enthalten
Deinen Vorschlag habe ich wie folgt eingebaut:
void ventil_schliessen_regler(void)
{
ZU=1; //zähler zählt herunter
while(hub >(ventilstellung_alt-umdrehung_zu ))
P3OUT &=~BIT0; // ZU-fahren
if ( ADW_P6_3 > 24) break; //hier Zeile 248
P3OUT |=BIT0; // ZU-fahren HALT
ZU=0;
}
Fehlermeldung: DS10-g0122-PID.c:248: break statement not within loop or
switch
>> KLAMMERN!
Woher ADW_P6_3 den AKTUELLEN Wert hat, steht dann auch wieder in den
Sternen. Wie kommt man eigentlich als so minderbegabt auf die Idee so
ein Projekt zu machen? Dir fehlt es ja anscheinend an allem...
Tim T. schrieb:> als so minderbegabt
oder einfach nur talentfrei! ... ist hier doch die mehrheit.
das du und andere sich hier reinhängen wundert mich.
mt
Apollo M. schrieb:> Tim T. schrieb:>> als so minderbegabt>> oder einfach nur talentfrei! ... ist hier doch die mehrheit.> das du und andere sich hier reinhängen wundert mich.>>> mt
Ja, war wiedermal doof, dachte es wäre schon auf der Zielgeraden aber in
Wirklichkeit gehts immer weiter in den Abgrund...
Freitag abends schaue ich die Heute-Show.
Und wenn ich Montag morgens etwas zum Lachen brauche, dann kann ich
diesen Thread nehmen. So fängt sich Woche fröhlich an.
Die Karnvevalszeit ist schon schön, selbst hier setzen sich die Leute
Pappnasen auf.
> fragt ein Programmierlaie
Ging ja wieder heiss her hier, gestern abend.
Dafür, dass er 'n Laie ist auf dem Gebiet, geht das doch. Etwas holperig
und ungelenk vielleicht.
Aber trotzdem muss man hier nicht soo arrogant reagieren. Schade...
Wahrscheinlich war ich diesmal zur falschen Zeit am falschen Ort, denn
normalerweise wird hier im Forum zumeist konkret auf Fragen
eingegangen.
Unabhängig von seinen "sinnlosen Kommentaren" führten die
Programmschnipsel von Tim T. letztendlich zum Erfolg.
Auch wenn es "nur" die Klammern waren.
So was sieht nun mal ein Laie nicht, auch wenn es "lächerlich"
erscheinen soll.
Vielen Dank.
Hier die aus meiner Sicht geänderte entscheidende Funktion.
void ventil_schliessen_regler(void)
{
ZU=1; //zähler zählt herunter
while(hub >(ventilstellung_alt-umdrehung_zu ))
{
ADW_lesen(); // Stromaufnahmemessung übernehmen
if ( ADW_P6_3 > 80) break; // ADW_6_3=Kanal 6.3; Stromaufnahme
// wird am Anschlag überschritten; while-Schleife wird verlassen
P3OUT &=~BIT0; // ZU-fahren
}
P3OUT |=BIT0; // ZU-fahren HALT
ZU=0;
}
Wobei aber ADW_P6_3 WÄHREND der Schleife nicht aktualisiert wird, also
entweder ist die Stromaufnahme schon vor der Schleife zu hoch und damit
als Abbruchbedingung vorhanden oder es wirkt sich in der Schleife auch
nicht aus...
äxl schrieb:>> fragt ein Programmierlaie>> Ging ja wieder heiss her hier, gestern abend.> Dafür, dass er 'n Laie ist auf dem Gebiet, geht das doch. Etwas holperig> und ungelenk vielleicht.> Aber trotzdem muss man hier nicht soo arrogant reagieren. Schade...
Ich stimme dir zu äxl. Es ist schade, traurig und dumm. Jeder ist Mal
Laie und Mal Fachmann auf einem Gebiet. Mit etwas mehr Verständnis
füreinander würd's hier glatt noch Spass machen ... . Wahrscheinlich zu
gut für einige.
Tim T. schrieb:>Wobei aber ADW_P6_3 WÄHREND der Schleife nicht aktualisiert wird,
Hat das programmiertechnische Gründe oder liegt es an der Arbeitsweise
des MSP430F1611?
Ich hatte eigentlich gedacht, dass der AD-wandler die Abtastung der
Kanäle mit
ADC12CTL0 |= ADC12SC+ ENC;
ständig wiederholt und dass mit
ADW_P6_3 = ADC12MEM3;
der Speicher ADC12MEM3 abgefragt wird und damit ADW_P6_3 auch beim
Durchlaufen der while-Schleife aktuell ist.
Tim T. schrieb:> Wobei aber ADW_P6_3 WÄHREND der Schleife nicht aktualisiert wird, also> entweder ist die Stromaufnahme schon vor der Schleife zu hoch und damit> als Abbruchbedingung vorhanden oder es wirkt sich in der Schleife auch> nicht aus...
Das aktualisieren passiert neben der Main() im interrupt.
Roland E. schrieb:> Tim T. schrieb:>> Wobei aber ADW_P6_3 WÄHREND der Schleife nicht aktualisiert wird, also>> entweder ist die Stromaufnahme schon vor der Schleife zu hoch und damit>> als Abbruchbedingung vorhanden oder es wirkt sich in der Schleife auch>> nicht aus...>> Das aktualisieren passiert neben der Main() im interrupt.
Nö, ADW_P6_3 wird nur in der ADW_lesen() Funktion zugewiesen und die
wird nirgends aufgerufen...
Roland E. schrieb:>Das aktualisieren passiert neben der Main() im interrupt.
Könnte das hier so gemeint sein? (aus SLAU049E)
Repeat-Sequence-of-Channels Mode
A sequence of channels is sampled and converted repeatedly. The ADC
results are written to the conversion memories starting with the
ADC12MEMx defined by the CSTARTADDx bits. The sequence ends after the
measurement
of the channel with a set EOS bit and the next trigger signal re-starts
the
sequence. Figure 17−9 shows the repeat-sequence-of-channels mode.
wolle g. schrieb:
>> ADW_P6_3 = ADC12MEM3;>Das ist ne Zuweisung, mehr nicht. Und wann wird die in der Schleife>gemacht? Richtig, garnicht.
Gibt es eine Lösung, um an den aktuellen Wert von ADW_P6_3 innerhalb
der while-Schleife zu kommen?
> wolle g. schrieb:> Gibt es eine Lösung, um an den aktuellen Wert von ADW_P6_3 innerhalb> der while-Schleife zu kommen?
Argh, das ist echt so traurig.
ADW_P6_3 hat NATÜRLICH immer seinen aktuellen Wert, es ist ja nur ein
verdammter int, geht auch garnicht anders, nur das ist überhaupt nicht
was du willst!
Du willst nicht den aktuellen Wert von ADW_P6_3 wissen sondern den
aktuellen Wert was bei der ADC Wandlung rausgekommen ist und jetzt
Quizfrage, wo steht diese Information wohl?
Ob du den dann noch ADW_P6_3 zuweisen möchtest oder ob du ihn direkt
nutzen willst ist dabei total egal...
wolle g. schrieb:> ... schrieb:>> Im Moment kenne ich nur den Codeschnipsel.>> deshalb als Anhang mal das gesamte Hauptprogramm, auch wenn es> vielleicht nicht allen Anforderungen entsprechen sollte.
Nein, das ist nicht das gesamte Programm.
* Was verbirgt die includierte C-Datei namens "DS10-gP12-SD_MAINTI.c" ?
* Sind da vielleciht die Funktionen temp_messung_starten() und
FKA_einrichten() definiert?
Ausserdem: Die pauseX() Funktionen werden wenn du Glück oder Pech hast,
vom Compiler komplett wegoptimiert und bewirken allen das gleich,
nämlich NIX. Du hast einen Timer - benutzt den!
Hallo,
Das alte Pferd
XXX:
goto
läuft noch. Und sogar in der Bibel (K&R) wird es für tief
verschachtelten Schleifen empfohlen.
( Gültig für C/C++ und Arduino)
max123 schrieb:> Hallo,>> Das alte Pferd>> XXX:> goto>> läuft noch. Und sogar in der Bibel (K&R) wird es für tief> verschachtelten Schleifen empfohlen.> ( Gültig für C/C++ und Arduino)
Praktisch um dem toten Pferd den Rest zu geben? Gotos sind fast immer
Unsinn, das einzige wofür ich die z.B. benutze ist um bei Treiber
initialisierungen Stufenweise zu deinitialisieren wenn was schief läuft.
Hier haben sie jedenfalls garnix zu suchen.
Eric B. schrieb:> Ausserdem: Die pauseX() Funktionen werden wenn du Glück oder Pech hast,> vom Compiler komplett wegoptimiert und bewirken allen das gleich,> nämlich NIX. Du hast einen Timer - benutzt den!
Das hat aber nichts mit dem Thema while ... zu tun.
Aber wenn man evtl. mein Programm verbessern möchte, dann bitte mit
konkreten Zeilen (einschließlich Klammern usw.)
>Du hast einen Timer - benutzt den!
Damit kann ich z.B. in diesem Fall gar nichts anfangen.
Nach der oben gezeigten Korrektur läuft man Programm, wobei jetzt noch
offen ist, welcher Wert der Stromaufnahme für den Abbruch der Schleife
verwendet wird. Während des Lauf der while-Schleife oder vor Beginn der
Schleife.
M.M. nach müsste es der ADW_P6_3 Wert sein, der während des
Schleifenlaufs vom AD_Wandler (ADCM12EM3) gemessen wird.
wolle g. schrieb:> M.M. nach müsste es der ADW_P6_3 Wert sein, der während des> Schleifenlaufs vom AD_Wandler (ADCM12EM3) gemessen wird.
-.-
ADW_P6_3 ist einfach nur eine Variable vom Typ int, die überhaupt nichts
selber macht, der musst du, damit du irgendwas sinnvolles damit machen
kannst, schon einen entsprechenden Wert zuweisen.
ADCM12EM3 ist ein Ergebnisregister wo die ADC-Einheit nach jedem
Messvorgang ein Ergebniswert rein schreibt, komplett unabhängig von
deinem sonstigen Programmablauf. Du machst die ganze Zeit den Fehler,
dass du aus irgendwelchen Gründen erwartest, dass die Variable ADW_P6_3,
warum auch immer, den gleichen Wert wie das Messergebnis im Register
ADCM12EM3 besitzt. Die VARIABLE ADW_P6_3 muss der Wert aus dem REGISTER
ADCM12EM3 zugewisen werden ( ADW_P6_3 = ADCM12EM3 ) und das musst du vor
jeder Prüfung innerhalb der Schleife machen, sonst testest du jeweils
nur gegen den alten Wert der Variablen ADW_P6_3. Wobei sich da natürlich
dann die Frage stellt, warum du nicht direkt das REGISTER ADCM12EM3
testest (z.B. if ( ADCM12EM3 > 80 ) break;) !?
Und jetzt hab ich keine Lust mehr...
Tim T. schrieb:>Und jetzt hab ich keine Lust mehr...
Nicht so schnell aufgeben!
> Die VARIABLE ADW_P6_3 muss der Wert aus dem REGISTER> ADCM12EM3 zugewiesen werden ( ADW_P6_3 = ADCM12EM3 )
Wahrscheinlich hast Du es übersehen.
In der Funktion: int ADW_lesen(void)
werden die ADW-Register gelesen.
Das soll jetzt kein Vorwurf sein, denn mein Programm lädt vermutlich
nicht zum Studium ein.
>Wobei sich da natürlich dann die Frage stellt, warum du nicht direkt das >REGISTER ADCM12EM3 testest (z.B. if ( ADCM12EM3 > 80 ) break;) !?
Die Frage ist berechtigt. Hier bin ich dem Holzweg gelandet. Vor
gewisser Zeit hatte ich etwas zur Funktionsweise des AD-Wandlers falsch
gedeutet.
wolle g. schrieb:> Wahrscheinlich hast Du es übersehen.> In der Funktion: int ADW_lesen(void)> werden die ADW-Register gelesen.> Das soll jetzt kein Vorwurf sein, denn mein Programm lädt vermutlich> nicht zum Studium ein.
Nein, wenn du mal weiter oben genau gelesen hättest, wäre dir
aufgefallen das ich die schon gefunden hab, aber sie wird nirgendwo
aufgerufen, was ich aber auch oben geschrieben hab.
Jetzt bin ich aber wirklich raus, ist müßig wenn nichtmal der ganze Text
gelesen wird...
Prozessor Dokter Schmunz schrieb:> Quatsch. Das sind Weicheierschleifen.>> Männerschleifen werden SO geschrieben:While(1) {> if(Abbruchbedingung)> {break;}> }
Echt lustig, dass du Männerschleifen und Rheinwerk (Jürgen Wolf) in
einem Beitrag gemeins erwähnst.
Ich sage nicht, dass du falsch liegst, aber es kommt auf das Problem
drauf an, man kann vieles nicht einfach über ein Kamm scheren.
Manchmal ist es Sinnvoller beides oder doch nur das eine zu
machen...oder vllt. doch eine
do
{
/* */
} while (x);
Deine while(1) ist nämlich in deinem Link nicht zu finden...
DORT steht die Abbruchbedingung auch im Kopf der while().
Naja, sei es drum.
Und nun geht es seid 2 Tagen und hab in allen Beiträgen keine Anständige
Antwort gesehen, die dem TO als Lösung dienen könnte...
Adam P. schrieb:> in allen Beiträgen keine Anständige> Antwort gesehen, die dem TO als Antwort dienen könnte...
Wie kommst Du darauf? Mit Hilfe von Tim T. wurde das Problem im Prinzip
gelöst.
siehe meinen Beitrag 05.03.2019 13:48
wolle g. schrieb:> Wie kommst Du darauf? Mit Hilfe von Tim T. wurde das Problem im Prinzip> gelöst.> siehe meinen Beitrag 05.03.2019 13:48
Ja OK,
Ich bin davon ausgegangen, dass du die Klammern nicht gesetzt hast, da
du wolltest das die while nur die nächste Anweisung einbezieht.
( Hatte den geposteten C Code nicht gesehen) lediglich dein ersten
Code-Schnipsel.
Tim T. schrieb:>aber sie wird nirgendwo aufgerufen,
Ich denke, im Programmschnipsel vom 05.03.2019 13:48 wird mit
ADW_lesen(); ADC12MEM3 abgerufen.
void ventil_schliessen_regler(void)
{
ZU=1; //zähler zählt herunter
while(hub >(ventilstellung_alt-umdrehung_zu ))
{
ADW_lesen(); // Stromaufnahmemessung übernehmen
if ( ADW_P6_3 > 80) break; // ADW_6_3=Kanal 6.3; Stromaufnahme
// wird am Anschlag überschritten; while-Schleife wird verlassen
P3OUT &=~BIT0; // ZU-fahren
}
P3OUT |=BIT0; // ZU-fahren HALT
ZU=0;
}
Mit ADW_P6_3 = ADC12MEM3;
enthält m. E. ADW_P6_3 das Messergebnis, welches in ADC12MEM3 aktuell
steht.
>Jetzt bin ich aber wirklich raus,
Nee, nee; Das ist erst möglich, wenn Du mich überzeugt hast.