Hallo, wie muss ich das Array aus dem Artikel http://www.mikrocontroller.net/articles/Drehgeber anpassen, wenn bei mir die Dekodertabelle für die halbe Auflösung immer noch doppelt zu schnell geht? Also bei mir zeigt es bei jedem Schritt einen Sprung von 2 an. // Dekodertabelle für wackeligen Rastpunkt // halbe Auflösung int8_t table[16] PROGMEM = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0}; D.h. ich bräuchte obiges Array für viertelte Auflösung. Danke!
Was meinst du mit "jedem Schritt"? Einen Rastpunkt eines Drehknopfs? Das was du vermutlich willlst, geht nicht mehr mit einer Änderung der Tabelle (zumindest nicht ohne deutliche Verlängerung der Tabelle und Änderung des Codes). Warum halbierst du nicht einfach die tatsächlich zum Weiterrechnen benutzte Position? Du bräuchtest also zwei Positionen: die bisherige genauere, aus der mit obiger Tabelle jeweils ein neuer Wert gebildet wird, und eine weitere, die dann immer als die genaue/2 berechnet wird. Mit letzterer arbeitest du im Programm, sie hat die halbe Auflösung.
Z.B. so:
1 | int8_t table[16] PROGMEM = {0,0,0,0,0,0,0,1,0,0,0,0,0,-1,0,0}; |
jørg schrieb: > Teil einfach enc_delta durch 2 Gefährlich. Was passiert, wenn encode_read so oft aufgerufen wird, dass enc_delta bei jeder Abfrage 0 oder 1 ist? Edit: Da die Tabelle nur noch zwei von 0 verschiedene Werte enthält, bringt sie keine Geschwindigkeitsvorteile mehr, im Gegenteil. Folgender Code ist schneller und spart einschließlich der nun nicht mehr benötigten Tabelle 30 Bytes an Flash-Speicher ein.
1 | ISR( TIMER0_COMP_vect ) // 1ms fuer manuelle Eingabe |
2 | {
|
3 | static int8_t last=0; // alten Wert speichern |
4 | int8_t last1; |
5 | |
6 | last1 = (last << 2) & 0x0F; |
7 | if (PHASE_A) last1 |= 0x02; |
8 | if (PHASE_B) last1 |= 0x01; |
9 | if(last1 == 0x07) |
10 | enc_delta++; |
11 | else if(last1 == 0x0d) |
12 | enc_delta--; |
13 | last = last1; |
14 | }
|
Vorsicht: Dieser Code ist nicht getestet :)
@jørg (Gast)
>Teil einfach enc_delta durch 2
Nein, das geht schief. Er muss den aus enc_delta abgeleiteten Wert
normal speichern und daraus den Wert / 2 teilen.
1 | while(1){ |
2 | val += encode_read(); |
3 | val_2 = val / 2; |
4 | LEDS = val_2; |
5 | }
|
MFG Falk
Hä? In der von dir verlinkten Seite sind doch extra Funktionen dafür angelegt worden: int8_t encode_read2( void ) int8_t encode_read4( void ) usw. Da ists vorgemacht, wie man das am besten (=ohne extra Variable) löst.
Yalu X. schrieb: > Z.B. so: > int8_t table[16] PROGMEM = {0,0,0,0,0,0,0,1,0,0,0,0,0,-1,0,0}; Ich habe eine Anfrage erhalten, wie man denn auf diese Tabelle käme. Hier ist eine kurze Erklärung: Die Signale A und B können zusammen vier Zustände annehmen: 00, 01, 10 und 11. Bei jedem Timer-Interrupt geht der Zustand (A,B) in einen Zu- stand (A',B') über. Dafür gibt es 4·4=16 Möglichkeiten. In folgender Tabelle sind auf der linken Seite alle 16 möglichen Zustandsübergänge und auf der rechten Seite der Wert für die Inkrementierung des Zählers (-1, 0 oder +1) aufgelistet. man betrachte sich dazu die Signaldiagramme am Anfang des Artikels [Drehgeber]. Ist die Interruptfrequenz hoch genug, d.h. zwischen zwei Zustandsüber- gänge fällt mindestens ein Interrupt, ändert sich bei jedem Interrupt der Pegel von höchstens einem der Signale A und B. Ändern sich beide Signale zusammen, wurde der Knopf zu schnell gedreht, so dass mindestens ein Zustandsübergang nicht registriert wurde. Diese Fälle sind in der Tabelle mit einem 'F' gekennzeichnet. Ja nachdem, welche Signalflanken bzw. Zustandsübergänge man für die In- krementierung des Zählers nutzt, erhält man unterschiedliche Auflösun- gen: I4 (volle Auflösung): Alle Flanken (4 pro Periode) I2 (halbe Auslösung): Nur Flanken von A (2 pro Periode) I1 (Viertelsauflösung): Nur Flanken von A, während B=1 (1 pro Periode)
1 | -----------+-------------- |
2 | Zustands-| Inkrement |
3 | übergang | (F=Fehler) |
4 | -----+-----+----+----+---- |
5 | A B | A'B'| I4 | I2 | I1 |
6 | -----+-----+----+----+---- |
7 | 0 0 | 0 0 | 0 | 0 | 0 |
8 | 0 0 | 0 1 | +1 | 0 | 0 |
9 | 0 0 | 1 0 | -1 | -1 | 0 |
10 | 0 0 | 1 1 | F | F | F |
11 | 0 1 | 0 0 | -1 | 0 | 0 |
12 | 0 1 | 0 1 | 0 | 0 | 0 |
13 | 0 1 | 1 0 | F | F | F |
14 | 0 1 | 1 1 | +1 | +1 | +1 |
15 | 1 0 | 0 0 | +1 | +1 | 0 |
16 | 1 0 | 0 1 | F | F | F |
17 | 1 0 | 1 0 | 0 | 0 | 0 |
18 | 1 0 | 1 1 | -1 | 0 | 0 |
19 | 1 1 | 0 0 | F | F | F |
20 | 1 1 | 0 1 | -1 | -1 | -1 |
21 | 1 1 | 1 0 | +1 | 0 | 0 |
22 | 1 1 | 1 1 | 0 | 0 | 0 |
23 | -----+-----+----+----+---- |
Der Beispielcode in http://www.mikrocontroller.net/articles/Drehgeber#Dekoder_f.C3.BCr_Drehgeber_mit_wackeligen_Rastpunkten fasst nun die vier Bits A, B, A' und B' eines Zustandsübergangs zu einer Integerzahl last (0..15) zusammen und nutzt diese als Index für die Tabelle der Inkremente. Der Tabellenwert wird dann zur Zählervariablen enc_delta hinzuaddiert. In dem von mir geposteten Codefragment für die Viertelsauflösung wird genau das Gleiche getan, nur ohne Tabelle. Da die Tabelle nur zwei von 0 verschiedene Werte enthält, werden die entsprechenden Indizes (7 und 13) stattdessen mittels zweier if-Abfragen direkt ausgewertet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.