아두이노 우노 R4 - 로터리 인코더

이 가이드에서는 아두이노 UNO R4와 함께 증분 인코더를 사용하는 방법에 대해 배워볼 것입니다. 우리는 다음을 다룰 것입니다:

아두이노 UNO R4 로터리 인코더

Hardware Preparation

1×Arduino UNO R4 WiFi Amazon
1×Arduino UNO R4 Minima (Alternatively) Amazon
1×USB Cable Type-C 쿠팡 | Amazon
1×Rotary Encoder 쿠팡 | Amazon
1×Jumper Wires Amazon
1×(Recommended) Screw Terminal Block Shield for Arduino UNO R4 쿠팡 | Amazon
1×(Recommended) Breadboard Shield For Arduino UNO R4 쿠팡 | Amazon
1×(Recommended) Enclosure For Arduino UNO R4 Amazon
1×(Recommended) Power Splitter For Arduino UNO R4 Amazon
공개: 이 섹션에서 제공된 링크 중 일부는 제휴 링크입니다. 이 링크를 통해 구매한 경우 추가 비용없이 수수료를 받을 수 있습니다. 지원해 주셔서 감사합니다.

로터리 엔코더에 대하여

회전 인코더는 회전 운동을 전기 신호로 변환하는 장치입니다. 이는 샤프트나 손잡이의 회전과 위치를 확인합니다. 주로 두 가지 유형이 있습니다:

  • 증분형 엔코더: 위치 변화를 측정하기 위해 펄스를 생성합니다.
  • 절대형 엔코더: 각 위치에 대해 특별한 디지털 코드를 제공하여, 전원이 꺼져도 정확한 위치 지정에 적합합니다.

이 튜토리얼은 증분 인코더에 관한 것입니다.

로터리 인코더 모듈 핀아웃

로터리 엔코더 핀아웃

로터리 인코더 모듈은 네 개의 핀으로 구성되어 있습니다:

  • CLK 핀 (출력 A): 이 핀은 노브를 한 번 클릭하는 방향으로 돌릴 때마다 신호를 보냅니다. 이는 LOW에서 HIGH로, 다시 LOW로 가는 완전한 신호 주기를 보여주며, 노브가 얼마나 회전했는지를 알려줍니다.
  • DT 핀 (출력 B): CLK 핀과 유사하지만, 이 핀의 신호는 CLK 신호보다 90도 지연되어 발생합니다. 이 지연은 회전이 시계 방향인지 반시계 방향인지 판단하는 데 도움이 됩니다.
  • SW 핀: 이 핀은 인코더의 내부 푸시버튼에 연결되어 있으며, 보통 열려 있습니다. 이 핀에 풀업 저항을 사용하면 노브가 눌리지 않았을 때 HIGH를, 눌렸을 때 LOW를 나타냅니다.
  • VCC 핀 (+): 이 핀을 3.3V에서 5V 사이의 전원을 공급하는 전원 공급 장치에 연결하세요.
  • GND 핀: 이 핀을 접지 (0V)에 연결하세요.

로터리 엔코더 vs 포텐셔미터

회전 인코더를 포텐셔미터와 혼동할 수 있지만, 이들은 다른 부품입니다. 다음은 그 비교입니다:

  • 로터리 엔코더는 완전히 계속해서 회전할 수 있지만, 포텐쇼미터는 전체 원의 4분의 3만 회전할 수 있습니다.
  • 로터리 엔코더는 펄스를 출력하는 반면, 포텐쇼미터는 아날로그 전압을 출력합니다.
  • 로터리 엔코더는 노브가 얼마나 회전했는지를 아는 데 유용하지만, 정확한 위치는 알 수 없습니다. 포텐쇼미터는 노브의 정확한 위치를 찾는 데 좋습니다.

로터리 인코더의 작동 원리

로터리 엔코더 출력

인코더에는 C라는 이름의 핀과 연결된 슬롯이 있는 디스크가 있으며, 이는 공통 접지로 작용합니다. 또한 두 개의 추가 핀, A와 B가 있습니다.

  • 손잡이를 회전하면 핀 A와 B가 공통 접지 핀 C와 접촉하게 되지만, 회전 방향에 따라 시계 방향 또는 반시계 방향으로 특정 순서에 따라 작동합니다.
  • 이 접촉은 타이밍이 약간 다른 두 개의 신호를 생성합니다. 이는 한 핀이 다른 핀보다 먼저 접지에 연결되기 때문입니다. 이 신호들은 90도 어긋나 있으며, 이를 사분면 인코딩이라 부릅니다.
  • 손잡이를 시계 방향으로 돌리면 핀 A가 핀 B보다 먼저 접지에 접촉됩니다. 반시계 방향으로 돌리면 핀 B가 핀 A보다 먼저 접지에 접촉됩니다.
  • 각 핀이 접지와 접촉하거나 끊어지는 시점을 관찰함으로써 손잡이의 회전 방향을 결정할 수 있습니다. 이는 핀 A와 비교하여 핀 B의 변화를 분석함으로써 수행됩니다.
회전 인코더의 작동 원리

A가 LOW에서 HIGH로 전환될 때:

  • B가 LOW이면 손잡이를 시계 방향으로 돌리세요.
  • B가 HIGH이면 손잡이를 반시계 방향으로 돌리세요.

※ NOTE THAT:

A핀과 B핀은 CLK 및 DT 핀에 연결되어 있습니다. 배치는 제조업체에 따라 다를 수 있습니다. 여기 제공된 코드는 DIYables의 로터리 인코더로 테스트되었습니다.

로터리 엔코더를 프로그래밍하는 방법

  • CLK 핀에서 신호를 확인하세요.
  • 신호가 LOW에서 HIGH로 변할 때, DT 핀이 무엇을 나타내고 있는지 확인하세요.
    • DT 핀이 HIGH를 나타내면, 다이얼이 반시계 방향으로 돌아갑니다. 카운터에 1을 더하세요.
    • DT 핀이 LOW를 나타내면, 다이얼이 시계 방향으로 돌아갑니다. 카운터에서 1을 빼세요.

Wiring Diagram

아두이노 UNO R4 로터리 엔코더 배선도

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

아두이노 UNO R4 코드 – 인터럽트 없는 로터리 엔코더

이 Arduino UNO R4 코드는 다음 작업을 수행합니다:

  • 인코더가 어떻게, 그리고 얼마나 회전하는지를 감지합니다.
    • 노브가 오른쪽으로 한 칸 클릭되었다고 감지하면 카운터에 1을 더합니다.
    • 노브가 왼쪽으로 한 칸 클릭되었다고 감지하면 카운터에서 1을 뺍니다.
  • 버튼이 눌렸는지 알아차립니다.
/* * 이 Arduino UNO R4 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO R4 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-r4/arduino-uno-r4-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 2 // The Arduino UNO R4 pin connected to the CLK pin of encoder #define DT_PIN 3 // The Arduino UNO R4 pin connected to the DT pin of encoder #define SW_PIN 4 // The Arduino UNO R4 pin connected to the SW pin of encoder #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // counter-clockwise direction int counter = 0; int direction = DIRECTION_CW; int CLK_state; int prev_CLK_state; ezButton button(SW_PIN); // create ezButton object that attach to pin 4 void setup() { Serial.begin(9600); // configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // read the initial state of the rotary encoder's CLK pin prev_CLK_state = digitalRead(CLK_PIN); } void loop() { button.loop(); // MUST call the loop() function first // read the current state of the rotary encoder's CLK pin CLK_state = digitalRead(CLK_PIN); // If the state of CLK is changed, then pulse occurred // React to only the rising edge (from LOW to HIGH) to avoid double count if (CLK_state != prev_CLK_state && CLK_state == HIGH) { // if the DT state is HIGH // the encoder is rotating in counter-clockwise direction => decrease the counter if (digitalRead(DT_PIN) == HIGH) { counter--; direction = DIRECTION_CCW; } else { // the encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } Serial.print("DIRECTION: "); if (direction == DIRECTION_CW) Serial.print("Clockwise"); else Serial.print("Counter-clockwise"); Serial.print(" | COUNTER: "); Serial.println(counter); } // save last CLK state prev_CLK_state = CLK_state; if (button.isPressed()) { Serial.println("The button is pressed"); } }

우리는 ezButton 라이브러리를 사용하여 버튼 디바운싱 코드를 더욱 간단하게 만듭니다.

Detailed Instructions

다음 지침을 단계별로 따르세요:

  • Arduino Uno R4 WiFi/Minima를 처음 사용하는 경우, Arduino IDE에서 Arduino Uno R4 WiFi/Minima 환경 설정에 대한 튜토리얼을 참조하십시오.
  • 제공된 다이어그램에 따라 로터리 인코더를 Arduino UNO R4에 연결합니다.
  • USB 케이블을 사용하여 Arduino Uno R4 보드를 컴퓨터에 연결합니다.
  • 컴퓨터에서 Arduino IDE를 실행합니다.
  • 적절한 Arduino Uno R4 보드(예: Arduino Uno R4 WiFi) 및 COM 포트를 선택합니다.
  • EzButton 라이브러리를 Arduino IDE에 추가합니다. 지침은 다음 링크를 방문하십시오: ezButton 라이브러리
  • 제공된 코드를 복사하여 Arduino IDE에서 엽니다.
  • Arduino IDE에서 Upload 버튼을 클릭하여 코드를 Arduino UNO R4에 로드합니다.
  • 노브를 시계 방향 및 시계 반대 방향으로 회전시킵니다.
  • 노브를 누릅니다.
  • 시리얼 모니터에서 결과를 확인합니다.
COM6
Send
DIRECTION: Clockwise | COUNTER: 1 DIRECTION: Clockwise | COUNTER: 2 DIRECTION: Clockwise | COUNTER: 3 DIRECTION: Clockwise | COUNTER: 4 DIRECTION: Clockwise | COUNTER: 5 DIRECTION: Counter-clockwise | COUNTER: 4 DIRECTION: Counter-clockwise | COUNTER: 3 DIRECTION: Counter-clockwise | COUNTER: 2 DIRECTION: Counter-clockwise | COUNTER: 1 DIRECTION: Counter-clockwise | COUNTER: 0 The button is pressed
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

코드 설명

코드의 각 줄에 있는 주석을 보세요.

Arduino UNO R4 코드 – 인터럽트를 사용한 로터리 엔코더

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

  • Arduino UNO R4 자원을 비효율적으로 사용합니다.
  • 다른 코드가 실행되는 데 너무 오래 걸리면 일부 카운트가 건너뛰어질 수 있습니다.

이를 제어하는 하나의 방법은 인터럽트를 통해서입니다. 인터럽트는 특정 이벤트를 지속적으로 확인해야 하는 필요성을 피하는 데 도움을 줍니다. 이를 통해 Arduino UNO R4는 이벤트를 모니터링하면서도 다른 작업을 수행할 수 있습니다.

다음 코드를 보면서 인터럽트를 사용하여 인코더에서 값을 읽는 방법을 알아봅시다.

/* * 이 Arduino UNO R4 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO R4 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-r4/arduino-uno-r4-rotary-encoder */ #include <ezButton.h> // the library to use for SW pin #define CLK_PIN 2 // The Arduino UNO R4 pin connected to the CLK pin of encoder #define DT_PIN 3 // The Arduino UNO R4 pin connected to the DT pin of encoder #define SW_PIN 4 // The Arduino UNO R4 pin connected to the SW pin of encoder #define DIRECTION_CW 0 // clockwise direction #define DIRECTION_CCW 1 // counter-clockwise direction volatile int counter = 0; volatile int direction = DIRECTION_CW; volatile unsigned long last_time; // for debouncing int prev_counter; ezButton button(SW_PIN); // create ezButton object that attach to pin 4 void setup() { Serial.begin(9600); // configure encoder pins as inputs pinMode(CLK_PIN, INPUT); pinMode(DT_PIN, INPUT); button.setDebounceTime(50); // set debounce time to 50 milliseconds // use interrupt for CLK pin is enough // call ISR_encoderChange() when CLK pin changes from LOW to HIGH attachInterrupt(digitalPinToInterrupt(CLK_PIN), ISR_encoderChange, RISING); } void loop() { button.loop(); // MUST call the loop() function first if (prev_counter != counter) { Serial.print("DIRECTION: "); if (direction == DIRECTION_CW) Serial.print("Clockwise"); else Serial.print("Counter-clockwise"); Serial.print(" | COUNTER: "); Serial.println(counter); prev_counter = counter; } if (button.isPressed()) { Serial.println("The button is pressed"); } // TO DO: your other work here } void ISR_encoderChange() { if ((millis() - last_time) < 50) // debounce time is 50ms return; if (digitalRead(DT_PIN) == HIGH) { // the encoder is rotating in counter-clockwise direction => decrease the counter counter--; direction = DIRECTION_CCW; } else { // the encoder is rotating in clockwise direction => increase the counter counter++; direction = DIRECTION_CW; } last_time = millis(); }
  • 제공된 코드를 복사하여 Arduino IDE에서 엽니다.
  • Arduino IDE에서 Upload 버튼을 클릭하여 코드를 Arduino UNO R4에 로드합니다.

이제 다이얼을 돌리면 이전 코드에서 보았던 것과 유사하게 직렬 모니터에 정보가 표시됩니다.

※ NOTE THAT:

  • Arduino UNO R4에 인코더의 CLK 핀을 인터럽트를 사용하여 연결하려면 핀 2 또는 3을 사용해야 합니다. 이 핀들만 인터럽트를 지원합니다.
  • 일부 온라인 가이드에서는 하나의 엔코더에 두 개의 인터럽트를 사용하는 것을 제안할 수 있지만, 이는 필요하지 않습니다. 하나의 인터럽트만 사용하는 것으로 충분합니다.
  • 글로벌 변수에 인터럽트를 사용할 때는 volatile 키워드를 반드시 사용하여 문제를 피해야 합니다.
  • 인터럽트 내부의 프로그래밍은 간단하게 유지하십시오. Serial.print() 또는 Serial.println()을 사용하지 마십시오.

Video Tutorial

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

관련 튜토리얼

※ OUR MESSAGES

  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!