아두이노 나노 로터리 엔코더

이 튜토리얼은 아두이노 나노와 로터리 인코더를 사용하는 방법을 지시합니다. 다룰 내용은 다음과 같습니다:

준비물

1×아두이노 나노 쿠팡 | 아마존
1×USB A to Mini-B USB 케이블 쿠팡 | 아마존
1×로터리 엔코더 (Rotary Encoder) 쿠팡 | 아마존
1×점퍼케이블 쿠팡 | 아마존
1×(추천) 아두이노 나노용 스크루 터미널 확장 보드 쿠팡 | 아마존
1×(추천) 아두이노 나노용 브레이크아웃 확장 보드 쿠팡 | 아마존
1×(추천) 아두이노 나노용 전원 분배기 쿠팡 | 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

로터리 엔코더 정보

회전하는 손잡이인 로터리 엔코더는 회전을 신호로 변환할 수 있습니다. 이것은 얼마나 많이 돌았는지와 그 위치를 나타냅니다. 주로 두 가지 종류가 있습니다:

  • 증분형 인코더: 빠른 신호를 사용하여 얼마나 많이 움직였는지를 확인합니다.
  • 절대 인코더: 이 유형은 각 위치마다 고유 코드를 제공하여, 전원이 꺼져도 어디에 있는지 정확히 파악할 수 있게 도와줍니다.

이 가이드는 증분 엔코더에 관한 모든 것입니다.

로터리 엔코더 모듈 핀배열

로터리 엔코더 사용법 핀아웃

로터리 인코더 모듈에는 4개의 핀이 있습니다:

  • CLK 핀 (출력 A): 회전이 얼마나 일어났는지 알려주는 주요 펄스입니다. 노브를 어느 방향으로든 한 딸깍 (클릭) 돌릴 때마다, CLK 핀은 전체 주기를 완료하는 신호 (LOW → HIGH → LOW)를 출력합니다.
  • DT 핀 (출력 B): CLK 핀처럼 작동하지만 CLK 신호보다 90도 지연된 신호를 출력합니다. 이것은 회전 방향 (시계 방향 또는 반시계 방향)을 파악하는 데 도움이 됩니다.
  • SW 핀: 인코더 안에 있는 푸시버튼에서 나오는 출력입니다. 보통 열려 있습니다. 이 핀에 풀업 저항을 사용한다면, 노브가 눌리지 않았을 때 SW 핀은 HIGH 상태가 되고, 눌렸을 때는 LOW 상태가 됩니다.
  • VCC 핀 (+): VCC (3.3과 5 볼트 사이)에 연결해야 합니다.
  • GND 핀: GND (0V)에 연결해야 합니다.

로터리 엔코더 대 비교 가변 저항기

회전 엔코더를 아두이노 나노 - 가변 저항기와 혼동할 수도 있지만, 이 두 부품은 서로 다릅니다. 다음은 이들 사이의 비교입니다:

  • 로터리 엔코더는 모던 버전의 포텐쇼미터로 생각할 수 있지만, 더 많은 기능을 제공합니다.
  • 로터리 엔코더는 멈추지 않고 전체 방향으로 회전할 수 있지만, 포텐쇼미터는 대략 3/4 정도만 회전할 수 있습니다.
  • 로터리 엔코더는 펄스를 출력하는 반면, 포텐쇼미터는 아날로그 전압을 생성합니다.
  • 손잡이가 얼마나 움직였는지만 알고 싶을 때, 정확한 위치를 지정하지 않고도, 로터리 엔코더는 편리합니다. 반면에, 손잡이의 정확한 위치를 알아야 할 때는 포텐쇼미터가 귀중합니다.

로터리 엔코더가 작동하는 방식

로터리 엔코더 output

인코더 안에는 공통 접지처럼 작동하는 C라고 불리는 핀에 연결된 슬롯이 있는 디스크가 있습니다. A와 B라는 두 개의 핀이 더 있습니다.

  • 노브를 돌릴 때, 핀 A와 B가 공통 접지핀 C와 접촉하지만, 노브를 돌리는 방향(시계 방향 또는 반시계 방향)에 따라 특정 순서로 접촉합니다.
  • 이러한 접촉은 두 개의 신호를 생성합니다. 한 핀이 다른 핀보다 먼저 접지에 닿기 때문에 시간적으로 약간 다릅니다. 두 신호는 서로 90도 동기화가 안 맞습니다. 이것을 쿼드러처 인코딩이라고 합니다.
  • 시계 방향으로 노브를 돌릴 때, 핀 A가 핀 B보다 먼저 접지에 닿습니다. 반시계 방향으로 노브를 돌릴 때는 핀 B가 핀 A보다 먼저 접지에 닿습니다.
  • 각 핀이 접지에 닿거나 떨어지는 시기를 모니터링함으로써 우리는 노브가 어느 방향으로 돌아가는지 알아낼 수 있습니다. 이는 핀 A가 변할 때 핀 B에게 무슨 일이 일어나는지 확인함으로써 이루어집니다.
how 로터리 엔코더 works

A가 LOW에서 HIGH로 상태가 변경될 때:

  • B가 낮으면, 노브를 시계 방향으로 돌립니다.
  • B가 높으면, 노브를 반시계 방향으로 돌립니다.

※ 주의:

A핀과 B핀은 CLK 및 DT 핀에 연결되어 있습니다. 그러나 제조업체에 따라 순서가 다를 수 있습니다. 아래 제공된 코드는 DIYables의 회전 엔코더와 함께 테스트되었습니다.

로터리 엔코더를 위한 프로그래밍 방법

  • CLK 핀에서 신호를 확인하세요.
  • 상태가 LOW에서 HIGH로 바뀌면 DT 핀의 상태를 확인하세요.
    • DT 핀의 상태가 HIGH이면, 노브가 반시계 방향으로 돌아간 것이므로 카운터를 1만큼 증가시키세요.
    • DT 핀의 상태가 LOW이면, 노브가 시계 방향으로 돌아간 것이므로 카운터를 1만큼 감소시키세요.

선연결

아두이노 나노 로터리 엔코더 연결 배선도

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.

이 회로는 브레드보드 없이도 만들 수 있습니다. 같은 배선은 다음과 같습니다:

아두이노 나노 로터리 엔코더 연결 배선도 (브레드보드 없음)

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.

헐거운 전선은 이상한 오류의 흔한 원인입니다. Arduino Nano를 아두이노 나노용 스크루 터미널 확장 보드에 꽂기만 하면 됩니다. 아래는 나사 단자 보드를 사용한 배선도입니다.

아두이노 나노 로터리 엔코더 연결 배선도 (screw terminal)

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.

Arduino Nano와 기타 부품에 전원을 공급하는 가장 효과적인 방법은 다음 링크를 참조하세요: 아두이노 나노 전원 공급 방법.

아두이노 나노 코드 - 로터리 엔코더

아래의 아두이노 나노 코드는 다음을 수행합니다:

  • 엔코더의 회전 방향과 회전량을 감지합니다.
    • 시계 방향으로 한 단계(클릭) 돌린 것을 감지하면 카운터를 1 증가시킵니다.
    • 반시계 방향으로 한 단계(클릭) 돌린 것을 감지하면 카운터를 1 감소시킵니다.
  • 버튼이 눌렸는지 감지합니다.
/* * 이 아두이노 나노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 나노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-nano/arduino-nano-rotary-encoder */ #include <ezButton.h> // SW 핀을 사용하기 위한 라이브러리 #define CLK_PIN 2 #define DT_PIN 3 #define SW_PIN 4 #define DIRECTION_CW 0 // 시계 방향 #define DIRECTION_CCW 1 // 반시계 방향 int counter = 0; int direction = DIRECTION_CW; int CLK_state; int prev_CLK_state; ezButton button(SW_PIN); void setup() { Serial.begin(9600); // 인코더 핀을 입력으로 설정 pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // 디바운스 시간을 50 밀리초로 설정 // 로터리 인코더의 CLK 핀의 초기 상태를 읽음 prev_CLK_state = digitalRead(CLK_PIN); } void loop() { button.loop(); // 반드시 loop() 함수를 먼저 호출해야 함 // 로터리 인코더의 CLK 핀의 현재 상태를 읽음 CLK_state = digitalRead(CLK_PIN); // CLK의 상태가 변경되면, 펄스 발생 // 이중 계산을 피하기 위해 상승 에지(LOW에서 HIGH로)에만 반응 if (CLK_state != prev_CLK_state && CLK_state == HIGH) { // DT 상태가 HIGH이면 // 엔코더가 반시계 방향으로 회전 => 카운터 감소 if (digitalRead(DT_PIN) == HIGH) { counter--; direction = DIRECTION_CCW; } else { // 엔코더가 시계 방향으로 회전 => 카운터 증가 counter++; direction = DIRECTION_CW; } Serial.print("Twisted direction: "); if (direction == DIRECTION_CW) Serial.print("CLOCKWISE"); else Serial.print("ANTICLOCKWISE"); Serial.print(" - counter: "); Serial.println(counter); } // 마지막 CLK 상태 저장 prev_CLK_state = CLK_state; if (button.isPressed()) { Serial.println("The button is pressed"); } }

버튼 디바운싱 코드를 간단하게 하기 위해 ezButton 라이브러리가 사용됩니다.

사용 방법

  • Arduino IDE에 ezButton 라이브러리를 설치하세요. 방법 보기
  • 위의 코드를 복사하여 Arduino IDE로 열기
  • 코드를 Arduino Nano에 업로드하기 위해 Arduino IDE에서 Upload 버튼을 클릭하세요
  • 손잡이를 시계 방향으로 돌린 다음, 반시계 방향으로 돌리세요
  • 손잡이를 누르세요
  • 시리얼 모니터에서 결과를 확인하세요.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
Arduino Nano
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano' on 'COM15')
New Line
9600 baud
Twisted direction: CLOCKWISE - counter: 1 Twisted direction: CLOCKWISE - counter: 2 Twisted direction: CLOCKWISE - counter: 3 Twisted direction: CLOCKWISE - counter: 4 Twisted direction: CLOCKWISE - counter: 5 Twisted direction: ANTICLOCKWISE - counter: 4 Twisted direction: ANTICLOCKWISE - counter: 3 Twisted direction: ANTICLOCKWISE - counter: 2 Twisted direction: ANTICLOCKWISE - counter: 1 Twisted direction: ANTICLOCKWISE - counter: 0 The button is pressed
Ln 11, Col 1
Arduino Nano on COM15
2

코드 설명

코드의 줄별 주석을 확인하세요.

아두이노 나노 코드 - 인터럽트를 사용한 로터리 인코더

이전 예제 코드에서는 폴링 방식을 사용하여 지속적으로 핀의 상태를 확인합니다. 이 방식은 두 가지 단점이 있습니다:

  • 아두이노 나노 자원 낭비
  • 다른 코드가 실행하는 데 시간이 오래 걸리면 일부 카운터가 누락될 수 있습니다.

이를 처리하는 한 가지 방법은 인터럽트를 사용하는 것입니다. 인터럽트는 특정 이벤트를 지속적으로 확인할 필요를 없애줍니다. 이를 통해 아두이노 나노가 다른 작업을 수행하면서도 이벤트를 놓치지 않고 처리할 수 있습니다.

다음은 인터럽트를 사용하여 로터리 인코더를 읽는 방법의 예입니다.

/* * 이 아두이노 나노 코드는 newbiely.kr 에서 개발되었습니다 * 이 아두이노 나노 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-nano/arduino-nano-rotary-encoder */ #include <ezButton.h> // SW 핀을 사용하기 위한 라이브러리 #define CLK_PIN 2 // 아두이노 나노 핀 D2를 로터리 인코더의 CLK 핀에 연결 #define DT_PIN 3 // 아두이노 나노 핀 D3를 로터리 인코더의 DT 핀에 연결 #define SW_PIN 4 // 아두이노 나노 핀 D4를 로터리 인코더의 SW 핀에 연결 #define DIRECTION_CW 0 // 시계 방향 #define DIRECTION_CCW 1 // 반시계 방향 volatile int counter = 0; volatile int direction = DIRECTION_CW; volatile unsigned long last_time; // 디바운싱용 int prev_counter; ezButton button(SW_PIN); void INTERRUPT_handler() { if ((millis() - last_time) < 50) // 디바운스 시간이 10ms임 return; if (digitalRead(DT_PIN) == HIGH) { // 인코더가 반시계 방향으로 회전하고 있음 => 카운터 감소 counter--; direction = DIRECTION_CCW; } else { // 인코더가 시계 방향으로 회전하고 있음 => 카운터 증가 counter++; direction = DIRECTION_CW; } last_time = millis(); } void setup() { Serial.begin(9600); // 인코더 핀을 입력으로 구성 pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // 디바운스 시간을 50밀리초로 설정 // CLK 핀에 대한 인터럽트 사용 // CLK 핀이 LOW에서 HIGH로 변경될 때 INTERRUPT_handler() 호출 attachInterrupt(digitalPinToInterrupt(CLK_PIN), INTERRUPT_handler, RISING); } void loop() { button.loop(); // 반드시 loop() 함수를 먼저 호출해야 함 if (prev_counter != counter) { Serial.print("Twisted direction: "); if (direction == DIRECTION_CW) Serial.print("CLOCKWISE"); else Serial.print("ANTICLOCKWISE"); Serial.print(" - counter: "); Serial.println(counter); prev_counter = counter; } if (button.isPressed()) { Serial.println("The button is pressed"); } // 여기에 다른 작업을 수행하십시오. }

이제 볼륨을 돌리면, 이전 코드에서 보았던 것처럼 시리얼 모니터에 정보가 나타나는 것을 알 수 있습니다.

※ 주의:

인터럽트를 사용하려면 인코더의 CLK 핀을 인터럽트를 처리할 수 있는 아두이노 나노 핀에 연결해야 합니다. 하지만 모든 아두이노 나노 핀이 이를 수행할 수 있는 것은 아닙니다. 예를 들어, 아두이노 나노에서는 오직 2번과 3번 핀만 인터럽트와 함께 작동할 수 있습니다.

다른 웹사이트의 튜토리얼에서 하나의 인코더에 대해 두 개의 인터럽트를 사용하는 경우를 볼 수 있지만, 이것은 불필요하고 낭비입니다. 단 하나의 인터럽트만으로 충분합니다.

인터럽트에서 사용되는 전역 변수에는 volatile 키워드를 사용하는 것이 중요합니다. 이를 무시하면 예상치 못한 문제가 발생할 수 있습니다.

인터럽트 내의 코드를 가능한 한 단순하게 유지하세요. 인터럽트 내에서 Serial.print() 또는 Serial.println()을 사용하는 것은 피하세요.

아두이노 나노 로터리 엔코더 응용 프로그램

로터리 엔코더를 사용하여 다음과 같은 응용 프로그램을 할 수 있지만 이에 국한되지는 않습니다:

  • Arduino Nano - 로터리 엔코더가 서보 모터의 위치를 제어합니다.
  • Arduino Nano - 로터리 엔코더가 LED의 밝기를 제어합니다.
  • Arduino Nano - 로터리 엔코더가 스테퍼 모터의 속도를 제어합니다.

동영상

비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.

관련 튜토리얼