Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Program reads rotary encoder correctly without bouncing in this code:

int val = 0;
byte clkPin = 3;
byte dtPin = 2;
bool lastClk;
bool lastDt;
void setup() {
  pinMode(clkPin,INPUT);
  pinMode(dtPin,INPUT);
  lastClk = digitalRead(3);
  lastDt = digitalRead(2);
  val = 0;
  attachInterrupt(digitalPinToInterrupt(clkPin), clkRise, RISING);
  Serial.begin(9600);
}

void loop() {
}

void clkRise(){
      lastClk = HIGH;
      lastDt = digitalRead(dtPin);
      if(lastDt == LOW){
        val--;
        Serial.println(val);
        }  else{val++; Serial.println(val);}
        }

but when i use lcd to show the result, i get massive bounces (i think) in this code:

#include <LiquidCrystal_I2C.h>

#include <Wire.h>

LiquidCrystal_I2C lcd(0x27,20,4);
int val = 0;
byte clkPin = 3;
byte dtPin = 2;
bool lastClk;
bool lastDt;
void setup() {
  lcd.begin();
  pinMode(clkPin,INPUT);
  pinMode(dtPin,INPUT);
  lastClk = digitalRead(3);
  lastDt = digitalRead(2);
  val = 0;
  attachInterrupt(digitalPinToInterrupt(clkPin), clkRise, RISING);
  Serial.begin(9600);
  lcd.home();
}

void loop() {
  lcd.print(val);
}

void clkRise(){
      lastClk = HIGH;
      lastDt = digitalRead(dtPin);
      if(lastDt == LOW){
        val--;
        Serial.println(val);
        }  else{val++;}
        }

it increases and decreases by random numbers between 0-5.I use KY-040 R.E. it has built-in 10k pull up resistors.

This is what i use to debounce:

A or B pin of R.E--10k R----------------------------------Arduino INPUT PIN
                         |
                         |
                         =0.1uF C
                         |
                         ---------------------GND
share|improve this question
    
Try adding a slight delay after lcd.print(val);. Something like delay(50);. Also, if the R.E. has in internal pull-up of 10k, the series resistor between the A/B pin should be lower than 10k. Otherwise the maximum voltage is only 2.5V (Vcc/2). – Gerben Mar 19 at 15:27
    
@Gerben i tried delaying, it works better but there are still big jumps like 3-4+ – Çay Öncesi Mar 19 at 16:04
    
Either increase the delay, or only do the lcd.print if the value of val has changed. – Gerben Mar 19 at 16:13
    
@Gerben it work way better now, but there are still rare jumps. would a schmitt trigger fix this? I took off the 10k resistor that i placed. – Çay Öncesi Mar 19 at 16:24
    
I don't know. That's not my area of expertise. – Gerben Mar 19 at 16:36
up vote 0 down vote accepted

I suspect the problem is that your hardware-debounce capacitive circuit isn't working well enough to accurately debounce the contacts, and that invalid transitions are occurring on the quadrature lines as read by the program.

Note that use of Serial.println() within your clkRise() interrupt handler is problematic, because Serial.println() uses interrupts itself. As far as I know, println() is not reentrant, ie cannot be used correctly from the multiple interrupts that may start before previous println() calls finish their background processing. The bits of extra delay introduced by LCD code may merely be exposing a problem.

There is no need for either hardware or software debouncing on quadrature inputs. A correctly-implemented state machine will reject invalid conditions that arise during bounce, or will immediately follow any extra up-tick by a corresponding down-tick, or vice versa.

For some state machine code, see for example answer 16420/3917 and also see answer 18221/3917. Also see answer 19109/3917.

share|improve this answer
    
Çay Öncesi should definitely not be doing Serial.println inside an ISR. – Nick Gammon Mar 20 at 3:15
    
@NickGammon alright. I finished my project. just curious, what is the outcome of placing Serial.println inside an ISR? – Çay Öncesi Mar 21 at 15:21
    
Serial.print puts whatever-it-is you want to print into a buffer. It then waits for interrupts to empty the buffer. If the buffer is full already, it waits before putting data into the buffer. Since the buffer won't be emptied inside an ISR, if the serial buffer is full, the program will then block indefinitely. – Nick Gammon Mar 21 at 19:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.