2016年9月24日 星期六

Rotary Encoder的程式動作原理以及Arduino程式的實現

#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程式會有幾個環節必須注意
  1. 外部中斷的設定方式:
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 <13 div="">
{
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 兩個巨集指令。



2016年9月16日 星期五

使用Arduino 來偵測Rotary Encoder

# Arduino
# Rotary Encoder
# Interrutp
# Ext interrupt
# Arduino for Encoder
# Arduino for Rotary
# 兩個剪貼搞定 Rotary Encoder
使用Arduino來偵測Rotary Encoder 在網路的範例很多,但是他們似乎是不太適合我用,他們的方法,當我轉動Encoder會加二,或者會誤動作,讓人誤以爲Encoder不良,或者是漏格現象
針對這個問題我寫了一個即簡單有好用的程式碼在此公開給大家參考,如需要再改建,或者有錯誤,請讓我知道。
這是我們可以買得到的Rotary Encoder 

這個是Rotary Encoder的波形解析圖我的程式是來自於這張圖,在網路衆多圖片中我覺得這一張圖片畫的最好。

Encoder 和Arduino的接法【只是建議】,實際上的應用還是要以你的需要而定。
在硬體方面我的PinA是接在Arduino的外部中斷腳,PinB可以接在一般的Digital pin即可。
在Arduino的 Setup{

pinMode(outputB,INPUT); //設定19爲input
digitalWrite(outputB,HIGH); // 內部pull high 電阻開啓
attachInterrupt(digitalPinToInterrupt(outputA),ENCODER_SUB,FALLING);  
}
 宣告外部中斷。
外部中短的語法www.arduino.cc網站中建議使用
attachInterrupt(digitalPinToInterrupt(outputA),ENCODER_SUB,FALLING);
digitalPinToInterrupt(outputA)這個寫法在我這次的MEGA2560才有辦法啓動外部中斷
這一點要特別注意。

中斷的副程式內容如下:

void ENCODER_SUB(void)
{

if ((f_cw_start ==0)||(f_ccw_start==0))
{
if(digitalRead(outputB)==1)
{
f_cw_start = 1;
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,RISING);

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

if ((f_cw_start ==1)||(f_ccw_start==1))
{
if(digitalRead(outputB)==0)
{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,FALLING);
encoder_counter++;
f_cw_start = 0;

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


}

}

}

WEMOS D1 MINI ESP8266 製作 NTP + 網路斷線自動重置裝置

我的同事建議我將 NTP 加上網路斷線偵測可以重新reset的功能