Forum: Mikrocontroller und Digitale Elektronik Zählrichtung festlegen


von Wolle G. (wolleg)


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?

von Dirk B. (dirkb2)


Lesenswert?

Wie oft wird der interrupt aufgerufen, wenn die Lichtschranke 
durchlässig ist?

von Wolle G. (wolleg)


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

von Achim S. (Gast)


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.

von Walter (Gast)


Lesenswert?

sind die Taster mit Pullup oder Pulldown?

von Wolle G. (wolleg)


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.

von Walter (Gast)


Lesenswert?

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

von Wolle G. (wolleg)


Lesenswert?

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.

von H.Joachim S. (crazyhorse)


Lesenswert?

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?

von Achim S. (Gast)


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?

von Patrick (Gast)


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.

von Patrick (Gast)


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
}

von Wolle G. (wolleg)


Angehängte Dateien:

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.

von Wolle G. (wolleg)


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

von Patrick (Gast)


Lesenswert?

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
....

von Wolle G. (wolleg)


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)

von Patrick (Gast)


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
    ....

von Wolle G. (wolleg)


Lesenswert?

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
von Stefan F. (Gast)


Lesenswert?

wolle g. schrieb:
> hier wird gleich gemeckert:
>
> in funktion 'P2anschluss '
>  AUF undeklariert

Das ist ja jetzt auch klein geschrieben.

von Wolle G. (wolleg)


Lesenswert?

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,

von Stefan F. (Gast)


Lesenswert?

Vielleicht zeigst du mal den aktuellen Quelltext, damit wir ihn nicht im 
Kopf nach persönlichem Gusto ausdenken müssen.

von Mario M. (thelonging)


Lesenswert?

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".

von Wolle G. (wolleg)


Lesenswert?

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
von Patrick (Gast)


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
}

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
Noch kein Account? Hier anmelden.