Zählrichtung festlegen

#5678489
Lesenswert?

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?
#5678572
Lesenswert?

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
Gast #5678573
Lesenswert?

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.
#5678596
Lesenswert?

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.
Gast #5678726
Lesenswert?

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?
Gast #5679330
Lesenswert?

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.
Gast #5679350
Lesenswert?

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
}
#5679498
Lesenswert?

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.
Angehängte Dateien:
#5679606
Lesenswert?

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
#5679827
Lesenswert?

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)
Gast #5679969
Lesenswert?

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
    ....
Gast #5680760
Lesenswert?

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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren