Encoder + button. Button needs to be pressed AND rotated

Hi all.

I have a problem in my code. In general, I want to create a menu using 16x2 LCD screen and encoder with button. At first, I struggled with keeping the signal on encoder clear. I didn't want to use delay() function, but eventually I gave up. But than, out of the blue, the button stopped working properly. Arduino only detects it's LOW state when you press the button and rotate it. Of course it's not how I want it - I would like it to be just a simple 'click!' It was working before the delay(20). My simplified code:

void loop() {
  aState = digitalRead(PinA);
  if (aState != aLastState){     
          if (digitalRead(PinB) != aState) {counter++;}
     }
   
          switch(counter) {//menu}   
    aLastState = aState;
   delay(20); //after adding this, the button stopped working properly.

   buttonState = digitalRead(Button);
   
     if (buttonState == LOW) {
       	//some function from menu
	while (digitalRead(Button) == HIGH) {//waiting for button to be pressed again to go back}
     } 
}

I also have a problem with going backwards in my menu, but I hope I will manage it on my own. I'm using Arduino Leonardo. Thanks!

No schematic, no code tags and only a snippet. This seems to be the place you wanted to post.

Or, have a look at How to use the forum...

Hi all! :slight_smile:

I would really appreciate your help in this. I'm working on device and I want to create a menu for it. I have an encoder with a button and LCD screen. But after I added delay() function (to get rid of a noise), the button stopped working properly. Now it need to be both pressed AND rotated. Without the delay, button is working just fine, but then I have a problem with bouncing.

Also I have a problem with going backwards using encoder (going forward (counter++) is not a problem).

#define PinA 9
#define PinB 10
#define Button 4

int counter=0;
int cnt;
int aLastState;
int aState;
int buttonState;

void setup() 
{
  Serial.begin(9600);
 
  pinMode(PinA,INPUT_PULLUP); 
  pinMode(PinB,INPUT_PULLUP);
  pinMode(Button,INPUT_PULLUP);

  aLastState = digitalRead(PinA);
}

void loop() 
{
  aState = digitalRead(PinA);
  cnt = counter;
  
  if (aState != aLastState)
     {   
       if (digitalRead(PinA) != aState) {counter--;}  
       if (digitalRead(PinB) != aState) {counter++;}
     }
  if (cnt != counter) 
    {
      Serial.println(counter);
    }

  aLastState = aState;
  delay(20); //this one is causing problems
  buttonState = digitalRead(Button);
  
  if (buttonState == LOW) 
     {
      counter = 0;
      Serial.println(counter);
     }
}

I would really appreciate any help from You. That's my first week with Arduino (I'm using Arduino Leonardo) and I find it both fun and challenging. Thank you very much for any advice! :slight_smile:

The delay cannot cause the button to stop working. You have placed your delay in a place where it will cause a slowdown of the entire loop, if it is only supposed to debounce the button it must be placed within the "if (buttonState == LOW)" block. Another thing is that you are using "aLastState" for two digital inputs - that will cause problems.

Danois90:
You have placed your delay in a place where it will cause a slowdown of the entire loop, if it is only supposed to debounce the button it must be placed within the "if (buttonState == LOW)"

It is supposed to debounce the encoder (aLastState=aState). No matter how long I'm pressing the button, it is still the same - it only works when I rotate it. I also tried to change the position of the delay (I placed it on the end of whole loop) but with the same effect. Where should I place it? Thank you for your answer!

Generally when we debounce a switch we take successive readings after a specified delay and check to see if they're the same. The delay(20) does nothing but inject a 20ms pause, then you read button only once. Perhaps you want to first_read button, delay, second_read button; if first_read == second_read == LOW do your stuff. There are other issues with how ypu're trying to read an encoder, but those can wait for now.

DKWatson:
The delay(20) does nothing but inject a 20ms pause, then you read button only once.

Yes, I know, but the delay function is for this:

  aLastState = aState;
  delay(20);

And it does help with bouncing on encoder but it also causes button to be pressed and rotated. I don't have a problem with button bouncing.

if (buttonState_1 == buttonState_2 == LOW)

Does that work? I was writing p-code.

Yes, thank you, now button works perfectly! Any tips on how to handle going backwards (counter--)?

If you want the delay to debounce your button only, this how it should be done:

if (digitalRead(Button) == LOW)
{
  delay(20); //Prevent button from being re-read within 20 millis
  counter = 0;
  Serial.println(counter);
}

You do not need the "buttonState" variable.

pati130013:
Any tips on how to handle going backwards (counter--)?

Try it. Save me the trouble of wiring your circuit.

Danois90:
If you want the delay to debounce your button only, this how it should be done:

if (digitalRead(Button) == LOW)

{
  delay(20); //Prevent button from being re-read within 20 millis
  counter = 0;
  Serial.println(counter);
}




You do not need the "buttonState" variable.

You cannot debounce a switch with a single read.

DKWatson:
You cannot debounce a switch with a single read.

Really? The posted code will filter away 20ms of bouncing, I'd call that debouncing. Wheter the delay should be 20ms or something else would depend on the switch and the carbon entity operating it.

For a good read on switch debouncing, check out the Ganssle article here.
Pay particular attention to the part that includes

Most people use a fairly simple approach that looks for n sequential stable readings of the switch, where n is a number ranging from 1 (no debouncing at all) to seemingly infinity. Generally the code detects a transition and then starts incrementing or decrementing a counter, each time rereading the input, till n reaches some presumably safe, bounce-free, count. If the state isn't stable, the counter resets to its initial value.

DKWatson:
Pay particular attention to the part that includes

Makes no sense in relation to debouncing a pushbutton.

@pati130013, please do not cross-post. Threads merged.