Pages: [1] 2   Go Down
Author Topic: Rotary encoder, messy signal?  (Read 3096 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm using a rotary encoder to set a variable to a certain number. It's counting up and down depending on which way it's turning.

This work fine for the most part, except every now and then it either goes up two numbers at once, or go back one and forward one instead of just one forward. I copied the code from the arduino examples, and I've used several different sets of code to make sure the code is not the problem.

My guess is the signal coming from the A and B pins is not 100% 'digital' and it has some noise which causes the interrupt to see two changes when there really only was one.

Does that sound logical and is there a remedy?

Thanks a lot,
Harry

p.s. here is some of the code I'm using:

--
#define encoder0PinA 2  //interrupt 0 on pin 2
#define encoder0PinB 4
volatile int encoder0Pos = 0;
--

-- 
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinA, HIGH);         // turn on pullup resistor
  digitalWrite(encoder0PinB, HIGH);         // turn on pullup resistor
  attachInterrupt(0, doEncoder0, CHANGE);   // encoder interrupt 0 on pin 2
--

--
void doEncoder0() {
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {encoder0Pos--;}
  else {encoder0Pos++;}

  Serial.println(encoder0Pos, DEC);
}
--
« Last Edit: February 23, 2011, 06:23:10 am by harryvermeulen » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 604
Posts: 33448
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

These are classic symptoms of either contact bounce or not servicing the interrupt fast enough. Is it a contact encoder or is it optical? Have you got any capacitors on the input?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Please post the whole code (using the # button to provide right tags) as the snippets don't provide enough insight
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the quick replies!

I'm at home right now, so I'll post the code and more information about the encoder tomorrow when I get to work.

Right now there are no capacitors in the circuit. The A and B pins are connected to a 'high' input pin with the internal pull-up resistor and the common is directly connected to the ground.

I think the encoder is a contact encoder, but I'll have to check to make sure tomorrow. There's really nothing in my interrupt, except handling the encoder change and printing the new value to the serial port, which I imagine should be fine.

The contact bounce theory sounds very plausible, and after reading: http://www.elexp.com/t_bounc.htm I'm wondering if there's a way to fix it software based on the arduino? I know the delay function doesn't work within interrupts. Any common software solutions against contact bounce? Otherwise I'll have to go to town and get some capacitors. At least there's a fix! smiley

Posting more info tomorrow. Thanks again!
Harry

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm wondering if there's a way to fix it software based on the arduino?

Hey Harry,

I had the same problem with rotary encoder bouncing. I found a website which explains rotary encoders pretty good and has some software debouncing in the source code: http://www.pavius.net/articles/development/81-rotary-encoder-based-cooking-timer
It's not Arduino specific, but it is not very hard to port to Arduino.

Best regards,

Harald (<-- almost the same as Harry smiley-wink)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Alright, I'll go have a look at that!

This is the encoder I got: http://uk.farnell.com/alps/ec11b15242/encoder-rotary-11mm-switch/dp/1191733?Ntt=1191733

And here's my code: (some of it is commented out, since I haven't connected those electronic parts yet).
Code:
/* read a rotary encoder with interrupts
   Encoder hooked up with common to GROUND,
   encoder0PinA to pin 2, encoder0PinB to pin 4 (or pin 3 see below)
   it doesn't matter which encoder pin you use for A or B 

   uses Arduino pullups on A & B channel outputs
   turning on the pullups saves having to hook up resistors
   to the A & B channel outputs

*/

#define max_category 22
#define max_age 99

//encoder0
#define encoder0PinA 2  //interrupt 0 on pin 2
#define encoder0PinB 4

//encoder1
//#define encoder1PinA 3  //interrupt 1 on pin 3
//#define encoder1PinB 5

//rocker0
#define rocker0Pin 21   //interrupt 2 on pin 21

//keySwitch0
#define keySwitch0Pin 20 //interrupt 3 on pin 20

//button0
#define scanButtonPin 19 //interrupt 4 on pin 19
#define scanLedPin 6
#define scanTimeOut 3000

//button1
#define deleteButtonPin 18 //interrupt 5 on pin 18

//segment0
#define segment0PinA 43
#define segment0PinB 45
#define segment0PinC 27
#define segment0PinD 25
#define segment0PinE 23
#define segment0PinF 41
#define segment0PinG 39
#define segment0PinDP 29
int segment0Pins[8] = {
                        segment0PinA,
                        segment0PinB,
                        segment0PinC,
                        segment0PinD,
                        segment0PinE,
                        segment0PinF,
                        segment0PinG,
                        segment0PinDP
                      };

//segment1
#define segment1PinA 51
#define segment1PinB 53
#define segment1PinC 35
#define segment1PinD 33
#define segment1PinE 31
#define segment1PinF 49
#define segment1PinG 47
#define segment1PinDP 37
int segment1Pins[8] = {
                        segment1PinA,
                        segment1PinB,
                        segment1PinC,
                        segment1PinD,
                        segment1PinE,
                        segment1PinF,
                        segment1PinG,
                        segment1PinDP
                      };

/*
//segment2
#define segment2Pin1 38
#define segment2Pin2 39
#define segment2Pin3 40
#define segment2Pin4 41
#define segment2Pin5 42
#define segment2Pin6 43
#define segment2Pin7 44
#define segment2Pin8 45

//segment3
#define segment3Pin1 46
#define segment3Pin2 47
#define segment3Pin3 48
#define segment3Pin4 49
#define segment3Pin5 50
#define segment3Pin6 51
#define segment3Pin7 52
#define segment3Pin8 53
*/

//inverse
byte seven_seg_digits[10][7] = {
                                { 0,0,0,0,0,0,1 },  // = 0
                                { 1,0,0,1,1,1,1 },  // = 1
                                { 0,0,1,0,0,1,0 },  // = 2
                                { 0,0,0,0,1,1,0 },  // = 3
                                { 1,0,0,1,1,0,0 },  // = 4
                                { 0,1,0,0,1,0,0 },  // = 5
                                { 0,1,0,0,0,0,0 },  // = 6
                                { 0,0,0,1,1,1,1 },  // = 7
                                { 0,0,0,0,0,0,0 },  // = 8
                                { 0,0,0,1,1,0,0 }   // = 9
                               };

volatile int encoder0Pos = 0;
volatile int encoder1Pos = 0;
volatile boolean rocker0Pos;
volatile boolean keySwitch0Pos;
volatile int fixCounter = 0;

void setup() {
  //input / output
  setupEncoders();
  setupRocker();
  setup7Segments();
  setupScanButton();
  setupKeySwitch();
  setupDeleteButton();
 
  //serial connection
  Serial.begin(9600);
}

void setupEncoders() {
  //encoder0
  pinMode(encoder0PinA, INPUT);
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinA, HIGH);         // turn on pullup resistor
  digitalWrite(encoder0PinB, HIGH);         // turn on pullup resistor
  attachInterrupt(0, doEncoder0, CHANGE);   // encoder interrupt 0 on pin 2
 
  /*
  //encoder1
  pinMode(encoder1PinA, INPUT);
  pinMode(encoder1PinB, INPUT);
  digitalWrite(encoder1PinA, HIGH);         // turn on pullup resistor
  digitalWrite(encoder1PinB, HIGH);         // turn on pullup resistor
  attachInterrupt(1, doEncoder1, CHANGE);   // encoder interrupt 1 on pin 3
  */
}

void setupRocker() {
  //rocker0
  pinMode(rocker0Pin, INPUT);
  digitalWrite(rocker0Pin, HIGH);           // turn on pullup resistor
  attachInterrupt(2, doRocker0, CHANGE);    // rocker interrupt 2 on pin 21
  rocker0Pos = digitalRead(rocker0Pin);     // can we do this here already? need to test it.
}

void setup7Segments() {
  for(int i = 0; i < 8; i++) {
    pinMode(segment0Pins[i], OUTPUT);
  }
  for(int i = 0; i < 8; i++) {
    pinMode(segment1Pins[i], OUTPUT);
  }   

  disableDots();  // start with the "dot" off
}

void setupScanButton() {
  pinMode(scanButtonPin, INPUT);
  digitalWrite(scanButtonPin, HIGH);
  pinMode(scanLedPin, OUTPUT);
  digitalWrite(scanLedPin, HIGH);
}

void setupKeySwitch() {
  pinMode(keySwitch0Pin, INPUT);
  digitalWrite(keySwitch0Pin, HIGH);           // turn on pullup resistor
  attachInterrupt(3, doKeySwitch, CHANGE);    // rocker interrupt 2 on pin 21
  keySwitch0Pos = digitalRead(keySwitch0Pin);     // can we do this here already? need to test it.
}

void setupDeleteButton() {
  pinMode(deleteButtonPin, INPUT);
  digitalWrite(deleteButtonPin, HIGH);
  attachInterrupt(5, doDeleteButton, FALLING);
}

void loop(){
  if(digitalRead(scanButtonPin) == LOW) {
    Serial.println("scanButtonPushed!");
    digitalWrite(scanLedPin, LOW);
    delay(scanTimeOut);
    digitalWrite(scanLedPin, HIGH);
  }
 
  delay(10);
  if(fixCounter < 100) { fixCounter++; }
 
}

//category
void doEncoder0() {
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {encoder0Pos--;}
  else {encoder0Pos++;}
 
  if(encoder0Pos < 0) {encoder0Pos = max_category;}
  if(encoder0Pos > max_category) {encoder0Pos = 0;}

  Serial.println(encoder0Pos, DEC);
  displayCategory(encoder0Pos);
}

//age
/*
void doEncoder1() {
  if (digitalRead(encoder1PinA) == digitalRead(encoder1PinB)) {encoder1Pos++;}
  else {encoder1Pos--;}
 
  if(encoder1Pos < 1) {encoder1Pos = max_age;}
  if(encoder1Pos > max_age) {encoder1Pos = 1;}
 
  Serial.println(encoder1Pos, DEC);
  displayAge(encoder1Pos);
}
*/

//gender
void doRocker0() {
  rocker0Pos = digitalRead(rocker0Pin);
  Serial.println(rocker0Pos, DEC);
}

//delete lock
void doKeySwitch() {
  keySwitch0Pos = digitalRead(keySwitch0Pin);
}

//delete
void doDeleteButton() {
  if(!keySwitch0Pos) {
    Serial.println("delete");
  }
}

void disableDots() {
  digitalWrite(segment0PinDP, HIGH);
  digitalWrite(segment1PinDP, HIGH);
  //digitalWrite(segment2PinDP, LOW);
  //digitalWrite(segment3PinDP, LOW);
}

void displayCategory(int category) {
  int firstNumber = floor(category / 10);
  int secondNumber = category % 10;
  sevenSegWrite(0, firstNumber);
  sevenSegWrite(1, secondNumber);
}

/*
void displayAge(int age) {
  int firstNumber = floor(age / 10);
  int secondNumber = age % 10;
  sevenSegWrite(2, firstNumber);
  sevenSegWrite(3, secondNumber); 
}
*/
 
void sevenSegWrite(int segment, byte digit) {
  switch(segment) {
    case 0:
      for(byte segCount = 0; segCount < 7; ++segCount) {
        digitalWrite(segment0Pins[segCount], seven_seg_digits[digit][segCount]);
      }
      break;
    case 1:
      for(byte segCount = 0; segCount < 7; ++segCount) {
        digitalWrite(segment1Pins[segCount], seven_seg_digits[digit][segCount]);
      }
      break;
  }
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's the code in the previously mentioned example about the encoder de-bouncing, but to be honest I have no clue what's going on there, hehe.

Code:
#include "sysdef.h"
#include "sys.h"
#include "quadenc_prv.h"

// ==========================================================================
// init

void quadenc_init(void)
{
// init locals
quadenc_channel0SearchPattern = 0;
quadenc_channel1SearchPattern = 0;
quadenc_channel0Status = 0xFF;
quadenc_channel1Status = 0xFF;
quadenc_buttonStatus = 0xFF;
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
quadenc_changeCounts = 0;
}
// ==========================================================================
// get last number of counts

void quadenc_getLastChangeCount(int_8 *counts)
{
// disable interrupts
// sys_disableInterrupts();

// get how many counts changed since last poll
*counts += quadenc_changeCounts;

// zero it out
quadenc_changeCounts = 0;

// enable interrupts
// sys_enableInterrupts();
}
// ==========================================================================
// ISR

void quadenc_isr(void)
{
//
// Debounce channel 0
//

// shift channel0 value into status. Save only N bits history
quadenc_channel0Status = ((quadenc_channel0Status << 1) | RB0) & 0x7;

// do lower 3 bits match search pattern?
if (quadenc_channel0Status == quadenc_channel0SearchPattern)
{
// change search pattern
quadenc_channel0SearchPattern = ((~quadenc_channel0SearchPattern) & 0x7);

// declare debounced transition
quadenc_transitionEvent = quadenc_channel0Status;
}

//
// Debounce channel 1
//

// shift channel0 value into status. Save only N bits history
quadenc_channel1Status = ((quadenc_channel1Status << 1) | RB1) & 0x7;

// do lower 3 bits match search pattern?
if (quadenc_channel1Status == quadenc_channel1SearchPattern)
{
// change search pattern
quadenc_channel1SearchPattern = ((~quadenc_channel1SearchPattern) & 0x7);

// declare debounced transition
quadenc_transitionEvent = (quadenc_channel1Status | (1 << 3));
}

//
// Check if transition forms an acceptable movement
//

// check if a transition occured
if (quadenc_transitionEvent != QUADENC_NO_TRANSITION_EVENT)
{
//
// Idle state
//
if (quadenc_state == QUADENC_STATE_IDLE)
{
// first value of CW transition?
if (quadenc_transitionEvent == quadenc_cwTransitions[0])
{
// yup - enter state
quadenc_state = QUADENC_STATE_DETECTING_CW;

// next transition
quadenc_transitionEventIndex++;
}
// first value of CCW transition?
else if (quadenc_transitionEvent == quadenc_ccwTransitions[0])
{
// yup - enter state
quadenc_state = QUADENC_STATE_DETECTING_CCW;

// next transition
quadenc_transitionEventIndex++;
}
}
//
// CW state
//
else if (quadenc_state == QUADENC_STATE_DETECTING_CW)
{
// found next expected transition?
if (quadenc_transitionEvent == quadenc_cwTransitions[quadenc_transitionEventIndex])
{
// increment it
quadenc_transitionEventIndex++;

// are we done?
if (quadenc_transitionEventIndex == 4)
{
// decrement count
quadenc_changeCounts++;

// back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
else
{
// incorrect transition, back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
//
// CCW state
//
else if (quadenc_state == QUADENC_STATE_DETECTING_CCW)
{
// found next expected transition?
if (quadenc_transitionEvent == quadenc_ccwTransitions[quadenc_transitionEventIndex])
{
// increment it
quadenc_transitionEventIndex++;

// are we done?
if (quadenc_transitionEventIndex == 4)
{
// increment count
quadenc_changeCounts--;

// back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}
else
{
// incorrect transition, back to idle
quadenc_state = QUADENC_STATE_IDLE;
quadenc_transitionEventIndex = 0;
}
}

// zero out transition
quadenc_transitionEvent = QUADENC_NO_TRANSITION_EVENT;
}
}


I can see he's checking for a 'search pattern', but I don't understand what that is or how he's forming one. (after reading the tutorial I do understand what it is, but I'm still unsure how to form and use one in the arduino).

Code:
// change search pattern
quadenc_channel0SearchPattern = ((~quadenc_channel0SearchPattern) & 0x7);


There's also a de-bounce example on the arduino website:

Code:
/*
 Debounce
 
 Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 a minimum delay between toggles to debounce the circuit (i.e. to ignore
 noise). 
 
 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached from pin 2 to +5V
 * 10K resistor attached from pin 2 to ground
 
 * Note: On most Arduino boards, there is already an LED on the board
 connected to pin 13, so you don't need any extra components for this example.
 
 
 created 21 November 2006
 by David A. Mellis
 modified 3 Jul 2009
 by Limor Fried
 
This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Debounce
 */

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise: 

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
 
  // set the LED using the state of the button:
  digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

But that's running in the loop() and can use millis() to keep track of time, which I think doesn't work in interrupts either.
« Last Edit: February 23, 2011, 10:52:52 pm by harryvermeulen » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 604
Posts: 33448
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Forget a software solution, that only masks the problem and reduces the maximum speed. This is the way to do it:-



You can miss out the 74LS74 if you want to use the software to sort things out, but the capacitors are a must and the schimitt buffers help as well.
« Last Edit: February 25, 2011, 05:26:08 pm by Grumpy_Mike » Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 28
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Notwithstanding the sledgehammer-to-crack-a-walnut approach above, have a look at the code here

http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino

It is a beautifully simple, elegant and very fast way of reading an encoder that will catch errors that you describe.

With respect to your code, it's considered good practise to make your interrupt routines as small and fast as possible - this means you should just update the position counter and get out. The other stuff (roll-over), serial.printing and displayAge (which is itself not a fast function) is best done outside the interrupt routine.

Code:
void doEncoder1() {
  if (digitalRead(encoder1PinA) == digitalRead(encoder1PinB)) {encoder1Pos++;}
  else {encoder1Pos--;}
 
  if(encoder1Pos < 1) {encoder1Pos = max_age;}
  if(encoder1Pos > max_age) {encoder1Pos = 1;}
 
  Serial.println(encoder1Pos, DEC);
  displayAge(encoder1Pos);
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great! I got it working nicely using the software solution. That's quite a nifty way of checking for bounces smiley

For some reason it's counting two numbers instead of one per click, but it's constant and reliable, not random like before. I'm just dividing the number by 2 and then it all seems to work.

Thanks a lot for the help! I really appreciate it.

Harry

Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 604
Posts: 33448
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For some reason it's counting two numbers instead of one per click, but it's constant and reliable,
That is what it is supposed to do, look at the signal translations for a click, you count when it goes high and again when it is low.
Logged

Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I solved the problem using a 2 ms delay between the interrupt and the moment I digitalRead the pins.
Since you cannot use a delay() in an interrupt service routine i did it simply by addressing a new function:

In setup:
attachInterrupt(0, onderbreking, FALLING);  // Interrupt 0 on pin 2

In the main loop:

void onderbreking()  {
  encode();
}

void encode() {
  delay(2);
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB))
    encoder = 2;   // clockwise
    else
    encoder = 1;   // counterclockwise
}
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you try that code on a real Arduino? I doubt if it works because the delay is still in the interrupt routine.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Anchorage, AK
Offline Offline
Edison Member
*
Karma: 42
Posts: 1176
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

LOL, nice try Arthur, but calling delay() from a function called by an ISR is no different than using delay() in the ISR directly.  The code path is the same (except for a little additional overhead for setting up before and tearing down after the jump.)  smiley-wink

I know some people prefer software debounce, but personally I agree it's a band-aid to the real problem.  Grumpy's solution is solid engineering and is going directly into my stash, but it is a lot of parts for a simple project input.  OP, have you tried the caps-n-resistors approach?
Logged

0
Offline Offline
Shannon Member
****
Karma: 201
Posts: 11744
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With a quadrature signal so long as only the changing signal has bounce (not both at once), the
accounting can be exact and no debouncing is needed - the counter will oscillate between two
neighbouring readings, but you just arrange to ignore 1 bit changes in the rest of the code.

You must handle CHANGE interrupts on at least one of the signals to see enough transitions to
prevent misaccounting due to bounce.  For full resolution you'd handle CHANGE on both signals
and the ISR would give full resolution (4 steps per quadrature cycle).

With a mechanical switch it is possible for both sets of contacts to be dirty and glitch at the same
time, in which case quadrature assumption is broken and the hardware filtering method will probably
get better results by removing the high frequency noise preferentially.   If also means the ISR won't
be called dozens of times on each transition which can only help.
Logged

[ I won't respond to messages, use the forum please ]

Pages: [1] 2   Go Up
Jump to: