[實用小物] Rotary Encoder with Arduino

Morgan Ting
閱益如美
Published in
7 min readMar 21, 2023
Photo by Jorge Ramirez on Unsplash

Rotary Encoder 旋轉編碼器,是一種將機械位移轉換成類比或數位訊號的裝置。利用此特性可以用來偵測速度與位移量。本文章將介紹增量式旋轉編碼器 KY-040 模組並透過 Arduino IDE 進行實驗操作。

使用工具 / 材料

  1. Arduino UNO *1
  2. Rotary Encoder module KY-040

增量型旋轉編碼器簡介

Rotary Encoder 旋轉編碼器是一種藉由旋轉產生位移並轉換類比或數位訊號輸出的機械裝置。

藉由旋轉產生位移可以感測旋轉速度以及位移量。旋轉編碼器藉由編碼方式將感測數值輸出,編碼方式有絕對型編碼與增量型編碼,絕對型編碼對於每一步位移輸出特定編碼藉由查表可以得到目前旋轉位置,增量型編碼器結構上較為精簡,轉動時可以依訊號輸出得知轉動量與方向,但無法得知目前轉動位置為何。

增量型編碼器通常有兩個輸出假設為 A 與 B,AB 兩者輸出波形相差 90 度依裝置說明可以得知 AB 兩波型相位領先落後分別代表順時針轉動或是逆時針轉動。

A 相領先 B 項
B 項領先 A 項

KY-040 旋轉編碼器

KY-040 模組是一款增量型旋轉編碼器,其特性如下:

  1. 操作電壓 3 ~ 5 V。
  2. 可連續360 度旋轉,旋轉一圈總共 20 步。
  3. 2-Bit 格雷碼 ( gray code) 輸出。
  4. 內建 1 按鈕開關。
  5. A 相 、B 相 、按鈕開關皆設置 10 K 歐姆上拉電阻。
  6. 沒有去彈跳電容。

模組外觀

  • 圖中的 CLK 即為 A 相,DT 即為 B 相,SW 為按鈕開關 ( 轉軸往下壓 )。
  • + 號為電源輸入端,可依系統需求輸入 3 ~ 5 V。
  • GND 為共同接地端。
KY-040 Rotary Encoder Module

模組電路圖

KY-040 模組電路圖

電路圖

接線圖

實驗

本次實驗使用 Arduino UNO 開發板讀取旋轉編碼器的輸出狀態並進一步判別正轉或反轉,將增減量數值顯示在 Serial Monitor 上。

旋轉編碼器的正反轉檢測關鍵在於 A 相與 B 相的輸出波形相位何者領先,關於波形檢測可以使用輪詢法不斷讀取 I / O 腳位電位高低或是利用訊號變化觸發中斷。

從波形輸出相位圖來分析可以觀察到以下特徵:

  • A 相領先 B 相表示編碼器處於順時針選轉動狀態,A 相訊號為負緣 ( 波形由高往低變化 ) 時 B 相為 高電位。
  • B 相領先 A 相表示編碼器處於逆時針選轉動狀態,A 相訊號為負緣 ( 波形由高往低變化 ) 時 B 相為 低電位。

順時針轉動輸出波形

順時鐘波形

逆時針轉動輸出波形

逆時鐘波形

為何要關注 「 負緣 」狀態,因為模組的 A、B 兩相與按鈕開關都設有上拉電阻,當編碼器轉動時A 或 B 會先後與 C ( GND ) 接觸此時會得到低電位,又因為 A 、B 兩項波形相差 90 度因此關注 A 相的負緣狀態再檢測 B 相狀態即可了解編碼器正反轉。當然,檢測 B 相負緣再檢測 A 相電位狀態也可行,若要更精確就是 A 、B 兩項都觸發中斷來進行判別。

程式碼


#include<avr/io.h>
#include<avr/interrupt.h>
#define F_CPU 16000000UL
volatile int counter = 10;
volatile int Pre_state, Now_state;

void pin_init()
{
DDRD &= ~(1<<PD2); // PORTD2 as input
DDRD &= ~(1<<PD3); // PORTD3 as input
Pre_state = PIND & (1<<PD2); // read state of PORD2
}

void INT0_init()
{
EICRA |= (1<<ISC01); // The falling edge
EIMSK |= (1<<INT0); // Enable INT0
sei(); // Enable global interrupt
}

ISR(INT0_vect)
{
Now_state = PIND & (1<<PD2); // read state of PORD2

if(Now_state != Pre_state) // compare with pre_state of PORD2
{
if(Now_state) // PORD2 is HIGH
{
if(PIND & (1<<PD3)) counter --; // counterclockwise
else counter ++;
}
else
{
if(PIND & (1<<PD3)) counter ++; // clockwise
else counter --;
}
Serial.println(counter);
Pre_state = Now_state; // update state
}

}

int main()
{
pin_init();
INT0_init();
Serial.begin(9600);

while(1);
}

結果與總結

使用外部中斷偵測旋轉編碼器轉動狀態,由 PORD2 ( INT0 ) 作為中斷偵測腳位並且設定成「 負緣 」觸發,當 INT0 腳位電位由高變低時觸動中斷接著進入中斷服務函式 ISR(INT0_vect) 處理正反轉並將結果透過 Arduino IDE 的 Serial Monitor顯示。

顯示結果如下,在轉動旋轉編碼器時會發現偶爾會有不穩定狀態,例如數值跳兩次且數值出現非預期增減。

Result

機械型增量旋轉編碼器是一款經濟實惠的人機介面元件,用來作為輸入數值調整設定。

實驗總結如下:

  • 利用中斷方式偵測旋轉編碼器輸入狀態,相較於輪詢方式可以避免資源浪費。
  • 旋轉編碼器有 A、B 兩輸出相,可對其中一相進行偵測或偵測兩相。
  • 偵測單一輸出相並使用軟體去除彈跳 ( Debounce ) 仍會產生非預期增減量。

若文章有幫助到您可以拍手給我鼓勵,或是免費加入 Like Coin 帳戶並點擊拍手按鈕,免費支持我。

--

--

Morgan Ting
閱益如美

用好奇心探索世界。喜愛學習樂於分享。