아두이노의 인터럽트 기능을 이용하면 추가적인 하드웨어 없이 로터리 엔코더 (rotaty encoder)의 출력을 간단하게 읽어들일 수 있다. 여기에서는 아두이노 Due와 오토닉스(autonics)사의 1800펄스/1회전 분해능의 고정밀 로터리 엔코더를 이용해서 실험을 진행해 보겠다.


 기본적인 아이디어는 다음과 같다.


[그림 1] 오토닉스사의 로커리 엔코더 (E40H8-1800-6-L-5 )


엔코더에서는 세 가지 신호가 나오는데 각각 A상, B상, 그리고 Z상이라고 한다. A상과 B상은 축이 회전하면 위 그림과 같은 펄스를 발생하는데 자세히 보면 위상이 90도 만큼 엇갈려 있다. 일단 회전각은 A상을 기준으로 rising edge 혹은 falling edge 에서 인터럽트를 발생하여 내부 변수를 하나씩 증가하는 식으로 저장하면 된다. 회전 방향은 B상을 참조하면 되는데 예를 들어 시계방향으로 회전시에는 A상의 falling edge에서 B상이 1이고 반대 방향에서는 0이다. 이것으로 회전방향을 판단하면 된다. Z상의 펄스는 1회전에 한 번 발생하므로 이것으로 영점을 잡으면 된다. 즉 Z상의 펄스가 발생하면 카운트를 0으로 리셋시킨다.


 이제 아두이노Due 쪽의 프로그램을 살펴보면 Due는 다른 아두이노와 달리 고성능 보드 답게 모든 핀에 인터럽트를 설정할 수 있다. (다른 아두이노는 보통 2개 많아야 6개이다.) 필자는


  • 26번핀: A상

  • 28번핀: B상

  • 30번핀: Z상

이렇게 연결하였다. 한 가지 주의할 것은 autonics사이 이 엔코더는 datasheet에서 5V로 동작한다고 쓰여져 있는데 그렇다고 5V전원을 연결하면 신호선에 과전압이 걸려서 Due보드에 무리를 줄 수 있다.(Due보드는 동작 전압이 3.3V임) 다행히 3.3V를 연결해도 잘 동작하는 것 같았다. 테스트 프로그램은 다음과 같다.


int pA = 26; // phase-A of rotary encoder
int pB = 28; // phase-B of rotary encoder
int pZ = 30; // phase-B of rotary encoder

volatile signed long cnt = 0;
volatile signed char dir = 1;

void setup() {
   Serial.begin(115200);
   attachInterrupt(pA, encoderCount, FALLING);
   pinMode(pB, INPUT);
   attachInterrupt(pZ, encoderReset, FALLING);
}

void loop() {
   Serial.print(micros());  Serial.print(',');
   Serial.println(cnt);
}

void encoderCount() { // A상 신호의 폴링 에지에서 호출됨
   //B상의 값에 따라 방향을 결정한다.
   dir = (digitalRead(pB)==HIGH)? 1:-1;
   cnt += dir;
}
void encoderReset() { // Z상 신호의 폴링 에지에서 호출됨
   cnt = 0;
}


이렇게 구현하면 매우 간단하게 로터리 엔코더 신호를 읽어들일 수 있다.



Posted by 살레시오
,