In Anlehnung an den hochkompakten Tastatur-Abfrage-Code von Peter Dannegger habe ich mir etwas überlegt um mehrere Drehgeber (vielfaches von 8) auslesen und verarbeiten zu können. Dieser Code ist erstmal nur ein Grundgerüst welches ich mangels Drehgeber (habe gerade keine 8/16/24/32 Drehegeber zur Hand :-)) noch nicht testen konnte. Die eigentliche Drehgeber-Routine verwende ich (in leicht veränderter Form) in einem meiner Projekte und stammt z.T. aus der Code-Beschreibung von Peter Dannegers Drehgeber-Routine (wobei die von Peter noch deutlich kompakter ist als meine Lösung, da ich die Eingänge entprelle, in einen Gray-Wert konvertiere und mit dem aktuellen und dem letzten Gray-Wert ein Increment bzw Decrement einer Variablen auslöse). Auf Basis dieser Vorgehensweise (und weil ich so fasziniert von der Byte-Weisen verarbeitung des Tastatur-Ports in PeDa's Code-Beispiel war) habe ich diesen Code geschrieben. Damit kann ein vielfaches von 8 Drehgebern ausgelesen werden. Die Anpassung an die jeweilige Hardware (wie die Port-Pins eingelesen werden ist der Drehgeber Routine eig. egal, es muß nur eine möglichkeit geben einen Port X für die 8 A und 8 B Pins auswählen zu können sofern mehr als 8 Drehgeber angeschlossen sind) passiert nur in dem Makro ENC_A und ENC_B. Mit ENC_BYTES wird bestimmt wieviele Drehgeber-Ports vorhanden sind (wie gesagt : wie die ports ausgelesen werden ist zweitrangig, da je nach hardware die ports per SPI, I2C, Parallel oder sonstwie angebunden sein können). Zur Funktionsweise : Über die Makros ENC_A und ENC_B wird der aktuelle zustand eines Ports für die A und B Pins des Drehgebers ausgelesen. In jeweils 3 Variablen für A und B werden die letzten 3 Werte gespeichert. Über eine UND-Verknüpfung wird die positive oder negative Flanke erkannt (entprellen). Aus dem Entprellten A und B Signal wird der Gray-Code gebildet. Mit dem letzten und dem aktuellen Gray-Wert wird ein Inkrement-Puls und ein Richtungs-Puls berechnet. Diese beiden Pulse verändern letztendlich den Inhalt der Drehgeber Variablen. Ich hoffe das mal jemand über den Code drüberschauen kann und bei gelegenheit auch mal testen kann (sofern ich entsprechend Drehgeber habe werde ich dies auch mal tun und ggf code änderungen hier posten).
Hallo Rene, gibt es Neuigkeiten in Deinem Projekt? Das ist genau das, was ich suche. Allerdings reicht mit eine Version, in der nur so viele Drehgeber angeschlossen sind, wie Eingabepins vorhanden sind. Ich habe die Originalversion von Peter für einen Drehgeber am laufen und bin begeistert. Jetzt suche ich nach einer Version für 3-4 Drehgeber. Zum Einsatz kommt aktuell ein Attiny 2313, später vielleicht ein ATMega8. Gruß Marc
Marc Höner schrieb: > Jetzt suche ich nach einer Version für 3-4 Drehgeber. Schreibste eben die Funktion 4-mal in den Interrupthandler, jeweils mit anderen Pins und Variablen. Peter
Danke für den Tipp, werde ich versuchen. Bin aber gerade auf ein anderes Problem gestossen. Ich habe einfach ein neues Projekt erstellt und den Quelltext hineinkopiert. Wenn ich jetzt den gleichen Quelltext kompiliere, bekomme ich folgende Warnmeldung: "c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:85:3: warning: #warning "F_CPU not defined for <util/delay.h>"" Wieso bekomme ich die bei der Kopie und nicht beim Original? Was muss ich tun um die Warnung zu vermeiden? Gruß Marc
Marc Höner schrieb: > Wieso bekomme ich die bei der Kopie und nicht beim Original? Darum: > Ich habe einfach ein neues Projekt erstellt > Was muss ich tun um die Warnung zu vermeiden? Gib in deinem neuen Projekt einfach auch eine F_CPU an.
Dumme Frage, was ist eine F_CPU, die Quarzfrequenz? Gruß Marc
Jups Zu deiner Frage. Habe es mangels Drehgebern (und passendem Projekt) noch nicht getestet. Habe zwar ein projekt dazu im Kopf, aber momentan keine Lust und kein Geld 22 Drehgeber und 5 Displays für meinen Synthesizer zusammenzuschrauben :-) Wäre dankbar wenn jemand den Code mal testen könnte. Für Fragen und Feedback bin ich jederzeit offen.
Hallo Peter und natürlich auch alle anderen, so richtig komme ich nicht weiter. Ich habe jetzt alle aus meiner Sicht notwendigen Teile kopiert und mit anderen PINs und Variablen versehen. Leider funktioniert nur ein Drehgeber. Beim anderen geht eine LED an und nichts weiter. Hier der Code: #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> // target: ATTiny2313 //---------------------------------------------------------------------- -- #define XTAL 8e6 // 8MHz #define PHASE_A (PIND & 1<<PD0) #define PHASE_B (PIND & 1<<PD1) #define PHASE_C (PIND & 1<<PD3) #define PHASE_D (PIND & 1<<PD4) #define LEDS_DDR DDRB #define LEDS PORTB // LEDs against VCC volatile int8_t enc_delta_1, enc_delta_2; // -128 ... 127 static int8_t last_1, last_2; void encode_init( void ) { int8_t new_1, new_2; new_1 = 0; new_2 = 0; if( PHASE_A ) new_1 = 3; if( PHASE_B ) new_1 ^= 1; // convert gray to binary last_1 = new_1; // power on state enc_delta_1 = 0; if( PHASE_C ) new_2 = 3; if( PHASE_D ) new_2 ^= 1; // convert gray to binary last_2 = new_2; // power on state enc_delta_2 = 0; TCCR1B = (1<<WGM12) | (1<<CS11) | (1<<CS10); // CTC, XTAL / 64 OCR1A = (uint16_t)(XTAL / 64.0 * 1e-3 - 0.5); // 1ms TIMSK |= 1<<OCIE1A; } ISR( TIMER1_COMPA_vect ) // 1ms for manual movement { int8_t neu_1, neu_2, diff_1, diff_2; neu_1 = 0; if( PHASE_A ) neu_1 = 3; if( PHASE_B ) neu_1 ^= 1; // convert gray to binary diff_1 = last_1 - neu_1; // difference last - new if( diff_1 & 1 ){ // bit 0 = value (1) last_1 = neu_1; // store new as next last enc_delta_1 += (diff_1 & 2) - 1; // bit 1 = direction (+/-) } neu_2 = 0; if( PHASE_C ) neu_2 = 3; if( PHASE_D ) neu_2 ^= 1; // convert gray to binary diff_2 = last_2 - neu_2; // difference last - new if( diff_2 & 2 ){ // bit 0 = value (1) last_2 = neu_2; // store new as next last enc_delta_2 += (diff_2 & 2) - 1; // bit 1 = direction (+/-) } } int8_t encode_read_1( void ) // read two step encoders { int8_t val; cli(); val = enc_delta_1; enc_delta_1 = val & 1; sei(); return val >> 1; } int8_t encode_read_2( void ) // read two step encoders { int8_t val; cli(); val = enc_delta_2; enc_delta_2 = val & 1; sei(); return val >> 1; } int main( void ) { int8_t richt_1, richt_2, cnt_1, cnt_2, cnt; cnt = 80; cnt_1 = 0; cnt_2 = 0; PORTD = 0xFF; DDRD = 0x00; LEDS_DDR = 0xFF; LEDS = 0x0F; encode_init(); sei(); for(;;){ richt_1 = encode_read_1(); richt_2 = encode_read_2(); if (richt_1 > 0) { LEDS = 0b00001011; cnt_1 = cnt; } else if (richt_1 < 0) { LEDS = 0b00000111; cnt_1 = cnt; } else if (richt_2 > 0) { LEDS = 0b00001110; cnt_2 = cnt; } else if (richt_2 < 0) { LEDS = 0b00001101; cnt_2 = cnt; } if (cnt_1 >0) cnt_1--; if (cnt_2 >0) cnt_1--; if (cnt_1 == 0) LEDS |= 0b00001100; if (cnt_2 == 0) LEDS |= 0b00000011; _delay_ms(1); } } Hat einer eine Idee? Gruß Marc
Hat sich erledigt, habe meine Tippfehler gefunden. Gruß Marc
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.