Problem: ATMega88 mit Encoder

Gast #3335043
Lesenswert?

Hallo,

ich habe ein Problem mit dem Einlesen eines Encoders (Pollin: PANASONIC 
EVEQDBRL416B).

Hardware: ATMega88
Programm: Anlehnung an Beispiel unter 
http://www.mikrocontroller.net/articles/Drehgeber (s. Anhang)

Bei der Problemsuche sind mir folgende Punkte aufgefallen:

OCR2A = (uint8_t)(XTAL2 / 64.0 * 1e-3 - 0.5)
Das Register sollte doch mit einem Wert gefüllt werden, der jede 
Millisekunde einen Interrupt erzeugt - oder? Bei meinem Programm stimmte 
dies nicht. Wie kommt man auf diese Formel?

Ich habe daraufhin folgenden Fix-Wert angegeben:
OCR2A = (uint8_t)(15);  // 1ms
Begründung: Die interne Clock-Frequenz ist 1/8 der Systemclock. Mit 
einem Vorteiler von 64 benötigt man somit 64us bis zum nächsten Zählwert 
im Timer. Nach 15*64us hat man rund 1ms (mit Oszi nachgemessen).

Das Hauptproblem sind aber die Berechnungen der Variablen "diff" und 
"enc_delta" in der Interruptroutine.

Die Reihenfolge der Variable "new" in die 1. Drehrichtung ist nach 
meiner Meinung 0->1->2->3->0 usw. und in die andere 0->3->2->1->0. Die 
Differenz ist somit -1 bzw. +1. (Ausnahme: 3->0 bzw. 0->3).

An dieser Stelle bin ich dann "ausgestiegen". Kann mir daher bitte 
jemand die Zeilen von

diff = last - new;                // difference last - new
  if( diff & 1 ){               // bit 0 = value (1)
    last = new;                 // store new as next last
    enc_delta += (diff & 2) - 1;        // bit 1 = direction (+/-)
  }

erklären?
Angehängte Dateien:
Gast #3335058
Lesenswert?

>OCR2A = (uint8_t)(XTAL2 / 64.0 * 1e-3 - 0.5)
>Das Register sollte doch mit einem Wert gefüllt werden, der jede
>Millisekunde einen Interrupt erzeugt - oder? Bei meinem Programm stimmte
>dies nicht. Wie kommt man auf diese Formel?

>Ich habe daraufhin folgenden Fix-Wert angegeben:
>OCR2A = (uint8_t)(15);  // 1ms
>Begründung: Die interne Clock-Frequenz ist 1/8 der Systemclock. Mit
>einem Vorteiler von 64 benötigt man somit 64us bis zum nächsten Zählwert
>im Timer. Nach 15*64us hat man rund 1ms (mit Oszi nachgemessen).

Du stellst eine Frage um sie Dir dann selber zu beantworten.
Übrigens, sieht deine Rechnung gut aus.

Gruß JOnas
#3335877
Lesenswert?

@ Thomas (Gast)

>Die Bedingung if (diff & 1) ist erfüllt, wenn die Variable "diff" den
>Wert "1" besitzt.

Nein. Wenn die bitweise Verknüpfung von diff und der Konstanten 1 
logisch wahr ist. Sprich, wenn das LSB von diff gesetzt ist. Siehe 
Bitmanipulation.

> Was ist aber wenn die Variable "diff" den Wert "-1"
> besitzt?

-1 = 0xFF -> ebenso wahr ;-)

>Mit der Formel  enc_delta += (diff & 2) - 1 kann ich überhaupt nichts
>anfangen....

Siehe oben. Du musst erstmal die C-Grundlagen lernen, damit du die 
Befehle richtg verstehst. DANN kannst du über den Algorithmus 
nachdenken.

enc_delta += (diff & 2) - 1
enc_delta  = enc_delta + (diff & 2) - 1

(diff & 2) -> bitweise Verknüpfung von diff und 2

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