旋轉編碼器的應用很廣泛,我們家的音響音量及功能選項轉鈕就是其中一個例子,想要用在 Arduino 的實作上,結合長條型 10 段 LED 顯示器,來控制 LED 的顯示數量,有點類似音響的音量大小顯示。由於有10個 LED,如要接在 Uno板上,會用掉太多的 Pin 腳,如加上旋轉編碼器,至少要 12個。本實作加入兩個 74HC595N 八位元的暫存器,來控制 10 個 LED,以下是製作的過程。
旋轉編碼器可分為絕對型(absolute)編碼器及增量型(incremental)編碼器兩種。增量型編碼器也稱作相對型編碼器(relative encoder),利用檢測脈衝的方式來計算轉速及位置,可輸出有關旋轉軸運動的資訊,一般會由其他裝置或電路進一步轉換為速度、距離、每分鐘轉速或位置的資訊。絕對型編碼器會輸出旋轉軸的位置,可視為一種角度傳感器。[維基百科]
旋轉編碼器可透過旋鈕旋轉,轉動過程中輸出脈冲的次數,旋轉圈數是没有限制的,不像可變電阻會有圈數限制。配合旋轉编碼器上的按鍵,可以回覆到初始狀態,即從0從新計數。
[旋轉編碼器]
旋轉編碼器 (rotary encoder)也稱為軸編碼器 (如下圖左方),是將旋轉位置或旋轉量轉換成類比或數位訊號的機電裝置。一般裝設在旋轉物體中垂直旋轉軸的一面。旋轉編碼器用在許多需要精確旋轉位置及速度的場合,如工業控制、機器人技術、專用鏡頭、電腦輸入裝置(如滑鼠及軌跡球)等。旋轉編碼器可分為絕對型(absolute)編碼器及增量型(incremental)編碼器兩種。增量型編碼器也稱作相對型編碼器(relative encoder),利用檢測脈衝的方式來計算轉速及位置,可輸出有關旋轉軸運動的資訊,一般會由其他裝置或電路進一步轉換為速度、距離、每分鐘轉速或位置的資訊。絕對型編碼器會輸出旋轉軸的位置,可視為一種角度傳感器。[維基百科]
旋轉編碼器可透過旋鈕旋轉,轉動過程中輸出脈冲的次數,旋轉圈數是没有限制的,不像可變電阻會有圈數限制。配合旋轉编碼器上的按鍵,可以回覆到初始狀態,即從0從新計數。
旋轉一圈被分為20小格,正轉逆轉皆可,當轉動時,CLK腳位就會呈低電位,此時可讀取DT資料腳位,若為HIGH代表正轉,LOW代表逆轉;SW則是開關腳位,轉軸可被按下改變此腳位的狀態。
• 74HC595N x 2
• 長條型 10 段 LED x 1
• 220歐姆電阻 x 10
• 麵包板 x 1
• 連接線 x 若干條
[74HC595N 移位暫存器 (Shift Register)]
74HC595是一個8位元串行輸入、並行輸出的位移緩存器:並行輸出爲三態輸出。在 SCK 的電位上升,串行數據由SDL輸入到內部的8位元位移緩衝器,並由 Q7 輸出,而並行輸出則是在 LCK 的電位上升時,將在8位元位移緩衝器的數據存入到8位並行輸出緩衝器。當串行數據輸入端 OE 的控制信號爲低電壓時,並行輸出端的輸出值等于並行輸出緩存器所存儲的值。而當 OE 爲高電位,也就是輸出關閉時,並行輸出端會維持在高阻抗狀態。[百度百科]- Q0--Q7: 八位元並行输出端,可以直接控制 LED 的8個段。
- Q7': 並聯输出端。可以連接第二個 74HC595 的 DS 端。
- DS: 串行資料输入端,可連接第一個 74HC595 的 Q7'。
- /MR(Pin 10):低電位時將移位暫存器的數據清為零。通常接到 VCC 防止數據被清除為零。
- SH_CP(Pin 11):電位上升時數據暫存器的數據移位。Q0 → Q1 →Q2 →Q3 →... →Q7;電位下降時移位暫存器數據不便。(脈衝寬度:5V時,大於十幾奈秒就可以了。)
- ST_CP(Pin 12):電位上升時移位暫存器的數據進入數據儲存暫存器,電位下降時儲存暫存器數據不變。通常會將 ST_CP 置於低電位,當移位结束後,在 ST_CP 端產生一個正脈衝( 5V时,大于幾十奈秒就行了),更新顯示數據。
- /OE(Pin 13):高電位時禁止輸出(高阻態)。如果開發板的引腳不多,可用一個引脚控制它,可以方便地產生閃爍和熄滅效果。比通過數據端移位控制要省時省力。
[材料]
• Arduino Uno x 1• 74HC595N x 2
• 長條型 10 段 LED x 1
• 220歐姆電阻 x 10
• 麵包板 x 1
• 連接線 x 若干條
[接線]
Arduino | 旋轉編碼器 |
---|---|
VIN | VCC(+) |
GND | GND |
Pin 4 | CLK |
Pin 5 | DT |
[程式]
// 旋轉編碼器輸入 #define inputCLK 4 #define inputDT 5 int counter = 0; int currentStateCLK; int previousStateCLK; // 設定 74HC595N 的接腳 int latchPin = 8; int clockPin = 12; int dataPin = 11; int numOfRegisters = 2; byte* registerState; long effectId = 0; long prevEffect = 0; long effectRepeat = 0; long effectSpeed = 30; String encdir =""; void regWrite(int pin, bool state){ // 決定是哪一個暫存器 int reg = pin / 8; // 決定哪一個暫存器的 Pin 腳 int actualPin = pin - (8 * reg); // 開始 session digitalWrite(latchPin, LOW); for (int i = 0; i < numOfRegisters; i++){ // 取得暫存器的實績狀態 byte* states = ®isterState[i]; // 更新狀態 if (i == reg){ bitWrite(*states, actualPin, state); } // 寫入 shiftOut(dataPin, clockPin, MSBFIRST, *states); } // 結束 session digitalWrite(latchPin, HIGH); } void setup() { // 設定編碼器 pins 當作輸入 pinMode (inputCLK,INPUT); pinMode (inputDT,INPUT); // 設定串列監控 Serial.begin (9600); // 讀取 inputCLK 的初始狀態,並指定給前一個變數 previousStateCLK = digitalRead(inputCLK); // 初始化陣列 registerState = new byte[numOfRegisters]; for (size_t i = 0; i < numOfRegisters; i++) { registerState[i] = 0; } // 設定 pins 輸出,可以控制位移暫存器 pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void loop() { // 讀取目前 inputCLK 的狀態 currentStateCLK = digitalRead(inputCLK); // 假使前次 inputCLK 跟目前狀態不同 if (currentStateCLK != previousStateCLK){ // 假使 inputDT 和 inputCLK 狀態不同 // 編碼器逆時鐘轉 if (digitalRead(inputDT) != currentStateCLK) { regWrite(counter, LOW); counter --; encdir ="CCW"; if (counter < 0){ regWrite(0, HIGH);} else { regWrite(counter, HIGH);} } else { // 編碼器轉向順時鐘方向 counter ++; encdir ="CW"; if (counter >10){ regWrite(10, HIGH);} else { regWrite(counter, HIGH);} } Serial.print("Direction: "); Serial.print(encdir); Serial.print(" -- Value: "); Serial.println(counter); } // 更新前一個 StateCLK 為目前狀態 previousStateCLK = currentStateCLK; }
[執行結果]
[參考資料]
- DroneBot Workshop:Using Rotary Encoders with Arduino
- How to Control a LOT of LEDs with Arduino & 74hc595
張貼留言