Forum: Mikrocontroller und Digitale Elektronik [ATmega32] Drehgeber Drehrichtung


von Dirk D. (sureai)


Lesenswert?

Hey,

ich will mit einem Drehgeber, der zwei phasenverschobene Rechecksignale 
ausgibt die Drehrichtung erkennen.
Ich habe leider nur einen externen Interrupt zur Verfügung und würde 
mich mit einer "Sparmaßnahme" zurfrieden geben und immer nur wie in 
diesem tut Drehgeber unter 4.1 bei einer steigenden Flanke von A den 
Pin von Phase B auslesen und somit die Drehrichtung rausfinden.
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <stdio.h>
4
#include <avr/interrupt.h>
5
6
volatile unsigned long counter256 = 0;
7
ISR( TIMER0_OVF_vect ){       // Overflow Interrupt Vector Timer0
8
    counter256++;
9
}
10
11
volatile uint8_t flagUmdrehung3 = 0;
12
volatile unsigned int counterUmdrehung3 = 0;
13
volatile int flagRichtung = 0;
14
ISR(INT1_vect){
15
    //Externer Interrupt 2
16
    counterUmdrehung3++; //Eine Umdrehung wurde registriert
17
    flagUmdrehung3 = 1;
18
    counterAtExtIsr = counter256;
19
    counter256 = 0;
20
    //Phase B überprüfen
21
    if ( PINA & (1<<PINA7) ) {
22
       flagRichtung = 1;
23
    } else {
24
        flagRichtung = 0;  
25
    }
26
}
27
28
int main(void){
29
    TCCR1B |= (1<<CS12);
30
    TCCR1A |= (1<<WGM10);
31
    TCCR1B |= (1<<WGM12);
32
    TCCR1A |= (1<<COM1A1) | (1<<COM1B1);
33
    DDRD |= (1<<PD4) | (1<< PD5);
34
    DDRD &= ~(1<<3); //PD3 als Eingang
35
    PORTD|= (1<<3); //Pullup aktivieren
36
    GICR|=(1<<INT1); //INT1 enable im General Interupt Control Register
37
    MCUCR|=(1<<ISC11)|(1<<ISC10); //Steigende Flanke löst aus INT1
38
    //MOTOR = 255;
39
    TIMSK |= (1<<TOIE0);
40
    TCCR0 = (1<<CS00);
41
    int myCounter = 0;
42
    int flagMyRichtung = 0;
43
    DDRA  &= ~(1<<PA7);  // Pin PA7 als Eingang hier liegt Phase B an
44
    PORTA |= (1<<PA7);  //Pullup aktivieren
45
    sei();
46
    while(1){
47
        if (flagUmdrehung3 == 1){
48
             flagUmdrehung3 = 0;
49
             cli();
50
             myCounter = counterAtExtIsr;
51
             flagMyRichtung = flagRichtung;
52
             sei();
53
             printf("%d\n",flagMyRichtung);
54
         }
55
    }
56
}

flagMyRichtung soll also je nach Drehrichtung entweder 1 oder 0 
ausgeben. Blöderweise gibt mein µc immer 1 aus für flagMyRichtung. Ist 
meine Abfrage nach Phase B falsch? So dass nie der else Teil eintreffen 
kann?

von Michael M. (eos400dman)


Lesenswert?

Evtl. prellen die Signale. Hast du die schon mal auf einem Oszi 
angeschaut?

Gruß Michael

von Dirk D. (sureai)


Lesenswert?

Michael M. schrieb:
> Evtl. prellen die Signale. Hast du die schon mal auf einem Oszi
> angeschaut?
>
> Gruß Michael

Was meint man denn mit "prellen" das Wort war mir schon in dem tut neu? 
So etwas wie einen Wackelkontakt?
Ich versuche mal ein Multimeter aufzutreiben, ich bin hier leider echt 
schlecht ausgestattet.

von Michael M. (eos400dman)


Lesenswert?

Dirk D. schrieb:
> ein Multimeter aufzutreiben

Das wird dir da nichts helfen.

Schau mal hier:
https://www.mikrocontroller.net/articles/Entprellung

Gruß Michael

von Wolfgang (Gast)


Lesenswert?

Vergiss das mit dem Interrupt und lies deine beiden Signale einfach in 
einem fest Zeittakt ein.

Das Thema wurde hier schon oft genug diskutiert.

von Harald W. (wilhelms)


Lesenswert?

Dirk D. schrieb:

> ich will mit einem Drehgeber, der zwei phasenverschobene Rechecksignale
> ausgibt die Drehrichtung erkennen.

Da bist Du nicht der erste. Das Thema gibts gefühlt alle zwei Tage
hier im Forum. Die dazu nötigen Grundlagen findest Du hier:
http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29
bzw. auf den µC-Seiten im Tutorial.

von Dirk D. (sureai)


Lesenswert?

Wolfgang schrieb:
> Vergiss das mit dem Interrupt und lies deine beiden Signale einfach in
> einem fest Zeittakt ein.
>
> Das Thema wurde hier schon oft genug diskutiert.

Okay, werde ich so machen. Nachdem ich das tut zum x-ten mal gelesen 
habe ist das glaube ich auch nicht mehr unmöglich für mich. Könnt ihr 
mir noch bestätigen, dass:
1
    if ( PINA & (1<<PINA7) ) {
2
       flagRichtung = 1;
3
    } else {
4
        flagRichtung = 0;  
5
    }

auf jeden Fall korrekt ausliest ob PA7 high oder low ist? Sollte meiner 
Meinung nach richtig sein.
Mit einem Multimeter konnte ich übrigens feststellen, dass sich die 
Spannung an einem Ausgang von meinem Sensor nicht verändert hat sondern 
konst auf ~5V bleibt, an dem anderen Ausgang funktionierte alles. Mit 
dem µc konnte ich auch keine Flankenwechsel über Interrupts feststellen 
an dem Ausgang, also gehe ich davon aus, dass mein Sensor defekt ist.

: Bearbeitet durch User
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.