___ _
_
_
_ ____
|_| |_|
|__________________________| |_| |_|
__
_________
|________________|
______
_____
|________________|
1 0 0
1 1 0
______
_____
|________________|
__
_________
|________________|
1 1 0
1 0 0
/*
* Auswertung eines Drehgebers mit "digitaler" Entprellung
* ... also ohne Kondensator oder delay(1)
* Der gemeinsame Kontakt am Drehgeber ist an Masse zu legen.
*
* Rückwärts
* ___ _ _ _ _ __________________________
* |_| |_| |__________________________| |_| |_|
* ____________________ _ _ _ _ ___
* |_| |_| |________________________________| |_| |_|
* 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1
* 1 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1
* # # # # # # # # # # # #
* 3 1 3 1 3 1 0 3 2 3 2 3
*
* Vorwärts
* ____________________ _ _ _ _ ___
* |_| |_| |________________________________| |_| |_|
* ___ _ _ _ _ __________________________
* |_| |_| |__________________________| |_| |_|
* 1 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1
* 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1
* # # # # # # # # # # # #
* 3 2 3 2 3 2 0 3 1 3 1 3
*
*
* D.Ahlgrimm 12.11.2016
*/
#define DR_INT0 2 // Pin2 für Interrupt 0
#define DR_INT1 3 // Pin3 für Interrupt 1
#define DR_BTN 4
// 0=00 (Schritt), 1=01 (rückwärts), 2=10 (vorwärts), 3=11 (Grundstellung)
volatile unsigned char dr_t=0;
volatile int dr_counter=0;
void dr(void) {
static unsigned char p;
switch(p=digitalRead(DR_INT0) | digitalRead(DR_INT1)<<1) {
case 0:
if(dr_t==1) {
dr_t=p;
dr_counter--;
} else if(dr_t==2) {
dr_t=p;
dr_counter++;
}
break;
case 1:
case 2:
if(dr_t==3) dr_t=p;
break;
case 3:
dr_t=p;
}
}
void setup() {
Serial.begin(115200);
pinMode(DR_INT0, INPUT_PULLUP);
pinMode(DR_INT1, INPUT_PULLUP);
pinMode(DR_BTN, INPUT_PULLUP);
attachInterrupt(0, dr, CHANGE);
attachInterrupt(1, dr, CHANGE);
}
void loop() {
static int cnt_old=-1, but_old=1;
if(digitalRead(DR_BTN)!=but_old) {
but_old=digitalRead(DR_BTN);
delay(2); // der Taster wird dann doch mittels Wartezeit entprellt
if(but_old==LOW) {
Serial.println("DN");
} else {
Serial.println("UP");
}
}
if(dr_counter!=cnt_old) {
cnt_old=dr_counter;
Serial.println(dr_counter, DEC);
}
}
Bei dieser Version wird der Drehgeber nur abgefragt, so lange der Taster am Drehgeber gedrückt gehalten wird.
/*
Auswertung eines Drehgebers mit "digitaler" Entprellung, Version 2
... also ohne Kondensator oder delay(1)
Der gemeinsame Kontakt am Drehgeber ist an Masse zu legen.
Rückwärts
___ _ _ _ _ __________________________
|_| |_| |__________________________| |_| |_|
____________________ _ _ _ _ ___
|_| |_| |________________________________| |_| |_|
1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1
1 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1
# # # # # # # # # # # #
3 1 3 1 3 1 0 3 2 3 2 3
Vorwärts
____________________ _ _ _ _ ___
|_| |_| |________________________________| |_| |_|
___ _ _ _ _ __________________________
|_| |_| |__________________________| |_| |_|
1 1 1 1 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1
1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1
# # # # # # # # # # # #
3 2 3 2 3 2 0 3 1 3 1 3
D.Ahlgrimm 13.11.2016
*/
#include <TimerOne.h>
#define DR_BTN 4
#define DR_P1 5
#define DR_P2 6
// 0=00 (Schritt), 1=01 (rückwärts), 2=10 (vorwärts), 3=11 (Grundstellung)
volatile unsigned char dr_t=0;
// Die Position des Drehgebers
volatile int dr_counter=0;
/* -----------------------------------------------------------------
Inkrementiert "dr_counter" bei der Folge 11-10-00 bzw.
dekrementiert "dr_counter" bei der Folge 11-01-00
an den Pins "DR_P1" und "DR_P2".
*/
void dr(void) {
static unsigned char p;
switch(p=digitalRead(DR_P1) | digitalRead(DR_P2)<<1) {
case 0: // Schritt erkannt
if(dr_t==1) { // wenn zuvor Rückwärts-Schritt
dr_t=p; // merken
dr_counter--; // und Schritt ausführen
} else if(dr_t==2) { // wenn zuvor Vorwärts-Schritt
dr_t=p; // merken
dr_counter++; // und Schritt ausführen
} // sonst nix bzw. ignorieren
break;
case 1: // rückwärts
case 2: // vorwärts
if(dr_t==3) dr_t=p; // wenn zuvor Grundstellung -> Richtung merken
break;
case 3: // Grundstellung
dr_t=p; // unbedingt merken
}
}
/* -----------------------------------------------------------------
Liefert den entprellten Zustand des Tasters "DR_BTN".
*/
char buttonDebounce(void) {
char last_but=digitalRead(DR_BTN), cnt=0;
// Schleife erst verlassen, wenn 10x in Folge der selbe Wert gelesen wurde
while(cnt<10) {
if(last_but==digitalRead(DR_BTN)) {
cnt++;
} else {
cnt=0;
last_but=digitalRead(DR_BTN);
}
delayMicroseconds(10);
}
return(last_but);
}
/* -----------------------------------------------------------------
*/
void setup() {
Serial.begin(115200);
pinMode(DR_BTN, INPUT_PULLUP);
pinMode(DR_P1, INPUT_PULLUP);
pinMode(DR_P2, INPUT_PULLUP);
Timer1.initialize(1000); // 1x pro Millisekunde
Timer1.attachInterrupt(dr);
Timer1.stop();
}
/* -----------------------------------------------------------------
Main
*/
void loop() {
static int cnt_old=0;
static char but_old=1, but_new;
but_new=buttonDebounce();
if(but_old!=but_new) {
but_old=but_new;
if(but_old==LOW) {
Serial.println("DN");
Timer1.start();
} else {
Serial.println("UP");
Timer1.stop();
}
}
if(dr_counter!=cnt_old) {
cnt_old=dr_counter;
Serial.println(dr_counter, DEC);
}
}
DN
1
2
3
4
5
6
5
4
3
2
1
0
-1
UP
DN
-2
-3
-4
-5
-4
-3
-2
-1
0
1
2
UP
_____________ _ _
|_| |_| |__
___ _ _
|_| |_| |____________
1 1 1 1 1 1 0
1 0 1 0 1 0 0
3 2 3 2 3 2 0 -> Normal-Fall ohne
Überlappung
_____________ _ _
|_| |_| |__
_____ _ _
|_| |_| |____________
1 1 1 1 1 0 1 0
1 0 1 0 1 0 0 0
3 2 3 1 3 0 2 0
-> direkter Übergang
_____________ _ _
|_| |_| |__
_______ _ _
|_| |_| |____________
1 1 1 1 0 1 0
1 0 1 0 1 0 0
3 2 3 2 1
2 0 -> halbe Überlappung
_____________ _ _
|_| |_| |__
_________ _ _
|_| |_|
|____________
1 1 1 0 1 0 1 0
1 0 1 0 1 0 0 0
3 2 3 0
3 0 2 0 -> volle
Überlappung
Schief gehen könnte was, wenn zusätzlich noch die Anzahl der
Prellungen oder deren einzelne Dauer bei den Signalen
unterschiedlich ausfiele:_______ _
|_| |______
___ _ _
|_| |_| |______
1 1 1 0 1 0
1 0 1 0 1 0
3 2 3 0 3 0 -> kein Schritt erkannt
_________ _
|___| |__
___ ___
|___| |______
1 1 1 1 0 0
1 0 0 1 1 0
3 2 2 3 1 0 -> falsche Richtung erkannt