<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【Arduino】旋轉編碼器的Arduino使用方法

      以前用CRT顯示器的時候,調整顯示器的時候用一個圓盤轉動和點擊的方法就可以實現選擇菜單和修改設置項的值,比多個按鈕的方式方便很多。

      鼠標滾輪也是這種操作方法,旋轉+點擊,只是方向不同。最近在網上買了旋轉編碼器模塊,想把它用到實際制作中。在網上找了很多資料,測試發現其中的代碼或多或少都有問題。于是決定自己研究一下旋轉編碼器的原理,只涉及高低電平應該會比較簡單。

      我買的旋轉編碼器模塊有5個引腳,分別是VCC, GND, SW, CLK, DT。其中VCC和GND用來接電源和地,按縮寫SW應該是Switch(開關)、CLK是Clock(時鐘)、DT是Data(數據)。

       

      網上的資料雖然代碼不是很理想,但介紹的原理基本是沒問題的。旋轉編碼器的操作是旋轉和按壓轉軸,在按下轉軸的時候SW引腳的電平會變化,旋轉的時候每轉動一步CLK和DT的電平是有規律的變化。在只接電源的情況下先測一下各種操作時引腳電平的變化,沒有示波器只好用萬用表測電壓。

      點擊:SW(紅)+GND(黑)時按下和松開按鈕沒有任何變化,VCC(紅)+SW(黑)松開時表針指向0,按下時高電平。據此可以推測SW平時為高阻態,按下時接地。用Arduino檢測的方法是設置連接SW的引腳為INPUT并上拉輸出高電平,檢測到引腳為低電平則表示按鈕按下,以下代碼可以正確檢測出按鈕的變化。

      //定義引腳連接
      int SW= 4;  // SW->D4
      bool lastButtonStatus = false;
       
      void setup()
      {
        pinMode(SW, INPUT);
        digitalWrite(SW, HIGH);//連接按鈕的引腳設為上拉
        Serial.begin(9600);
      }
       
      void loop()
      {
        bool buttonStatus = !digitalRead(SW);//高電平時未按下,狀態為false
        if (buttonStatus != lastButtonStatus)
        {
          Serial.println(buttonStatus ? "pressed" : "released");
          lastButtonStatus = buttonStatus;//保存當前狀態
        }
        delay(100);
      }

      旋轉:CLK(紅)+GND(黑),每旋轉一次(和方向無關),電平轉換一次,DT(紅)+GND(黑),變化情況和上一種情況一致,并且CLK和DT的電平保持一致。VCC(紅)+CLK(黑),VCC(紅)+DT(黑)也是同樣的情況。CLK(紅)+DT(黑)或者CLK(黑)+DT(紅)時,每次旋轉(和方向無關)指針都會輕微擺動然后歸零,并且相鄰兩步指針的擺動方向相反。結論:每次旋轉CLK和DAT引腳的電平都會變化,電平變化有時間差,但無法區分往哪個方向旋轉。

      編寫測試代碼,在按下按鈕的時候讀取CLK和DT的值:

       1 //定義引腳連接
       2 int CLK = 2;//CLK->D2
       3 int DT = 3;//DT->D3
       4 int SW = 4;//SW->D4
       5  
       6 void setup()
       7 {
       8   pinMode(SW, INPUT);
       9   digitalWrite(SW, HIGH);//連接按鈕的引腳設為上拉
      10   pinMode(CLK, INPUT);
      11   pinMode(DT, INPUT);
      12   Serial.begin(9600);
      13 }
      14  
      15 void loop()
      16 {
      17   if (!digitalRead(SW)) //讀取到按鈕按下時讀取CLK和DT的值
      18   {
      19     int clkValue = digitalRead(CLK);//讀取CLK引腳的電平
      20     int dtValue = digitalRead(DT);//讀取DT引腳的電平
      21     Serial.print("CLK:");
      22     Serial.print(clkValue);
      23     Serial.print("; DT:");
      24     Serial.println(dtValue);
      25     delay(1000);
      26   }
      27 }

      測試發現不管順時針還是逆時針旋轉,每次按下按鈕之后讀取的CLK和DT的值都是一樣的,并且相鄰兩步之間的值是不一樣的,符合用萬用表測量的結果。

      萬用表測量時發現CLK和DT的變化有一定的時間差,可以用Arduino在CLK電平變化的瞬間讀取DT的值,可能會找到其中的規律。改成通過中斷0監控CLK上的電平變化,讀取CLK和DT的電平值:

       1 //定義引腳連接
       2 int CLK = 2;//CLK->D2
       3 int DT = 3;//DT->D3
       4 const int interrupt0 = 0;// Interrupt 0 在 pin 2 上
       5  
       6 void setup()
       7 {
       8   pinMode(CLK, INPUT);
       9   pinMode(DT, INPUT);
      10   attachInterrupt(interrupt0, ClockChanged, CHANGE);//設置中斷0的處理函數,電平變化觸發
      11   Serial.begin(9600);
      12 }
      13  
      14 void loop()
      15 {
      16 }
      17  
      18 //中斷處理函數
      19 void ClockChanged()
      20 {
      21   int clkValue = digitalRead(CLK);//讀取CLK引腳的電平
      22   int dtValue = digitalRead(DT);//讀取DT引腳的電平
      23   Serial.print("CLK:");
      24   Serial.print(clkValue);
      25   Serial.print("; DT:");
      26   Serial.println(dtValue);
      27 }

      順時針旋轉一步:

      順時針旋轉3步(用橫線分隔):

      逆時針旋轉3步(用橫線分隔):

      根據以上測試結果,每旋轉一次觸發的中斷次數不一致,可能是硬件本身引起的,類似按鈕抖動。多次測試之后,查看每次變化的最后一組值,順時針旋轉時CLK和DT的值不一致,逆時針旋轉時CLK和DT的值一致。修改代碼,順時針時對計數值加1,逆時針時對計數值減1,按下按鈕時計數值清零。

       1 //定義引腳連接
       2 int CLK = 2;//CLK->D2
       3 int DT = 3;//DT->D3
       4 int SW = 4;//SW->D4
       5 const int interrupt0 = 0;// Interrupt 0 在 pin 2 上
       6 int count = 0;//計數值
       7 int lastCLK = 0;//CLK歷史值
       8  
       9 void setup()
      10 {
      11   pinMode(SW, INPUT);
      12   digitalWrite(SW, HIGH);
      13   pinMode(CLK, INPUT);
      14   pinMode(DT, INPUT);
      15   attachInterrupt(interrupt0, ClockChanged, CHANGE);//設置中斷0的處理函數,電平變化觸發
      16   Serial.begin(9600);
      17 }
      18  
      19 void loop()
      20 {
      21   if (!digitalRead(SW) && count != 0) //讀取到按鈕按下并且計數值不為0時把計數器清零
      22   {
      23     count = 0;
      24     Serial.print("count:");
      25     Serial.println(count);
      26   }
      27 }
      28  
      29 //中斷處理函數
      30 void ClockChanged()
      31 {
      32   int clkValue = digitalRead(CLK);//讀取CLK引腳的電平
      33   int dtValue = digitalRead(DT);//讀取DT引腳的電平
      34   if (lastCLK != clkValue)
      35   {
      36     lastCLK = clkValue;
      37     count += (clkValue != dtValue ? 1 : -1);//CLK和DT不一致時+1,否則-1
      38     Serial.print("count:");
      39     Serial.println(count);
      40   }
      41 }

      測試發現大多數時候可以正確輸出:


      偶爾旋轉不是很順暢會出現跳動的情況,這時候能感覺到旋鈕在兩步之間跳動了一下。看到有人說在引腳和地之間接上濾波電容會好一些,實際測試發現并沒有改善。推測由于旋鈕是D字型的,用手旋轉的時候確實會出現跳動的情況,裝上旋鈕帽之后應該會避免這種情況。

      旋轉編碼器可以用于需要精確調整值(電位器不準確),操作菜單等場合。后續會使用旋轉編碼器制作一些小東西,也歡迎大家分享旋轉編碼器相關代碼。

       

      posted @ 2015-11-21 21:32  Alex Leo  閱讀(23693)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 久久中精品中文字幕入口| 久久一区二区中文字幕| 成人免费在线播放av| 噜噜综合亚洲av中文无码| 激情四射激情五月综合网| av中文字幕在线二区| 2020久久香蕉国产线看观看 | 亚洲精品国产综合久久一线| 会同县| 亚洲高清aⅴ日本欧美视频| 在线精品自拍亚洲第一区| 国产成人午夜福利院| 欧美日本激情| 精品视频不卡免费观看| 精品综合久久久久久97| 无码人妻aⅴ一区二区三区蜜桃| 六十路熟妇乱子伦| 免费特黄夫妻生活片| 五月开心六月丁香综合色啪| 老太脱裤让老头玩ⅹxxxx| 黑森林福利视频导航| 男女激情一区二区三区| 欧美成人精品一级在线观看| 尹人香蕉久久99天天拍| caoporn成人免费公开| 精品精品亚洲高清a毛片| 大地资源高清播放在线观看| 性奴sm虐辱暴力视频网站| 爱色精品视频一区二区| 国产亚洲人成网站观看| 亚洲色一色噜一噜噜噜| 亚洲av午夜福利大精品| 亚洲国产成人精品无码区蜜柚| 一卡2卡三卡4卡免费网站| 视频一区二区三区刚刚碰| 一个人免费观看WWW在线视频| 国产精品天堂蜜av在线播放| 国产麻豆精品一区一区三区 | 久久精品高清一区二区三区| 色综合伊人色综合网站| 国产精品人妻中文字幕|