Using Rotary Encoder with Arduino

In this arduino tutorial it is explained what rotary encoder is and how to use it with Arduino. In the rotary Arduino example provided here users can control the brightness of an LED using a rotary encoder. Rotating the encoder clockwise increases the brightness, and rotating it counterclockwise decreases the brightness. Pressing the encoder button turns off the LED. The number of turns of the encoder and the current brightness value are displayed in the serial monitor.

A rotary encoder is an electromechanical device used to convert the angular position or rotation of a shaft into digital signals. It provides a way to measure and track the rotation of a knob or shaft. Rotary encoders are commonly used in various applications, including robotics, industrial control systems, gaming devices, and audio equipment.



There are two main types of rotary encoders: incremental and absolute.

1. Incremental Rotary Encoder:

An incremental rotary encoder generates pulses as the shaft rotates. It consists of two output channels, typically labeled as A and B. Each channel has a series of evenly spaced pulses. The channels are typically out of phase by 90 degrees (also known as quadrature encoding). As the shaft rotates, the encoder produces a series of pulses on the A and B channels. The direction of rotation can be determined by examining the order in which the pulses arrive on the A and B channels. By counting the number of pulses, the encoder's position or the number of rotations can be determined.

2. Absolute Rotary Encoder:

An absolute rotary encoder provides a unique digital code or value for each position of the shaft. It can directly indicate the absolute angular position of the shaft without the need for counting pulses. Absolute encoders use various techniques to achieve this, such as binary code, Gray code, or a combination of multiple tracks or bits. Each unique position corresponds to a specific code, which can be read to determine the shaft's angular position.

Working Principle:

In both types of rotary encoders, the basic principle involves the rotation of a disk or a wheel with evenly spaced slots or marks, and a sensor or set of sensors that detect these marks as the shaft rotates. The sensors may use different technologies, such as optical, magnetic, or capacitive, depending on the encoder type.

For incremental encoders, the marks on the disk produce pulses as they pass by the sensor. The A and B channels generate square wave signals that are out of phase with each other. By analyzing the sequence and timing of the pulses on the A and B channels, the direction of rotation and the number of rotations can be determined.

Absolute encoders, on the other hand, provide a unique code for each position of the shaft. The code can be read by the sensors or read heads, which are positioned to detect the specific marks or patterns on the encoder disk or wheel. The code is then translated into a digital value that represents the absolute angular position of the shaft.

Overall, rotary encoders provide a way to measure and monitor the rotation of a shaft or knob, enabling precise control and feedback in various applications. 

Arduino Rotary Encoder Circuit Diagram

 The following shows the circuit diagram of connecting rotary encoder with Arduino and a LED.

arduino rotary encoder schematic

In the above, rotary encoder module, KY-040, is used. 

rotary encoder 2
 The rotary encoder clock (CLK), data (DT), and switch (SW) pins are connected to Arduino pins A0, A1, and A2. A LED is connected to pin 6 with a resistor 220Ohm.

Arduino Rotary encoder Program

This code is an implementation of a rotary encoder using an Arduino board. A rotary encoder is an input device that converts the rotation of a shaft into digital signals. The code reads the rotation and button press of the rotary encoder and adjusts the brightness of an LED accordingly.

int CLKpin= A0; // pin A or clock pin
int DTpin= A1; // pin B or data pin
int SWpin= A2 ; // switch pin
int LEDpin = 6; // LED on PWM pin
int bright = 120; // initial LED value
int fade = 10; // amount to change LED
int rotate = 0; // number of rotary turns
int oldA = HIGH; // status of pin A
int change, result, newA, newB;

void setup(){
	Serial.begin(9600); // define Serial output baud rate
	pinMode(LEDpin, OUTPUT); // LED pin as output
	pinMode(SWpin, INPUT_PULLUP); // switch pin uses internal pull-up resistor
}

void loop(){
	if(digitalRead(SWpin) == LOW) 
		bright = 0; // switch, active LOW,
	// turns off LED
	change = encoder(); // function for direction of rotation
	rotate = rotate + abs(change); // number of turns of rotary encoder
	bright = bright + change*fade; // change LED brightness
	bright = constrain(bright, 0, 255); // constrain LED brightness
	
	if(change != 0){ // display number
		Serial.print(rotate);
		Serial.print("\t"); // of rotary turns
		Serial.println(bright); // and LED brightness
	}
	analogWrite(LEDpin, bright); // update LED brightness
}

// function to determine direction
int encoder(){
	result = 0;
	newA = digitalRead(CLKpin); // state of (CLK) pin A
	newB = digitalRead(DTpin); // state of (DT) pin B
	// falling edge on (CLK) pin A
	if (oldA == HIGH && newA == LOW) result = 2*newB - 1;
	oldA = newA; // update state of (CLK) pin A
	return result;
}

Let's go through the code step by step:

1.  Pin Definitions:

int CLKpin = A0; // pin A or clock pin int DTpin = A1; // pin B or data pin int SWpin = A2; // switch pin int LEDpin = 6; // LED on PWM pin

These variables define the pin connections for the rotary encoder and the LED.

2. Variable Initialization:

int bright = 120;  // initial LED value
int fade = 10;     // amount to change LED
int rotate = 0;    // number of rotary turns
int oldA = HIGH;   // status of pin A
int change, result, newA, newB;

 These variables store various states and values used in the code. bright represents the current LED brightness value, fade determines the amount by which the brightness changes, rotate keeps track of the number of turns of the rotary encoder, oldA stores the previous state of pin A, and change, result, newA, and newB are used for temporary calculations.

3. Setup Function:

void setup() {
  Serial.begin(9600);                  // define Serial output baud rate
  pinMode(LEDpin, OUTPUT);             // LED pin as output
  pinMode(SWpin, INPUT_PULLUP);        // switch pin uses internal pull-up resistor
}

 In the setup function, the serial communication is initialized with a baud rate of 9600. The LEDpin is set as an output, and the SWpin (switch pin) is configured as an input with an internal pull-up resistor.

4. Main Loop:

void loop() {
  if (digitalRead(SWpin) == LOW) bright = 0;  // switch, active LOW, turns off LED
  change = encoder();                        // function for direction of rotation
  rotate = rotate + abs(change);              // number of turns of rotary encoder
  bright = bright + change * fade;            // change LED brightness
  bright = constrain(bright, 0, 255);         // constrain LED brightness

  if (change != 0) {
    Serial.print(rotate); Serial.print("\t"); // display number of rotary turns
    Serial.println(bright);                    // and LED brightness
  }

  analogWrite(LEDpin, bright);                // update LED brightness
}

The loop function is the main part of the code that runs repeatedly. It performs the following steps:

  • It checks if the switch pin is LOW, indicating that the button on the rotary encoder is pressed. In this case, it sets the brightness value (bright) to 0, turning off the LED.
  • It calls the encoder function to determine the direction of rotation of the rotary encoder. The result is stored in the change variable.
  • The absolute value of change is added to the rotate variable to keep track of the number of turns of the rotary encoder.
  • The bright variable is updated based on the change and fade values. If change is positive, the brightness increases; if change is negative, the brightness decreases.
  • The bright value is constrained to be within the range of 0 to 255 using the constrain function.
  • If there was a change in the rotary encoder (change != 0), the current number of turns (rotate) and LED brightness (bright) are printed to the serial monitor.
  • Finally, the LED brightness is updated by calling analogWrite on the LEDpin with the updated bright value.

5. Encoder Function:

int encoder() { result = 0; newA = digitalRead(CLKpin); // state of (CLK) pin A newB = digitalRead(DTpin); // state of (DT) pin B // falling edge on (CLK) pin A if (oldA == HIGH && newA == LOW) result = 2 * newB - 1; oldA = newA; // update state of (CLK) pin A return result; }

The encoder function is responsible for determining the direction of rotation of the rotary encoder. It reads the current states of the CLKpin (pin A) and DTpin (pin B). By comparing the old and new states of pin A, it determines if a falling edge (change from HIGH to LOW) has occurred.

  • If a falling edge is detected, the result value is updated. This value is calculated based on the state of pin B (newB). If newB is HIGH, the result will be 1; if newB is LOW, the result will be -1.
  • The oldA variable is updated with the new state of pin A.
  • The result value is returned to the loop function.


Post a Comment

Previous Post Next Post