Rotary Encoder Module

1. Rotary Encoder Module

Rotary encoder 모듈은 시계 방향/반시계 방향으로 회전함에 따라 output pulse 값을 변경시켜 줍니다. 시계/반시계 방향 회전과 버튼 클릭 입력을 간편하게 구현할 수 있습니다. Rotating potentiometer 와는 달리 회전량에 대한 제한 없이 돌릴 수 있습니다. 1스텝 회전에 대한 카운트는 프로그램 상에서 처리해줘야 하는데, 일반적으로 interrupt pin (UNO 보드 기준으로 D2, D3 핀) 을 사용해서 회전이 발생하면 자동으로 등록된 interrupt callback 함수가 실행되도록 구현합니다. Rotary encoder에 있는 버튼을 이용해서 count 를 초기화 하도록 프로그램 상으로 구현해서 사용하는 경우가 많습니다.

보통 회전당 12스텝 정도를 가지고 있으나 제품에 따라 200스텝 이상을 가지고 있기도 합니다.

Rotary encoder는 3개의 핀을 가지고 있는데 각각의 핀에서 high/low 시그널을 읽을 수 있습니다. 버튼용 핀을 제외하고 회전 감지용 핀 두 개를 조합할 경우 (00, 01, 11, 10) 4개의 조합을 읽을 수 있습니다. Rotary encoder 는 특정 방향으로 돌릴 경우 (00, 01, 11, 10) 순서로 반복되도록 되어 있습니다. 따라서 이전 상태와 현재 상태를 비교해서 회전 방향을 알 수 있습니다.

RotaryEncoderWaveform

Bildr 에서 소개하는 회전방향 추출방법은 다음과 같습니다. 먼저 이전 상태에 대한 값을 기록해 두고 새롭게 상태가 업데이트 되면 뒤에 덧붙여서 4bit 코드를 만듭니다. 이렇게하면 총 8개의 코드가 만들어집니다. (0001, 0010, 0100, 0111, 1000, 1011, 1110, 1101) 이 중에서 1101, 0100, 0010, 1011 값은 시계 방향으로 회전한 경우이며,  1110, 0111, 0001, 1000 값인 경우는 반시계 방향 회전입니다.

참고 : Bildr (http://bildr.org/2012/08/rotary-encoder-arduino/)

Model: KY-040
Working voltage: 5V
Material: PCB + Brass
Weight: 10g
Size: 32 x 19 x 30mm

2. 연결 방법

Encoder Pin -> Arduino Pin

GND    ->    GND
+           ->    +5V
SW       ->    D4   (버튼 감지용)
DT        ->    D3   (회전 A, 인터럽트 핀 사용)
CLK      ->    D2  (회전 B, 인터럽트 핀 사용)

3. 소스 코드 (스케치) 

//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;
int encoderSwitchPin = 4; //push button switch

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);

  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);

  pinMode(encoderSwitchPin, INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  digitalWrite(encoderSwitchPin, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){ 
  //Do stuff here
  if(digitalRead(encoderSwitchPin2)){
    //button is not being pushed
  }else{
    //button is being pushed
  }

  Serial.println(encoderValue);
  delay(1000); //just here to slow down the output, and show it will work  even during a delay
}

void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded; //store this value for next time
}

You may also like...