AVR單片機教程——旋轉編碼器


本文隸屬於AVR單片機教程系列。

 

好久沒寫這個系列了。今天講講旋轉編碼器。

旋轉編碼器好像不是單片機玩家很常用的器件,但是我們的開發板上有,原因如下:

  1. 旋轉編碼器挺好用的。電位器能旋轉的角度有限,旋轉編碼器可以無限圈旋轉;旋轉時不連續,有卡點,適合對應離散數據。

  2. 開發板上選用的旋轉編碼器,使用起來簡單、方便。

  3. 本來旁邊的電位器(旋鈕,以后會講)一枝獨秀,挺孤單的,我就配一個高度大致相同的旋轉編碼器陪伴它。

今天我想寫旋轉編碼器,於是在網絡上搜索了一下,相關資料很少。最基本地,旋轉編碼器的作用是將角位移、角速度等機械量轉換為電信號。本文不求成為旋轉編碼器的百科全書,但會把 觸點電刷式 增量式 旋轉編碼器的原理講清楚。這里出現了兩個定語,是對類別的限定;關於旋轉編碼器的分類,請自行百度。

開發板上的旋轉編碼器是從淘寶買的,淘寶商家提供了資料,這是本講的主題。為避免廣告嫌疑,我不能放鏈接上來,所以我就把它轉換成圖片放在文章里(請在新頁面中查看):

我們從旋轉編碼器的原理開始。旋轉編碼器的內部是觸點與電刷,可以看作按鍵:當兩者接觸時,開關閉合;反之斷開。實際上它們的本質是一樣的。在旋轉時,按鍵會周期性地閉合、斷開;如果一端接地,另一端接上拉電阻,就會有周期性高、低電平的脈沖信號產生。我們使用的旋轉編碼器每轉過一圈會輸出24個脈沖。

通過對脈沖進行計數,可以知道編碼器轉過的角度。如果不管方向,測量角度或角加速度等,用一個輸出就夠了。但是如果考慮方向,無論是順時針還是逆時針轉動,電平都是“高低高低高……”。為了獲得方向的信息,需要使用兩個輸出,它們的相位相差90°,如圖所示:

A和B是兩個輸出端,C端接地。當程序檢測到A端由高電平變為低電平時(方法在按鍵那里講過了),如果檢測到B端是高電平(這就更簡單了),那就是順時針旋轉;如果是低電平,那就是逆時針旋轉。實際上不一定要檢測A端的下降沿,只要按照這張圖來,怎么都對。

庫函數使用的檢測方法是:A、B端由低低變為高低時,判為順時針轉過一格;由低低變為低高時,判為逆時針轉過一格。這不是最好的方法(你可以想一下怎樣改進,但是不要低估它的難度),但從實際使用上來看,只要用戶不故意在兩個卡點之間扭來扭去,這種方法是可以勝任的。

我們寫一個用旋轉編碼器控制數碼管顯示數字的程序,也可以理解為對旋轉編碼器進行計數並用數碼管顯示。旋轉編碼器A和B端分別連接端口4和5,數碼管連接6和7。程序的思路是:每隔一毫秒調用rotary_rotated(它和button_pressed函數類似——如果你還記得的話)檢測編碼器是否被轉動以及轉動的方向,並根據方向對計數器變量num進行增減。(為什么讓numuint8_t類型?)為了凸顯旋轉編碼器的主題,數碼管就用segment_auto來解決了。

#include <ee1/delay.h>
#include <ee1/rotary.h>
#include <ee1/segment.h>

int main()
{
    rotary_init(PIN_4, PIN_5);
    segment_init(PIN_6, PIN_7);
    segment_auto();
    uint8_t num = 0;
    while (1)
    {
        switch (rotary_rotated())
        {
        case ROTARY_CW:
            ++num;
            break;
        case ROTARY_ACW:
            --num;
            break;
        default:
            break;
        }
        segment_hex(num);
        delay(1);
    }
}

注意相鄰卡點之間擠了4個AB端口的狀態,因此延時不能過長。你可以試試更長的間隔。

作業:對於旋轉編碼器,直接檢測IO口電平;對於數碼管,使用“原始”的動態掃描,即不要用segment_auto();重寫樣例。(提示:你可以分別完成兩個要求,然后合並。)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM