STM32正交編碼器驅動電機


1。編碼器原理
       什么是正交?如果兩個信號相位相差90度,則這兩個信號稱為正交。由於兩個信號相差90度,因此可以根據兩個信號哪個先哪個后來判斷方向。

 

 

 

這里使用了TI12模式,例如當T1上升沿,T2在低電平時;T1下降沿,T2在高電平時,向上計數,這樣的好處是當有毛刺產生的時候,會自動+1 -1過濾掉毛刺。

2。編碼器的中斷

由於編碼器是基於定時器的,所以編碼器的中斷實際上就是定時器的中斷。也就是說定時器是每隔一定時間加一個數(或減一個數 ),當數到達預設值時就產生中斷,而編碼器是每一個有效脈沖就加一個數(或減一個數 ),當數到達預設值時就產生中斷。若預設值為1000則編碼器與定時器中斷不同的是,當編碼器反轉時值到達999產生一次中斷,而當編碼器正轉到達0時同 樣產生一次中斷。在硬件上這兩個中斷是沒法區分的,這也就造成了有種情況的誤判。

3。STM32編碼器沒有考慮的情況

想象一下,如果編碼器的預設值為1000,當某次我們使得編碼器正轉產生中斷后,立即反轉則又該怎么辦呢?根據上面的說法,這時候會產生兩次一樣的中斷。 如果在算法上沒有處理的話,極有可能認為是行走了兩次正向。但實際上並沒有。所以這個時候必須結合方向來判斷行走的情況(判斷方向使用的是DIR寄存器 位)或者在產生中斷后讀一次count寄存器位(看看是999還是0,以此來判斷當前的方向)。只有上一次為正且這一次同樣為正,距離才是相加的。

4。STM32f1系列定時器16位的問題

我用STM32的定時器3工作於編碼器方式,可以正常得到編碼器位置,但由於現在只有16位計數,位數不夠,我想擴展到32位,可以先用定時器內部連接,將定時器3 的溢出送到定時器2,用定時器2做高位,在正轉的時候正常,但反向的時候出錯。換了個思路,做個每10ms產生一次的中斷,在中斷中調用下面的代碼,下述代碼中MAX_COUNT是 比 10ms內可能出現的計數最大值還要大的值,ENCODER_TIM_PERIOD是定時器的period值,最好比MAX_COUNT大,然后定義一個32位的有符號變量,如currentCount,然后每隔10ms執行一次currentCount += Enc_GetCount();只需要去讀取currentCount的值就可以得到位移信息了。

s16   Enc_GetCount(void)
{
    static  u16   lastCount = 0;
    u16  curCount = ENCODER_TIM->CNT;
    s32 dAngle = curCount - lastCount;
    if(dAngle >= MAX_COUNT){
      dAngle -= ENCODER_TIM_PERIOD;
    }else if(dAngle < -MAX_COUNT){
      dAngle += ENCODER_TIM_PERIOD;
    }
    lastCount = curCount;
    return (s16)dAngle;
}

5。其它一些得到的信息

1.編碼器有個轉速上限,超過這個上限是不能正常工作的,這個是硬件的限制,原則上線數越多轉速就越低,這點在選型時要注意,編碼器的輸出一般是開漏的,所以單片機的io一定要上拉輸入狀態.
2.定時器初始化好以后,任何時候CNT寄存器的值就是編碼器的位置信息,正轉他會加反轉他會減這部分是不需要軟件干預的,初始化時給的TIM_Period 值應該是碼盤整圈的刻度值,在減溢出會自動修正為這個數.加超過此數值就回0.
3.如果要擴展成多圈計數需要溢出中斷,程序上圈計數加減方向位就行了.
4.每個定時器的輸入腳可以通過軟件設定濾波
5.應用中如果沒有絕對位置信號或者初始化完成后還沒有收到絕對位置信號前的計數只能是相對計數.收到絕對位置信號后重新修改一次CNT的值就行了.碼盤一般都有零位置信號,結合到定時器捕獲輸入就行.上電以后要往返運動一下找到這個位置.
6.即便有濾波計數值偶爾也會有出錯誤的情況,一圈多計一個或少計一個數都是很正常的特別是轉速比較高的時候尤其明顯,有個絕對位置信號做修正是很有必要的.絕對位置信號不需要一定在零位置點,收到這個信號就將CNT修正為一個固定的數值即可.
7.開啟定時器的輸入中斷可以達到每個步計數都作處理的效果,但是高速運轉的時候你可能處理不過來.


免責聲明!

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



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