Inkrementalgeber

Ich habe das Ganze noch einmal neu durchdacht, und jetzt ist die Lösung ganz einfach, und man kommt, wenn man pollt oder 2 2-Flanken-Interrupteingänge hat (nicht beim EZUSB verfügbar) ohne weitere Hardware aus.

Also, der Inkrementalgeber liefert:
	00 - 01 - 11 - 10 usw.
Das ist doch ein 2-bit-Gray-Kode!!!

Da macht man als erstes Binärkode draus:
	00 - 01 - 10 - 11 usw.
mittels: if (kode&0x02) kode^=0x01;

Dies nun subtrahiert man vom vorhergehenden Binärkode, und erhält eine 2-Bit-Differenz (die oberen 6 Bits ignoriert man einfach):

	00 = keine Bewegung
	01 = Bewegung Halbschritt vorwärts
	10 = Bewegung, aber wohin?
	11 = Bewegung Halbschritt rückwärts
Also: if (diff&0x01) Bewege (diff&0x02 ? -1 : +1)

Stören mehrfache Hin- und Herbewegungen während des Umschaltvorgangs nicht, braucht man sich nicht ums Entprellen kümmern, die Zähllogik verzählt sich nicht, solange immer nur 1 der beiden Kontakte prellt. Beispielsweise spielt es keine Rolle, wenn bei einem Lautstärkesteller die Lautstärke beim Leiserdrehen kurz 16-15-16-15 zappelt. Hingegen wäre es bei einem Sendersuchlauf blöd, wenn dieser rückwärts-vorwärts-rückwärts angestoßen auf Grund von zwischenzeitlichen Feldstärkeschwankungen (im Auto) nicht zum vorhergehenden Sender springt, sondern bspw. auf dem vorhandenen bleibt.

Will man Vollschritte, muss man am Bewegunszähler noch ein Bit "unten" mehr vorsehen, oder ein Byte und "+128" bzw. "-128" addieren.

Interessant ist außerdem, dass man die 2 Bits gar nicht "nach unten" schaffen muss; sie können, um ein paar µC-Befehle zu sparen, "oben" gelassen werden; sie müssen nur zusammenhängen. Etwa:

	kode=PORTB&0x60;
	if (kode&0x40) kode^=0x20;
	diff=kode-alter_kode;
	alter_kode=kode;
	if (diff&0x20) {
	 if (diff&0x40) speed=-speed;
	 Bewege(speed);
        }

Hinweis: Die obigen Ausführungen beziehen sich auf symmetrische Signalverläufe, bspw. „2s“ oder „1s“. Bei Gebern mit mehreren „elektrischen Schritten pro Rastung“ muss man einfach nur noch die Zählschritte herunterteilen.