Datum:
Hi, in einem meiner Projekte verwende ich einen Drehencoder. Der Encoder hat ne Rastung, pro Rasteinheit liefert er zwei Inkremente ab. Prinzipell funktioniert die Auswertung. Angeschlossen ist der Drehgeber an zwei externe INTs (PinChange an AVR ATmega88). Im Programm gibt es nun Probleme, weil das Ding prellt. Ne "normale" Entprellung kommt nicht in Frage, weil man ja keine Pulse verpassen will. Das Problem ist, daß Linksdrehen (-) nicht die Umkehrung von Rechtsdrehen (+) ist, d.h. im Programm wird die Folge +-+ anders interpretiert als ++- anders als + etc. Hat jemand ne Idee wie man das lösen könnte? Hier mal die C-Implementierung:
#ifndef _DREHGEBER_H_ #define _DREHGEBER_H_ #define DREH_INVALID -128 static inline char drehgeber_step(void); static inline char drehgeber_job(void); #if defined (__GNUC__) && defined (__AVR__) # include <avr/pgmspace.h> #else # define PROGMEM # define pgm_read_byte(x) (*(x)) #endif // avr-gcc // Aufrufen, wenn eine Flanke an einem der Ports festgestellt wurde, // zB aus einer ISR heraus. char drehgeber_step () { static const char drehgeber_transitions[] PROGMEM = { 0, 1, -1, DREH_INVALID, -1, 0, DREH_INVALID, 1, 1, DREH_INVALID, 0, -1, DREH_INVALID, -1, 1, 0 }; static uint8_t a_alt; uint8_t a = a_alt; if (IS_SET (PORT_DREH_A)) a |= (1 << 2); if (IS_SET (PORT_DREH_B)) a |= (1 << 3); a_alt = a >> 2; return (char) pgm_read_byte (& drehgeber_transitions[a]); } // Mein Drehgeber hat eine Rasterung und bei jeden Raster erzeugt er *zwei* // Flanken. Man muss also die Anzahl der Schritte etwas mühsam durch 2 teilen. char drehgeber_job(void) { char step = drehgeber_step(); char s = 0; if (DREH_INVALID != step) { static char tick; char t = step + tick; if (t >= 2) s = 1; if (t <= -2) s = -1; t -= s; t -= s; tick = t; } return s; } #endif // _DREHGEBER_H_ |
Was das Makro IS_SET macht sollte klar sein, aufgerufen wird drehgeber_job() in der PinChange ISR:
#include <inttypes.h> #include <avr/interrupt.h> #include "drehgeber.h" static int8_t volatile steps; // vom Drehgeber ... SIGNAL (SIG_PIN_CHANGE0) { steps += drehgeber_job(); } int main() { ... // Leeraufruf zum Initialisieren drehgeber_step(); ... } |
Datum:
>Im Programm gibt es nun Probleme, weil das Ding prellt. Ne "normale" >Entprellung kommt nicht in Frage, weil man ja keine Pulse verpassen >will. Macht man im TImerinterrupt alle 1 bzw. 10ms. Drehgeber: Beispielcode in C
Datum:
#ARGL# Hätt ich auch seber mal draufkommen können, das auszuprobieren... Reagiert im 10ms-Job zwar merklich langsamer als vorher, aber wenigstens zählt er nicht mehr falsch... EDIT und @ 2.5kHz ist's so wie ich's mir vorstelle :-) So einfach ist die Welt...
Datum:
auf alle Fälle mit 0,1 uf keramik c von den pulskontaten nach masse. das ist oft mehr als die halbe miete !!!
Datum:
Die Schaltung ist fertig und keinPlatz mehr... mit der Poll-per-IRQ klappt's ja prima und mit minimaler Hardware :-)
Datum:
Codevorschlag ohne Klimbim (für Encoder mit 2 Werten pro Rasterung im
polling):
neu= PORTB&0b.0000.0011; // einlesen der beiden Pins
if (alt!=neu)
{
// Auswertung der Richtung
// jede Richtung hat separaten Zähler
if(alt==0 && neu==1)zahler_down++;
if(alt==1 && neu==3)zahler_down++;
if(alt==3 && neu==2)zahler_down++;
if(alt==2 && neu==0)zahler_down++;
if(alt==0 && neu==2)zahler_up++;
if(alt==2 && neu==3)zahler_up++;
if(alt==3 && neu==1)zahler_up++;
if(alt==1 && neu==0)zahler_up++;
//wenn einer der Richtungszähler den Wert 2 hat
//wird er auf Null zurückgesetzt und der Hauptzähler bewegt
if(zahler_up == 2) {Hauptzahler++; zahler_up=0;}
if(zahler_down == 2) {Hauptzahler--; zahler_down=0;}
//zum Entprellen:wenn ein Zähler den Wert 1 erreicht
//wird die Gegenrichtung zurückgesetzt
if(zahler_up == 1) {zahler_down=0; }
if(zahler_down == 1) {zahler_up=0; }
alt=neu;
}
ich weiss der thread ist alt , ist bei google aber noch weit vorne wenn
man nach --Drehencoder entprellen-- sucht
Datum:
fantozzi schrieb: > Codevorschlag ohne Klimbim Also 13 IFs, das ist ne riesen Menge Klimbim. Der Code im obigen Link braucht kein einziges IF, der ist kurz und knackig (wenig Zyklen, wenig Flash). Peter
Datum:
Peter Dannegger schrieb: > Also 13 IFs, das ist ne riesen Menge Klimbim. Hat ja auch 3,5 Jahre gedauert, bis er fertig war.
Datum:
Dietmar Steiner schrieb: > auf alle Fälle mit 0,1 uf keramik c von den pulskontaten nach masse. > > das ist oft mehr als die halbe miete !!! Da der Thread offenbar bei der Suche noch so weit vorne ist: Oben genannten Tipp bitte unter keinsten Umständen machen. Das ist allergröbster Pfusch und zerstört nicht nur die Kontakte, sondern erzeugt auch noch extreme Störungen.