Forum: Mikrocontroller und Digitale Elektronik Drehgeber Richtung Counter


von bd (Gast)


Lesenswert?

Hallo,

folgender Sachverhalt:

Ich nutze den Timer1 des Atmega128 als Counter (Counter1). Dieser zählt 
externe Impulse (ca. 1-2Khz). Wenn ein gewisser Schwellwert erreicht ist 
(z.b. 20), so wird der TIMER1_COMPA_vect Interrupt ausgelöst, der 
wiederum eine Variable X hochzählt (bzw. runterzählt).

Dann nutze ich die Int2 und Int3 Eingänge als externe Interrupts. Diese 
dienen dazu, die Zählrichtung zu ändern. Sprich: Int2 sorgt dafür, dass 
die Variable X hochgezählt wird, Int3 sorgt dafür, dass die Variable X 
runtergezählt wird.

Das alles funktioniert auch problemlos.

Jedoch ergibt sich beim Zählrichtungswechsel eine Verfälschung der 
Ergebnisse. Folgende Ausgangssituation: Die Variable X wird hochgezählt, 
der Counter1 Zählerstand ist z.b. gerade bei 18. Der Interrupt soll bei 
20 auslösen und damit die Variable X incrementieren. Nun kommt Int3, so 
dass die Variable X von nun an runter gezählt werden soll. Da der 
Counter1 seine Zählrichtung nicht ändern kann, zählt er also beim 
nächsten einkommenden Impuls auf 19, dann 20 und löst den interrupt aus, 
der die Variable X um 1 dekrementiert. Jedoch soll die Variable X erst 
nach 18 Impulsen decrementiert werden, da die 18 Impulse ja zuvor 
hochgezählt wurden.

Meine Lösung wäre folgende: Bei Int3 weise ich dem Vergleichsregister 
OCR1A den wert von TCNT1 zu und setze TCNT1 anschließend zurück auf 0. 
Dann zählt der Zähler bis 18 und dekrementiert dann Variable X:

tmp_sreg = SREG;
cli();
if (TCNT1 >=0){
    temp_counter=TCNT1;
    TCNT1=0;
    OCR1A=temp_counter;
    }
SREG = tmp_sreg;

Funktioniert aber nicht.  Kann ich das so nicht machen?

von bd (Gast)


Lesenswert?

Tippfehler in der If Abfrage. Richtig ist:

if (TCNT1 >0)

von Tapferer Recke (Gast)


Lesenswert?

bd schrieb:
> if (TCNT1 >=0)

Wann soll den diese Bedingung nicht erfüllt sein??

von bd (Gast)


Lesenswert?

siehe mein ergänzendes zweites Posting ;)

von Eric B. (beric)


Lesenswert?

bd schrieb:

> Meine Lösung wäre folgende: Bei Int3 weise ich dem Vergleichsregister
> OCR1A den wert von TCNT1 zu und setze TCNT1 anschließend zurück auf 0.
> Dann zählt der Zähler bis 18 und dekrementiert dann Variable X:

Aber dann musst du danach nicht vergessen dein OCR1A Wert wieder auf 20 
zurückzustellen. Meine Lösung wäre TCNT auf 2 (20-18) zu stellen und 
OCR1A nicht anzufassen:
1
tmp_sreg = SREG;
2
cli();
3
if (TCNT1 >=0){
4
    TCNT1 = OCR1A - TCNT1;
5
}
6
SREG = tmp_sreg;

DISCLAIMER: Keine Ahnung ob das funktioniert 8-)

EDIT: Und 2 Interrupts für die Drehrichtung ist murks. Du brauchst nur 
einen, um Richtung zu wechseln. :-)

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

bd schrieb:

> Jedoch ergibt sich beim Zählrichtungswechsel eine Verfälschung der
> Ergebnisse.

Nein, alles macht genau, was du ihm gesagt hast, was es machen soll. 
Wenn du das Ergebnis für falsch hältst, hast du der Sache einfach nur 
nicht gesagt, was du tatsächlich machen willst.

Sowas nennt man einen logischen Programmierfehler. Nix Schlimmes, machen 
alle (zumindest hin und wieder).

Das Problem bei dir ist halt nur: du bist nichtmal in der Lage, formal 
auszudrücken, was du eigentlich willst. Das ist natürlich eine ganz 
schlechte Voraussetzung dafür, deine Intention in so etwas Formalem wie 
einer Programmiersprache korrekt auszudrücken.

Da hilft nur eins wirklich: Lernen. Garnicht mal so sehr das 
Programmieren, sondern einfach nur logisch zu denken und das Problem 
formal logisch korrekt zu formulieren.

Konkret geht es hier eigentlich nur um das Problem, TCNTx und OCRx nach 
eine Anweisung zur Zählrichtungsänderung korrekt vorzubesetzen, damit 
der OC-Interrupt im gewünschten Moment erfolgt. Das ist trivialste 
Mathematik. 3. Klasse oder so, Rechnen mit "Ganzen Zahlen"...

Und übrigens: Sehr sinnvoll ist deine "Lösung" insgesamt sowieso nicht. 
Denn bei dem, was du eigentlich willst, bringt die Verwendung der 
Hardware eigentlich nur Nachteile. Sprich: es wäre viel einfacher, das 
rein in Software umzusetzen, insbesondere wohl für dich...

Warum versuchst du es also in Hardware? Da braucht man nicht lange 
raten: Da ist noch anderer Code im Spiel, der quasi "parallel" ablaufen 
soll, aber entgegen jeder Warnung der Erwachsenen mit Delays 
programmiert wurde...

Stimmt's oder hab' ich Recht?

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.