增量式編碼器專題


編碼器簡介

編碼器(encoder)把角位移或直線位移轉換成電信號,前者稱為碼盤,后者稱為碼尺。

按照工作原理編碼器可分為增量式和絕對式兩類:

①增量式編碼器: 將位移轉換成周期性的電信號,再把這個電信號轉變成計數脈沖,用脈沖的個數表示位移的大小。通常為A相、B相、Z相輸出,A相、B相為相互延遲1/4周期的脈沖輸出,根據延遲關系可以區別正反轉,而且通過取A相、B相的上升和下降沿可以進行2或4倍頻;Z相為單圈脈沖,即每圈發出一個脈沖。

②絕對式編碼器: 每一個位置對應一個確定的數字碼,因此它的示值只與測量的起始和終止位置有關,而與測量的中間過程無關。

這里僅介紹旋轉式增量編碼器的使用。


兩種增量式編碼器

使用歐姆龍E6B2-CWZ6C 1000P/R編碼器(輸出A、B、Z三相)和ASLONG JGA25-371直流減速電機(帶334線編碼器),為使原理清晰,選用最常見的51單片機(IAP15F2K61S2)測試。

歐姆龍E6B2-CWZ6C 1000P/R編碼器外形如下: 
l01

參數表如下: 
l02

ASLONG JGA25-371直流減速電機外形如下(左邊的兩根黃線是電機引線,綠色和白色線是兩組脈沖輸出線,下面的未經減速的直流電機每轉1周輸出334個脈沖,用一根線就能測量轉速,雙脈沖可以判斷旋轉方向,紅色的線接3V至5V電源給測速芯片供電,黑色線接地): 
l03

參數表為: 
l04

以該電機為例看一下增量式編碼器的特性:

接線如下(紅黑鱷魚夾為0~15V可調電源,為電機供電;排陣為5V電源為編碼器測速元件供電;示波器探頭連接到編碼器的A、B輸出相上) 
l05

電壓加到11V,正轉(左圖)和反轉(右圖)波形如下: 
l06

可以看出,輸出脈沖很穩定,正轉時A相超前於B相1/4個周期,反轉時B相超前於A相1/4周期。脈沖頻率約為21.3kHz,又知道電機的轉速比為21.3,減速前轉一周輸出334個脈沖,則電機的輸出轉速為: 
l07


編碼器測位置、測轉速、測角加速度原理

測位置

編碼器每周的脈沖數是一定的,通過記錄初始位置和轉過的脈沖數可以計算轉過的角度。當然,為了減小單片機的運算量,沒必要換算成角度。如1000線的編碼器輸出500個脈沖,那么我們知道轉了半圈,而沒必要先換算成180度,再除以360度等於半圈。

擁有固定起始位置的裝置,可以用增量式編碼器測角度。如倒立擺,其起始位置為自然下垂。然而,像舵機或者機器人的關節的角度測量有時並沒有絕對位置,用增量式編碼器就顯得局限了(除非可以解決初始位置的問題),這種情況下用電位器或絕對式編碼器是不錯的選擇。

測轉速

增量式編碼器有測頻率(M法)和測周期(T法)以及兩種結合的M/T法(高速時M法,低速時T法)。

M法測速:記取一個采樣周期Tc內旋轉編碼器發出的脈沖個數M來算出轉速n。適用於轉速較高、脈沖輸出比較快的情況。原理用數學上說就是:位置的微分等於速度,角度的微分得到轉速。計算公式如下(這里沒有考慮減速比): 
l08 
式中:

  • n—轉速,r/min;
  • Tc—采樣周期,s;
  • M1—時間Tc內的脈沖個數;
  • Z—旋轉編碼器每轉輸出的脈沖個數。

T法測速:測出編碼器兩個輸出脈沖之間的時間間隔來計算出轉速n。 
由於Tc和Z為常數,所以n與M1成正比,故稱M法測速。適用於轉速較低、脈沖輸出較慢的情況。計算公式如下: 
l09 
式中:

  • M2—編碼器兩個脈沖之間的時鍾脈沖個數;
  • f0—時鍾脈沖頻率,Hz。

測角加速度

轉速的微分為角加速度: 
l10 
式中

  • aω—角加速度;
  • nk—本次測量的轉速;
  • nk-1—上一次的轉速;
  • Tc—采樣周期。

單片機編程實現原理

單片機對外唯一需要做的是捕獲脈沖。

脈沖捕獲的方法

①定時器的計數器模式,來一個脈沖計一個數(傳統的51單片機都有Timer0、Timer1,STC89C52和IAP15F2K61S2均有Timer2,STC12系列沒有Timer2。STM32的定時器有一大堆,當然只當計數器浪費了,因為其可以配置為正交編碼模式)。

②外部中斷(一般都有INT0、INT1,有的有INT2、INT3等),如STC89C52有INT0、INT1,支持下降沿觸發和低電平觸發。IAPF2K61S2有INT0~4共5路外部中斷,其中INT0和INT1支持上升沿或下降沿均可觸發方式和僅下降沿觸發方式、INT2、INT3和INT4僅支持下降沿觸發模式。

③PCA (可編程計數器陣列Programmable Counter Array)脈沖捕獲(STC12C5A有2路、STC12C56有4路、STC15F2K有3路。STM32的普通定時器即可實現脈沖捕獲)。

使用IAP15F2K61S2測10個編碼器的速度

使用一個定時器做時基定時器測速,剩余的2個定時器計數器+5路外部中斷+3路PCA=10路編碼器測速,再占用10個IO口可以判斷編碼器旋轉方向。其中INT0、INT1、3路PCA是可以編碼器2倍頻的,下面會有解釋。

采樣周期Tc

因為編碼器運算一次也是定時器中斷一次,所以,采樣周期Tc其實就是時基定時器的中斷時間,或者中斷時間的倍數。

關於倍頻

1倍頻:僅對編碼器一相輸出進行上升沿或下降沿捕獲。則1000線編碼器轉1圈僅捕獲1000個脈沖。

2倍頻:對編碼器一相上升沿和下降沿均捕獲,或者對兩相的編碼器進行一個邊沿捕獲(這個很少用),則1000線編碼器轉1圈可以捕獲2000個脈沖。一般有的外部中斷中和PCA支持上升沿、下降沿同時捕獲。

4倍頻:對編碼器A、B相的上升沿和下降沿均捕獲。這樣1000線的編碼器轉1圈可以捕獲到4000個脈沖,精度大大提高。(對於STC12或者IAP15F2K61S2,使用兩路PCA進行脈沖捕獲,配置為上升下降均中斷。對於STM32可以直接把定時器配置為正交編碼接口,上下沿均采樣,一個定時器搞定一個編碼器)。

由以上分析可知:

對於擁有3個定時器、2個外部中斷(貼片的有4個外部中斷)的直插式STC89C52來說,僅測位置的話,可以1倍頻測量多達5個編碼器的位置。

對於擁有6個定時器(含3路PCA)、5個外部中斷的IAP15F2K61S2來說,僅測位置的話,可以1倍頻測量多達11個編碼器的位置。其中,3路PCA、2個外部中斷支持上升沿和下降沿均捕獲,可以配置成2倍頻或4倍頻測量。

如果需要測量速度,則需要犧牲一個定時器作為時基,定時(轉速公式中的采樣周期Tc)中斷來測速,如若中斷中10ms查詢一次,則Tc=0.01s。即每10ms計算一次速度。 
當然,如果需要Z相的話,可能需要再犧牲一路。


需要考慮的問題

為什么要考慮中斷優先級

STC15W4K60S4系列單片機的中斷優先級如下: 
l11

為什么要考慮中斷優先級?假設使用中斷優先級為7的PCA進行脈沖捕獲,頻率為25kHz,即40μs進一次PCA中斷;此時,若又有一個優先級為1的定時器0中斷,且其內部程序執行時間大於40μs,則會出現丟脈沖現象。所以,一般所有中斷中的程序加起來的時間不宜超過最大的編碼器脈沖輸出頻率的倒數。

當然,對於進去就關總中斷的流氓函數來說,其執行時間最好不要超過所有脈沖捕獲的間隔。

倍頻是否一定好

倍頻可以獲得更高的位置精度,如1000線的編碼器1倍頻的分辨率為360/1000=0.36度,2倍頻的分辨率為360/2000=0.18度,4倍頻的分辨率為360/4000=0.09度。這是很誘人的。

但上節中已經介紹,所有中斷中的程序加起來的時間不宜超過最大的編碼器脈沖輸出頻率的倒數。2倍頻則意味着這個時間縮短了一倍,頻繁的中斷會極大的影響CPU做其它工作。所以精度滿足的情況下,沒必要追求更高的倍頻。

51單片機的using

對於51單片機(STM32請繞過),如我們寫定時器1中斷函數時,常寫:void tm1_isr() interrupt 3 using 1。其中3是Timer1的中斷優先級,那么using后的1呢?

using是C51中的關鍵字,keil的help中給出了using的解釋:

In all members of the 8051 family, the first 32 bytes of DATA memory (0x00-0x1F) is grouped into 4 banks of 8 registers each. Programs access these registers as R0-R7. The register bank is selected by two bits of the program status word, PSW. 
Register banks are useful when processing interrupts or when using a real-time operating system because the MCU can switch to a different register bank for a task or interrupt rather than saving all 8 registers on the stack. The MCU can then restore switch back to the original register bank before returning.

所以,我們可以在中斷函數分配寄存器組(using 0~3,主函數默認使用0,則其他中斷可以使用寄存器組1~3)來省去壓棧的時間,加快中斷的切換速度。當然,using可以修飾任何函數,不過建議只用來修飾中斷函數。同級中斷設成同樣的寄存器組。中斷中調用的函數最好不要被中斷意外的其他函數調用,否則會出現“重復調用”的警告。盡管可以用reentrant來修飾,但會占用大量堆棧空間。當然,也可以分成兩個不同名的函數寫。有時使用using會帶來“莫名其妙”的錯誤,在中斷中被調用的函數最好使用using指定與中斷函數相同的寄存器組。因此,對using關鍵字的使用,如果沒把握,寧可不用,交給編譯系統自己去處理好了。


編碼器測速編程舉例

使用定時器的計數器模式測速度

演示程序給出了定時器0作基准定時器,計數器1捕獲脈沖的測速方法, 先設置定時器1的計數器模式(timer.c,注意不要使能定時器2的中斷):

void Timer_Init(unsigned int T_N100us) //百微秒 { unsigned int T_100us; // AUXR |= 0x80; //定時器0為1T模式 //33.1776MHz下最多1.97ms // T_100us = 65536-FOSC/10000*T_N100us; //1T模式 AUXR &= 0x7f; //定時器0為12T模式 //33.1776MHz下最多23.7ms T_100us = 65536-FOSC/12/10000*T_N100us; //12T模式 // TMOD = 0x00; //設置定時器為模式0(16位自動重裝載) TMOD= 0x40; //設置定時器為模式0(16位自動重裝載),定時器1為計數器模式 TL0 = T_100us; //初始化計時值 TH0 = T_100us >> 8; TL1 = 0x01; TH1 = 0x01; TR0 = 1; //定時器0開始計時 TR1 = 1; //定時器1開始計數 ET0 = 1; //使能定時器0中斷 EA = 1; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

然后在定時器0中斷(interrupt.c)中判斷速度(程序中得出1s輸出的脈沖數Freq):

//使用Aslong的JGA25-371直流減速電機:334線編碼器,減速比為 21.3,12V額定電壓,額定轉速201rpm //那么額定轉速下10ms輸出脈沖數:201*21.3*334/60/100=238.3257個脈沖 unsigned char ch,cl; static unsigned int temp=0; static unsigned int temp_1=0; //上次的值 cl=TL1; //先讀低位(高位變得沒那么快) ch=TH1; temp_1=temp; temp=ch*256+cl; //用左移怎么實現? ch<<8+cl //if(temp>=temp_1) Freq=(temp-temp_1)/5; // *200/1000 kHz //20kHz 每5ms 計100個數 //else Freq=(65536-temp_1 + temp)/5; if(temp>=temp_1) Freq=(temp-temp_1)*100; //1s的脈沖數,即頻率 else Freq=(65536-temp_1 + temp)*100;


免責聲明!

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



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