Debounced Rotory Encoder

Da von unseren Kunden in letzter Zeit immer wieder Fragen zur Implementierung des Drehimpulsgebers (digitales Poti) gestellt wurden möchten wir hier kurz eine Möglichkeit zeigen, ein sauberes Signal des Drehimpulsgebers mithilfe von Interrupts auszugeben. Hier im Beispiel am Seriellen Monitor:

Schaltung:

Stückliste:

 

Arduino Sketch:

/*
* Rotary Encoder connected to a Microcontroller, compatible with Arduino Uno R3
*
* Encoder Pins: CLK, DT, SW, +, GND
* The encoder contains two pull-up-resistors of 10k at CLK and DT
* All contacts are low-active
*
* Program based on software by Stefan Nikolaus
* https://www.nikolaus-lueneburg.de/2016/02/rotary-encoder/
* and important code written by rafbuff at http://playground.arduino.cc/Main/RotaryEncoders
* "Another Interrupt Library THAT REALLY WORKS (the Encoder interrupts the processor
* and debounces like there is no tomorrow)."
*
* Pins 2 and 3 are used because they support interrups !
* Debouncing works really great !!!
* Math.positive counting: DT on 3, CLK on 2
* Clockwise counting: DT on 2, CLK on 3
*
* Modifications:
* - deleted 'unprintable' characters, modified {} and TABs
* - added the button detection for pin 4 "SW"
* - added actionButton() and actionPosition(); here we can put down the
* code for further processing in our system.
*
* UKA 31.05.2018
*/


#define encoderPinA 2
#define encoderPinB 3
#define SW 4


volatile unsigned int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management

int button = LOW;
int old_button = LOW;

// interrupt service routine variables
boolean A_set = false;
boolean B_set = false;


void setup()
{
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);

pinMode( SW, INPUT_PULLUP );


digitalWrite(encoderPinA, HIGH); // turn on pullup resistors
digitalWrite(encoderPinB, HIGH); // turn on pullup resistors

attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)

Serial.begin(9600); // output to PC Serial Monitor

}// --------------------- setup --------------------------------



void loop()
{
rotating = true; // reset the debouncer

if (lastReportedPos != encoderPos)
{
actionPosition();
lastReportedPos = encoderPos;
}


button = !digitalRead( SW );

if( button != old_button )
{
actionButton();
delay( 10 );
old_button = button;
}

}// --------------------------- main loop -----------------------


void actionButton()
{
Serial.print("Button: ");
Serial.print ( button );
Serial.print (" | ");
Serial.println(encoderPos, DEC);
} // ------------------ actionButton --------------------------------


void actionPosition()
{
Serial.print("Position: ");
Serial.print(encoderPos, DEC);
Serial.print (" | ");
Serial.println ( button );
} // ------------------ actionPosition --------------------------------




// ------------- Interrupt Service Routines ------------------------------

// ISR Interrupt on A changing state (Increment position counter)
void doEncoderA()
{
if ( rotating ) delay (1); // wait a little until the bouncing is done
if( digitalRead(encoderPinA) != A_set ) // debounce once more
{
A_set = !A_set;
// adjust counter +1 if A leads B
if ( A_set && !B_set )
encoderPos += 1;
rotating = false; // no more debouncing until loop() hits again
}
}// ------------------- doEncoderA ----------------------------------------


// ISR Interrupt on B changing state, same as A above
void doEncoderB()
{
if ( rotating ) delay (1);
if( digitalRead(encoderPinB) != B_set )
{
B_set = !B_set;
//adjust counter -1 if B leads A
if( B_set && !A_set )
encoderPos -= 1;
rotating = false;
}
}// -------------------- doEncoderB --------------------------------------

Wir hoffen, dass Ihnen unser heutiger Blogbeitrag zur Lösung Ihres Problems und als Gedankenanstoß für Ihre Projekte weitergeholfen hat und wir freuen uns auf Ihre Kommentare. Bis zum nächsten Beitrag von AZ-Delivery, Ihrem Experten für Mikroelektronik!

 

1 Kommentar

Walter van Boer

Walter van Boer

/*

Walter van Boer 12.06.2018 Further modifications: - writing error: actionposition() actionbutton() in void loop() - should be actionPosition(), actionButton() - should be: if (A_set && !B_set) in ISR void doEncoderA() -This sketch works great!
*/

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert