Rotary Encoder not working properly

I used some code that I found online but the rotary encoder only shows increments even when Im turning it anticlockwise. It also shows that button has been pressed randomly even when I did not press the button, is there something wrong with it? I used an old one as well as a brand new one and got the same results.

I used the code and model of the one found on LastMinuteEngineers.

// Rotary Encoder Inputs
#define CLK 2
#define DT 3
#define SW 4

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;

void setup() {
        
	// Set encoder pins as inputs
	pinMode(CLK,INPUT);
	pinMode(DT,INPUT);
	pinMode(SW, INPUT_PULLUP);

	// Setup Serial Monitor
	Serial.begin(9600);

	// Read the initial state of CLK
	lastStateCLK = digitalRead(CLK);
}

void loop() {
        
	// Read the current state of CLK
	currentStateCLK = digitalRead(CLK);

	// If last and current state of CLK are different, then pulse occurred
	// React to only 1 state change to avoid double count
	if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

		// If the DT state is different than the CLK state then
		// the encoder is rotating CCW so decrement
		if (digitalRead(DT) != currentStateCLK) {
			counter --;
			currentDir ="CCW";
		} else {
			// Encoder is rotating CW so increment
			counter ++;
			currentDir ="CW";
		}

		Serial.print("Direction: ");
		Serial.print(currentDir);
		Serial.print(" | Counter: ");
		Serial.println(counter);
	}

	// Remember last CLK state
	lastStateCLK = currentStateCLK;

	// Read the button state
	int btnState = digitalRead(SW);

	//If we detect LOW signal, button is pressed
	if (btnState == LOW) {
		//if 50ms have passed since last LOW pulse, it means that the
		//button has been pressed, released and pressed again
		if (millis() - lastButtonPress > 50) {
			Serial.println("Button pressed!");
		}

		// Remember last button press event
		lastButtonPress = millis();
	}

	// Put in a slight delay to help debounce the reading
	delay(1);
}

Use the rotary encoder library.

Issue still persists after i included the library you provided

Change the CLK and DT to INPUT_PULLUP

what does that mean? replace each CLK with INPUT and each DT with PULLUP?

It seems to be a robot generated code.

I copied it from LastMinuteEngineers, i dont really understand how it works, i have changed

	pinMode(CLK,INPUT);
	pinMode(DT,INPUT);

to

	pinMode(CLK,INPUT_PULLUP);
	pinMode(DT,INPUT_PULLUP);

it still doesnt work

You seem to be a real beginner.

Including the library is not enough. You have to use the functions of the encoder-library.
The library that was linked to by user @buckfast_beekeeper is very likely to still work unreliable if this library does not use the state-machine / state-change detection.

I recommend the NewEncoder-library which works very reliably
You can download this library from here

for installing a ZIP-library read this tutorial

Here is a Demo-Code for the NewEncoder-library that uses encoder-pins on IO-pin 2 and 3


#include "NewEncoder.h" //https://github.com/gfvalvo/NewEncoder

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -10;
const int maxVal =  10;
const int startVal = 2;

// Pins 2 and 3 should work for many processors, including Uno. 
// See README https://github.com/gfvalvo/NewEncoder#readme 
// for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;


      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

best regards Stefan

If you are using a breadboard, make sure you have good connections or try a different spot on the breadboard.

I use the Encoder library.

That library is available trough the IDE library manager. Always use the library manager to install libraries if possible.

How to install an Arduino library.

would my code work with the library?

Try some of the example code. See if you can make it work with your code.

Used an encoder here..
Uno Pong

Maybe it helps.. ~q

Your original sketch works. Is this encoder for the pomodoro? The code for the encoder works on that thread, too. I suspect your wiring (on both threads).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.