#Arduino
#Rotary Encoder
#編碼器
#旋轉編碼器
Rotary Encoder 在一般的儀器或者家電產品常常看到他的蹤影在此特別的說明一下他的原理與程式的實現。

Rotary Encoder 外觀

這一張圖是ENCODER的工作原理【橘色】的部分是接地片或這是電源片,A,B兩點是信號它是利用角度的時間差來判斷正傳或者是反轉的,我個人覺得他的圖畫的很好再次引用說明。
圖片來源:http://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/
【圖片版權屬該網站作者所有】

分別處於兩個角度當旋轉是ON、OFF就會輸出AB相位信號。

根據這個信號圖撰寫程式,程式如附檔這個程式有實測過是OK的

寫ENCODER程式會有幾個環節必須注意
外部中斷的設定方式:
Arduino 建議的語法如下:
attachInterrupt(digitalPinToInterrupt(18), interrupt1,RISING); //CHANGE);
必須使用這個語法才能動作,官方網站建議接腳的定義要寫這個【digitalPinToInterrupt(18)】,不能寫IO PORT
一般網路的寫法如下:
attachInterrupt(0, doEncoder, CHANGE); // encoder pin on interrupt 0 - pin 2
我在Arduino MEGA2560測試一直無法成功啓動外部中斷我不知道爲什麼,因爲無法看到compiler之後的組合語言所以無法得知爲什麼。
還有TOUCH功能和VR功能還沒有實現,繼續努力。

Arduino 範例:
void ENCODER_SUB(void)
{
if ((f_cw_start ==0)||(f_ccw_start==0))
{
// if(digitalRead(outputB)==1)
if (bit_is_set(P_ENC,BP_ENCB))
{
f_cw_start = 1;
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,RISING); //CHANGE);

} else{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,RISING); //CHANGE);
f_ccw_start = 1;
}
}

if ((f_cw_start ==1)||(f_ccw_start==1))
{
// if(digitalRead(outputB)==0)
if (bit_is_clear(P_ENC,BP_ENCB))
{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,FALLING); if(encoder_counter
{
encoder_counter++;
}else{
encoder_counter = 0;
}
f_cw_start = 0;


}else{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,FALLING);
if (encoder_counter >0)
{
encoder_counter--;
}else{
encoder_counter = 13;
}
f_ccw_start = 0;


}

}
Serial.print("Interrupt-->");
Serial.println(encoder_counter);
}

這個程式經過測試是OK的沒有漏格現象,但是由於我的Encoder他的AB相位只差1.3ms~3ms所以當你旋轉速度過快程式會反應不及,因爲Arduino的IO函數有延遲,使用我將digitalRead()改爲bit_is_set or bit_is_clear 兩個巨集指令。