// 旋轉編碼器 Rotary Encoder
// 用旋轉編碼器的旋轉方向和旋轉量,來操控一個十段 LED排燈
// https://sites.google.com/view/rayarduino/rotary-encoder
/*
#define CLK 2 //旋轉編碼器 CLK 連接 Arduino pin 2
#define DT 3 //旋轉編碼器 DT 連接 Arduino pin 3
#define SW 4 //旋轉編碼器 SW 連接 Arduino pin 4
#define LED1 5 //十段 LED 排燈連接 Arduino pins 5-13 及 A0
#define LED2 6
#define LED3 7
#define LED4 8
#define LED5 9
#define LED6 10
#define LED7 11
#define LED8 12
#define LED9 13
#define LED10 A0
int pin=2; //定義一些整數;
int count = 0;
int lastCLK = 0; //lastCLK 為旋轉編碼器 CLK 預設狀態 =0
void setup()
{
pinMode(SW, INPUT); //Arduino 預備讀入旋轉編碼器 CLK, DT, and SW 狀態
digitalWrite(SW, HIGH); //旋轉編碼器按鍵 SW為上拉電阻模式
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
//設置系統岔斷模式,當pin 2 輸入狀態有改變( CHANGE ) 時,呼叫副程式 ClockChanged()
attachInterrupt(digitalPinToInterrupt(pin), ClockChanged, CHANGE);
pinMode(LED1, OUTPUT); //Arduino 對外輸出電壓控制 十段 LED 排燈
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
pinMode(LED6, OUTPUT);
pinMode(LED7, OUTPUT);
pinMode(LED8, OUTPUT);
pinMode(LED9, OUTPUT);
pinMode(LED10, OUTPUT);
Serial.begin(9600);
}
//本程式 void loop() 唯一做的事,是當旋轉編碼器按鍵 SW 被按下時,系統重設,整數 count 歸零,熄滅所有LED燈。
void loop()
{
if (!digitalRead(SW) && count != 0)
{
count = 0;
Serial.print("count:");
Serial.println(count);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
digitalWrite(LED4, LOW);
digitalWrite(LED5, LOW);
digitalWrite(LED6, LOW);
digitalWrite(LED7, LOW);
digitalWrite(LED8, LOW);
digitalWrite(LED9, LOW);
digitalWrite(LED10, LOW);
}
}
void LedOutput(int value) //副程式 void LedOutput 。當輸入值 value 為 1 時,點亮一個LED燈;value 為 2 時,點亮兩個LED燈。依此類推。
{
digitalWrite(LED1, LOW); //先把所有LED關掉
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
digitalWrite(LED4, LOW);
digitalWrite(LED5, LOW);
digitalWrite(LED6, LOW);
digitalWrite(LED7, LOW);
digitalWrite(LED8, LOW);
digitalWrite(LED9, LOW);
digitalWrite(LED10, LOW);
if (value >= 1 && value <= 10) {
switch(value) {
case 1:
digitalWrite(LED1, HIGH);
break;
case 2:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
break;
case 3:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
break;
case 4:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
break;
case 5:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
break;
case 6:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
digitalWrite(LED6, HIGH);
break;
case 7:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
digitalWrite(LED6, HIGH);
digitalWrite(LED7, HIGH);
break;
case 8:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
digitalWrite(LED6, HIGH);
digitalWrite(LED7, HIGH);
digitalWrite(LED8, HIGH);
break;
case 9:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
digitalWrite(LED6, HIGH);
digitalWrite(LED7, HIGH);
digitalWrite(LED8, HIGH);
digitalWrite(LED9, HIGH);
break;
case 10:
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
digitalWrite(LED5, HIGH);
digitalWrite(LED6, HIGH);
digitalWrite(LED7, HIGH);
digitalWrite(LED8, HIGH);
digitalWrite(LED9, HIGH);
digitalWrite(LED10,HIGH);
break;
}
}
}
void ClockChanged() //副程式 void ClockChanged ()
{
int clkValue = digitalRead(CLK); // Arduino 讀入旋轉編碼器 CLK 狀態
int dtValue = digitalRead(DT); // Arduino 讀入旋轉編碼器 DT 狀態
if (lastCLK != clkValue)
{
lastCLK = clkValue;
count += (clkValue != dtValue ? 1 : -1); //旋轉編碼器順時針旋轉時,count +1;逆時針旋轉時, count -1
Serial.print("count:");
Serial.println(count);
int rcount = count/2; //旋轉編碼器轉一格,count 會被+2 ,LED 一次亮兩個; 為使旋轉編碼器轉一格, LED亮一個,故把 count÷2
LedOutput(rcount); //把 count ÷2 後的值 (rcount) 傳至副程式 LedOutput (value)
}
}
*/
// How Rotary Encoder Works and Interface It with Arduino
// https://lastminuteengineers.com/rotary-encoder-arduino-tutorial/#google_vignette
// Rotary Encoder Inputs
#define CLK 2
#define DT 3
#define SW 4
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
unsigned long lastButtonPress = 0;
void setup() {
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
currentDir ="CCW";
} else {
// Encoder is rotating CW so increment
counter ++;
currentDir ="CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Read the button state
int btnState = digitalRead(SW);
//If we detect LOW signal, button is pressed
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
Serial.println("Button pressed!");
}
// Remember last button press event
lastButtonPress = millis();
}
// Put in a slight delay to help debounce the reading
delay(1);
}
/*
// Rotary Encoder Inputs
#define CLK 2
#define DT 3
int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir ="";
void setup() {
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
// Call updateEncoder() when any high/low changed seen
// on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
}
void loop() {
//Do some useful stuff here
}
void updateEncoder(){
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
currentDir ="CCW";
} else {
// Encoder is rotating CW so increment
counter ++;
currentDir ="CW";
}
Serial.print("Direction: ");
Serial.print(currentDir);
Serial.print(" | Counter: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
}
*/
/*
// Include the Servo Library
#include <Servo.h>
// Rotary Encoder Inputs
#define CLK 2
#define DT 3
Servo servo;
int counter = 0;
int currentStateCLK;
int lastStateCLK;
void setup() {
// Set encoder pins as inputs
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
// Setup Serial Monitor
Serial.begin(9600);
// Attach servo on pin 9 to the servo object
servo.attach(9);
servo.write(counter);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
}
void loop() {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter --;
if (counter<0)
counter=0;
} else {
// Encoder is rotating CW so increment
counter ++;
if (counter>179)
counter=179;
}
// Move the servo
servo.write(counter);
Serial.print("Position: ");
Serial.println(counter);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
}
*/