Um bei einem Heizkörpermotorventil (elektron. Thermostatventil) den aktuellen Stellweg zu ermitteln, habe ich im Getriebe am ersten Zahnrad eine IR-Lichtschranke eingebaut, die bei jeder Umdrehung einen Impuls erzeugt. Diese Impulse werden gezählt und sind ein Maß für den Stellweg. Das Zählen funktioniert erst einmal, aber mir gelingt es programmiertechnisch nicht, dass der Zählwert je nach Laufrichtung hoch oder runterzählt. Hier mein Programmschnipsel: int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer while(1) { if (P2IN&BIT0) // Taste Ventil-AUF gedrückt { AUF=1; P4OUT &=~BIT0; // LED rot P4.0 EIN P2OUT &=~BIT4; // AUF-fahren } else { P4OUT |=BIT0; AUF=2; P2OUT |=BIT4; //Halt Motor } if (P2IN&BIT1) // Taste Ventil-ZU gedrückt { P4OUT &=~BIT1; // LED gelb P4.1 EIN ZU=1; P3OUT &=~BIT0; // ZU-fahren } else { ZU=2; P4OUT |=BIT1; // LED gelb P4.1 AUS P3OUT |= BIT0; //Halt Motor } } } interrupt (PORT2_VECTOR)P2anschluss (void) { Blitz_gelb(); if (AUF==1) // Zählereingang { zaehlerstand = zaehlerstand +1; zaehlerstand_anzeigen(); } if(ZU==1) zaehlerstand_anzeigen(); // Zählereingang { zaehlerstand = zaehlerstand -1; zaehlerstand_anzeigen(); } P2IFG&=~BIT5; } Zur Erläuterung: In der while–Schleife werden die Taster für AUF und ZU abgefragt und der Motor über eine H-Brücke angesteuert. Um die Zählrichtung zu ermitteln, wollte ich durch Einfügen der Variablen AUF=1 bzw ZU=1 in die Tasterbefehle ein Art Verknüpfung mit der Zählrichtung herstellen. Also wenn Taste AUF gedrückt wird -->hochzählen, wenn Taste ZU gedrückt wird -->herunterzählen. Leider erfolgt nach obigem Beispiel kein Zählen mehr. Hat jemand eine andere Idee oder sieht meinen Fehler?
Wie oft wird der interrupt aufgerufen, wenn die Lichtschranke durchlässig ist?
Dirk B. schrieb: > Wie oft wird der interrupt aufgerufen, wenn die Lichtschranke > durchlässig ist? nach Oszibild sieht man ca. alle 60ms einen ca 10ms breiten negativen Impuls. Wenn man die Zeile: if (AUF==1) und die Zeilen für das Herunterzählen weg lässt, dann läuft das Zählen wie es soll bzw. im umgedrehten Fall wird heruntergezählt --> negative Werte
deine if-Abfrage für ZU funktioniert nicht: wolle g. schrieb: > if(ZU==1) zaehlerstand_anzeigen(); // Zählereingang > { > zaehlerstand = zaehlerstand -1; > zaehlerstand_anzeigen(); > } Die if-Abfrage wirkt sich nur auf den Aufruf von zaehlerstand_anzeigen() aus. D.h. der nachfolgende Block mit zaehlerstand = zaehlerstand -1; wird in jedem Fall ausgeführt. Und wenn du zuvor gerade den Zählerstand um 1 erhöht hast (AUF==1), dann wird diese Änderung hier wieder zurückgenommen.
Achim S. schrieb: > deine if-Abfrage für ZU funktioniert nicht: > > wolle g. schrieb: >> if(ZU==1) zaehlerstand_anzeigen(); // Zählereingang >> { >> zaehlerstand = zaehlerstand -1; >> zaehlerstand_anzeigen(); >> } Mist. Das kommt davon, wenn man den aktuellen Stand nicht richtig kopiert. >D.h. der nachfolgende Block mit zaehlerstand = zaehlerstand -1; wird in >jedem Fall ausgeführt. So hatte ich mir das ja auch gedacht, aber leider wird gar nichts angezeigt, woraus ich ableiten würde, dass die Zeilen if (AUF==1) nicht funktionieren oder die Variable AUF nicht erzeugt wird bzw. zum richtigen Zeitpunkt nicht zu Verfügung steht Walter schrieb: >sind die Taster mit Pullup oder Pulldown? Die Taster liegen über einen Widerstand auf Masse.
wolle g. schrieb: > if (P2IN&BIT0) // Taste Ventil-AUF gedrückt wolle g. schrieb: > Walter schrieb: >>sind die Taster mit Pullup oder Pulldown? > Die Taster liegen über einen Widerstand auf Masse. wenn das so zu verstehen ist dass die Taster beim Drücken den Eingang auf Masse ziehen, dann ist die Abfrage falsch
Walter schrieb: > wenn das so zu verstehen ist dass die Taster beim Drücken den Eingang > auf Masse ziehen, dann ist die Abfrage falsch Der Taster liegt auf Masse (über einen R) und der Eingang des µC wird beim Drücken auf +3V geschaltet.
wolle g. schrieb: > Der Taster liegt auf Masse (über einen R) und der Eingang des µC wird > beim Drücken auf +3V geschaltet. Interessanter Ansatz - wie machst du das?
wolle g. schrieb: > So hatte ich mir das ja auch gedacht, aber leider wird gar nichts > angezeigt, woraus ich ableiten würde, dass die Zeilen if (AUF==1) nicht > funktionieren oder die Variable AUF nicht erzeugt wird bzw. zum > richtigen Zeitpunkt nicht zu Verfügung steht zuerst war deine Fehlerbeschreibung, dass nicht gezählt wird. Jetzt meinst du, es wird nichts angezeigt. Kannst du das Fehlerbild mal etwas sauberer herausarbeiten? Der Compiler wird schon das umsetzen, was du hingeschrieben hast. Deshalb würde ich mir weniger Sorgen um die Verfügbarkeit der Variablen machen, das Problem liegt wohl eher in deiner Interpretation der Ausgaben des Codes. Was macht die Funktion zaehler_anzeigen()? Wird etwas auf ein Display geschrieben? Oder über die serielle Schnittstelle geschickt? Kann es sein, dass diese Routine sich "verschluckt" oder den Programmablauf lange unterbricht? Wird die Funktion Blitz_gelb() denn wie erwartet ausgeführt, wenn das Zahnrad dreht?
Ich würde die ZU-Variable einsparen. Die Information AUF oder ZU eigentlich in einem einzelnen Bit/ bzw in C einer Variable abbildbar --> "AUF"-gedrückt --> AUF = 1; sowie "ZU" gedrückt --> AUF = 0; So merkst du dir die letzte aktivierte Richtung und zählst bei einem Impuls, der ja nur kommt, wenn der Motor in die entsprechende Richtung dreht. Außerdem hast du bisher noch keine Verriegelung der beiden Richtungen, wenn ich das richtig deute --> wenn deine H-Brücke das ausschließt, ists ok, aber schicker wäre eine Reaktion "STOPP" bei gleichzeitiger Betätigung der Taster.
In etwa so: (noch ohne Richtungsverriegelung)
1 | int main(void) |
2 | {
|
3 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer |
4 | |
5 | while(1) |
6 | {
|
7 | if (P2IN&BIT0) // Taste Ventil-AUF gedrückt |
8 | {
|
9 | AUF=1; |
10 | P4OUT &=~BIT0; // LED rot P4.0 EIN |
11 | P2OUT &=~BIT4; // AUF-fahren |
12 | }
|
13 | else
|
14 | {
|
15 | P4OUT |=BIT0; |
16 | P2OUT |=BIT4; //Halt Motor |
17 | }
|
18 | |
19 | if (P2IN&BIT1) // Taste Ventil-ZU gedrückt |
20 | {
|
21 | P4OUT &=~BIT1; // LED gelb P4.1 EIN |
22 | AUF=0; |
23 | P3OUT &=~BIT0; // ZU-fahren |
24 | }
|
25 | else
|
26 | {
|
27 | P4OUT |=BIT1; // LED gelb P4.1 AUS |
28 | P3OUT |= BIT0; //Halt Motor |
29 | }
|
30 | }
|
31 | }
|
32 | |
33 | interrupt (PORT2_VECTOR)P2anschluss (void) |
34 | {
|
35 | Blitz_gelb(); |
36 | |
37 | if (AUF==1) // Zählereingang |
38 | {
|
39 | zaehlerstand = zaehlerstand +1; |
40 | }
|
41 | else
|
42 | {
|
43 | zaehlerstand = zaehlerstand -1; |
44 | |
45 | }
|
46 | zaehlerstand_anzeigen(); |
47 | P2IFG&=~BIT5; |
48 | }
|
H.Joachim S. schrieb: > wolle g. schrieb: >> Der Taster liegt auf Masse (über einen R) und der Eingang des µC wird >> beim Drücken auf +3V geschaltet. > > Interessanter Ansatz - wie machst du das? Ich hänge mal das Schaltbild an. Die H-Brücke hängt an der mit dem Pfeil gekennzeichneten Buchsenleiste. Die Taster heißen hier Prog1 und Prog2.
Achim S. schrieb: > zuerst war deine Fehlerbeschreibung, dass nicht gezählt wird. Jetzt > meinst du, es wird nichts angezeigt. Kannst du das Fehlerbild mal etwas > sauberer herausarbeiten? > > Der Compiler wird schon das umsetzen, was du hingeschrieben hast. > Deshalb würde ich mir weniger Sorgen um die Verfügbarkeit der Variablen > machen, das Problem liegt wohl eher in deiner Interpretation der > Ausgaben des Codes. > Wird die Funktion Blitz_gelb() denn wie erwartet ausgeführt, wenn das > Zahnrad dreht? a) Blitz wird erwatungsgemäß ausgeführt und ist auch ein Zeichen dafür, dass die Tasten und die Lichtschranke funktionieren. b) Patricks Vorschlag habe ich getestet. Ergebnis: Der Zähler läuft nur rückwärts, weil offensichtlich nur die Zeile zaehlerstand = zaehlerstand -1; bearbeitet und dann angezeigt wird. c) hier noch einmal meine Version mit meinen Beobachtungen: Wenn ich es so benutze, wie folgend angegeben, dann wird aufwärts gezählt und der Zählerstand wird auf einer Flüssigkristallanzeige angezeigt, egal welche Taste gedrückt wird. Zunächst i.O. Wenn alle Zeilen verarbeitet werden sollen (wie nennt man das? kommentieren/ auskommentieren?), mit /* …….. */ herausnehmen Dann wird nichts angezeigt, denn wie oben schon vermutet, werden wahrscheinlich die if-Schleifen nicht verarbeitet. (meine Theorie) interrupt (PORT2_VECTOR)P2anschluss (void) { Blitz_gelb(); //if (AUF==1) { zaehlerstand = zaehlerstand +1; zaehlerstand_anzeigen(); }/* if (ZU==1) { zaehlerstand = zaehlerstand -1; zaehlerstand_anzeigen(); }*/ P2IFG&=~BIT5; } hoffentlich habe ich mich jetzt besser ausgedrückt
Wo hast du denn "AUF" deklariert? Nicht dass das immer wieder neu initialisiert wird.. Versuchs mal als erstes hinter
1 | int main(void) |
2 | {
|
3 | int AUF = 0; |
4 | ....
|
Patrick schrieb: > Wo hast du denn "AUF" deklariert? Die Variablen AUF, ZU wurden als globale Variable (oder wie man das nennt) deklariert. So: unsigned int AUF,ZU; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer while(1) { if (P2IN&BIT0) // Taste Ventil-AUF gedrückt { AUF=1; P4OUT &=~BIT0; // LED rot P4.0 EIN P2OUT &=~BIT4; // AUF-fahren } else ............ Jetzt habe ich mal bei der Deklaration geschrieben: unsigned int AUF=1,ZU; und damit wird aufwärts gezählt bei unsigned int AUF,ZU=1; wird abwärts gezählt Also, wie könnte man es anstellen, dass den Variablen erst dann ein Wert zugeordnet wird, wenn sie gebraucht werden. (hier bei Tastendruck, später zusätzlich von einem PI(D)-Regler)
Das wirkt, als ob die Speicherstellen der Variablen durch die Zuweisungen in der Main nicht erreicht werden. Versuch mal, sie in der main als "extern" bekannt zu machen, so vermeidest du, dass ggf. nur auf (wie auch immer entstandenen..) Lokalvariablen gearbeitet wird. Zusätzlich besser klein schreiben, Großbuchstaben sollten eigentlich nur für Konstanten verwendet werden.
1 | unsigned int auf,zu; |
2 | int main(void) |
3 | {
|
4 | extern unsigned int auf,zu; |
5 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer |
6 | ....
|
Patrick schrieb: > Versuch mal, sie in der > main als "extern" bekannt zu machen, so vermeidest du, dass ggf. nur auf > (wie auch immer entstandenen..) Lokalvariablen gearbeitet wird. hier wird gleich gemeckert: in funktion 'P2anschluss ' AUF undeklariert
:
Bearbeitet durch User
wolle g. schrieb: > hier wird gleich gemeckert: > > in funktion 'P2anschluss ' > AUF undeklariert Das ist ja jetzt auch klein geschrieben.
Stefanus F. schrieb: > Das ist ja jetzt auch klein geschrieben. dürfte m.E. keine Rolle spielen, denn bei Deklaration und Verwendung wurden die Variablen groß geschrieben,
Vielleicht zeigst du mal den aktuellen Quelltext, damit wir ihn nicht im Kopf nach persönlichem Gusto ausdenken müssen.
Achim S. schrieb: > Der Compiler wird schon das umsetzen, was du hingeschrieben hast. > Deshalb würde ich mir weniger Sorgen um die Verfügbarkeit der Variablen > machen, ... Und dann kommt der Optimierer und macht Dir einen Strich durch die Rechnung. @wolleg: Deklariere AUF und ZU doch mal als "volatile".
Mario M. schrieb: > Und dann kommt der Optimierer und macht Dir einen Strich durch die > Rechnung. > @wolleg: Deklariere AUF und ZU doch mal als "volatile". Danke für den Hinweis. auch an alle "Mitarbeiter" Problem gelöst. Gehört wahrscheinlich in die Rubrik "hohe Schule" für Programmierlaien.
:
Bearbeitet durch User
Alle vorgeschlagenen Änderungen in C hab ich mal angefügt. Ich kann mir vorstellen, dass der Knackpunkt im "volatile" im Interrupt begraben liegt - der Interrupt "weiss" nicht, dass außer ihm noch andere Prozeduren, wie etwa die Main auf die Variablen einfluss nehmen. --> Im Interrupt wird nur gelesen, d.h. er geht von einer Art Konstante aus und lädt nicht neu. Die Angabe "extern volatile" in der Main und im Interrupt isteigentlich überflüssig, sofern sie sich im gleichen C-File befinden, aber schaden tut es auch nicht. Falls es funktioniert, kannst du sie ja dann wieder rauswerfen.
1 | volatile unsigned int auf, zu; |
2 | int main(void) |
3 | {
|
4 | extern volatile unsigned int auf, zu; |
5 | |
6 | WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer |
7 | |
8 | while(1) |
9 | {
|
10 | if (P2IN&BIT0) // Taste Ventil-AUF gedrückt |
11 | {
|
12 | auf=1; |
13 | P4OUT &=~BIT0; // LED rot P4.0 EIN |
14 | P2OUT &=~BIT4; // AUF-fahren |
15 | }
|
16 | else
|
17 | {
|
18 | P4OUT |=BIT0; |
19 | P2OUT |=BIT4; //Halt Motor |
20 | }
|
21 | |
22 | if (P2IN&BIT1) // Taste Ventil-ZU gedrückt |
23 | {
|
24 | P4OUT &=~BIT1; // LED gelb P4.1 EIN |
25 | auf=0; |
26 | P3OUT &=~BIT0; // ZU-fahren |
27 | }
|
28 | else
|
29 | {
|
30 | P4OUT |=BIT1; // LED gelb P4.1 AUS |
31 | P3OUT |= BIT0; //Halt Motor |
32 | }
|
33 | }
|
34 | }
|
35 | |
36 | interrupt (PORT2_VECTOR)P2anschluss (void) |
37 | {
|
38 | extern volatile unsigned int auf, zu; |
39 | Blitz_gelb(); |
40 | |
41 | if (auf==1) // Zählereingang |
42 | {
|
43 | zaehlerstand = zaehlerstand +1; |
44 | }
|
45 | else
|
46 | {
|
47 | zaehlerstand = zaehlerstand -1; |
48 | |
49 | }
|
50 | zaehlerstand_anzeigen(); |
51 | P2IFG&=~BIT5; |
52 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.