增量式編碼器是直接利用光電轉(zhuǎn)換原理輸出三組方波脈沖A、B和Z相;A、B兩組脈沖相位差90o,從而可方便地判斷出旋轉(zhuǎn)方向,而Z相為每轉(zhuǎn)一個脈沖,用于基準點定位。它的優(yōu)點是原理構(gòu)造簡單,機械平均壽命可在幾萬小時以上,抗干擾能力強,可靠性高,適合于長距離傳輸。其缺點是無法輸出軸轉(zhuǎn)動的絕對位置信息。增量式編碼器是一種測量設(shè)備轉(zhuǎn)動的傳感器,在電機驅(qū)動控制中得到廣泛應(yīng)用。
關(guān)鍵詞:SPMC75? 增量編碼器
1?引言
? 本文主要是講解SPMC75F2413A的PDC定時器模塊的增量碼盤接口功能,用這個接口可以測量增量碼盤轉(zhuǎn)軸的角位移,同時還可根據(jù)單位時間的角位移計算出增量碼盤轉(zhuǎn)軸的角速度,進而得到轉(zhuǎn)軸的轉(zhuǎn)速。本例使用的增量碼盤接口模式1,這是四倍頻接口模式,適合圖2-1中所示類型的波形。
2?系統(tǒng)框圖
系統(tǒng)結(jié)構(gòu)如圖2-1所示,主要由信源模擬發(fā)生模塊和速度測量模塊組成。兩個模塊均由SPMC75F2413A構(gòu)成。信源模擬發(fā)生模塊產(chǎn)生如中A、B所示的信號波形,A、B信號相差90度,圖中只示出了B超前A的情況,信號的頻率由電位器調(diào)整。
圖 2-1 系統(tǒng)結(jié)構(gòu)圖
?
3?增量編碼盤接口原理
3.1 設(shè)計原理
增量編碼盤是一種測量角位移增量的傳感器,根據(jù)其工作方式的不同可分為光電式、磁電式和純機械式等幾種,光電式和磁電式是現(xiàn)今最常用的方式。其中光電式用得最多是光電透射式,而磁電式主要是利用類式磁帶的原理在一個圓周上均布了N、S的磁信號,利用磁敏組件檢出信號。
SPMC75F2413A的增量編碼盤接口模式1工作原理如圖3-1所示:外部輸入信號TCLKA、TCLKB頻率相同但相位互差90度,其頻率與其轉(zhuǎn)速成正比,比例為增量編碼的細分數(shù)(每轉(zhuǎn)1轉(zhuǎn)所輸出的脈沖個數(shù))。而兩路信號的相位關(guān)系則代表了轉(zhuǎn)向信息。當TCLKA超前TCLKB時為正轉(zhuǎn),反之當TCLKA滯后TCLKB時為反轉(zhuǎn)。同時,由于這兩路信號是互差90度的,為了提高測量的精度,計數(shù)器是在兩路信號的跳變沿都計數(shù),而計數(shù)的方向則由兩路信號的相位關(guān)系確定。TCLKA超前時計數(shù)器增計數(shù),TCLKA滯后時計數(shù)器減計數(shù)。如此,用戶便可以得到從計數(shù)器開始計數(shù)后增量編碼轉(zhuǎn)軸的角位移量(如當增量編碼盤的細分數(shù)為N時,增量編碼盤的每一個脈沖代表的角位移為由于為四倍頻計數(shù),因此,當計數(shù)器的值為K時,所代表的角位移為)。同時,用戶可以通過測量單位時間內(nèi)的角位移而得到當前轉(zhuǎn)軸的轉(zhuǎn)速。其轉(zhuǎn)速為:
??????? ------(式3-1)
式中:為轉(zhuǎn)軸角速度;
為測量時間;
為內(nèi)的計數(shù)器增量;
N為碼盤的細分數(shù);
圖2-1 相位計數(shù)模式1
?
4?硬件說明
4.1 信號模擬發(fā)生電路
這部分電路如圖4-1所示,使用SPMC75F2413A的MCP3實現(xiàn)雙線增量碼盤輸出信號的模擬,并根據(jù)AD采集的數(shù)據(jù)設(shè)置信號的頻率和方向,以滿足系統(tǒng)測試的需要。
圖4-1信號模擬發(fā)生電路
4.2 測量接口電路
電路如圖4-2所示,這部分是本例的主體部分,它主要是利用SPMC75F2413A的PDC定時計數(shù)器的相位計數(shù)(碼盤接口)模式1完成位置信號的采集、速度的測量。為了提高測量精度,使用了四倍頻技術(shù)。
圖4-2測量接口電路
?
5?軟件說明
5.1 軟件說明
系統(tǒng)的軟件部分主要是系統(tǒng)所用到的硬件的初始化,并在硬件中斷時進行相應(yīng)的的處理。同時利用DMC的通信軟體庫完成與PC的通信,以便對系統(tǒng)狀態(tài)和結(jié)果進行監(jiān)控。
5.2 軟件流程
5.2.1?主程序流程
主程序在完成系統(tǒng)初始化以后,就不斷檢測有沒有來自PC的控制信息,如果有便完成相應(yīng)的控制功能,沒有就繼續(xù)檢測。同時將當前系統(tǒng)測得數(shù)據(jù)送入DMC接口區(qū),以便系統(tǒng)狀態(tài)的監(jiān)示。
圖5-1 主程序流程圖
5.2.2?中斷流程
中斷服務(wù)主要有三個,一個是系統(tǒng)通信中斷服務(wù),主要是在DMC庫中完成;一個是PDC定時器的溢出中斷服務(wù),在這里主要完成位置計數(shù)溢出的處理,以保證位置單元的正確性;最后一個是定時器的周期中斷服務(wù),這里主要完成當前位置信息的采集,同時根據(jù)位置增量計算當前的轉(zhuǎn)速。
5.3 程序代碼
使用SPMC75F2413A的PDC0的相位計數(shù)模式(即兩線增量碼盤接口)實現(xiàn)使用兩線增量碼盤測量電機轉(zhuǎn)速。
#include "Spmc75_regs.h" #include "mcMACRO.h" #include "Spmc75_dmc_uart_ext.h" #define Samp_Time 8 // 采樣定時器 , 單位 ms void Daly_Time(int Time); void PDC0_Init(void); void Time2_Init(void); static int Moto_Speed = 0; // 電機轉(zhuǎn)速 static int Over_flag = 0; // 位置計數(shù)器溢出標志 static int Encoder_Data = 256*4; // 編碼盤的細分常數(shù) // 電機絕對位置 ( 長整數(shù) , 為了計算方便 , 高低分開定義 ) static unsigned int Position_Count[2] = {0,0}; static unsigned int Old_Position_Count = 0; // 上一次電機位置 ( 低 16 位 ) //===================================================================== // ----Function: main(void); // -Description: 主函數(shù) // -----Returns: None // -------Notes: //===================================================================== main() { PDC0_Init(); Time2_Init(); MC75_DMC_UART_Setup(9600); INT_IRQ(); while(1) { MC75_DMC_UART_Service(); if(SPMC_DMC_Load_SpdCmd(1) > 0) Encoder_Data = SPMC_DMC_Load_SpdCmd(1)*4; SPMC_DMC_Save_SpdNow(1,Moto_Speed); } } //===================================================================== // ----Function: void PDC0_Init(void); // -Description: 定時器初始化 // --Parameters: None // -----Returns: None // -------Notes: //===================================================================== void PDC0_Init(void) { P_IOA_Dir->W &= 0xe7ff; // 設(shè)置用到的 IO 口 P_IOA_Attrib->W &= 0xe7ff; P_IOA_Buffer->W |= 0x1800; P_IOA_SPE->W |= 0x1800; P_TMR0_Ctrl->B.SPCK = CB_TMR0_SPCK_FCKdiv1; // 設(shè)置采樣時鐘為主系統(tǒng)時鐘 // 設(shè)置定時計數(shù)器模式為四倍頻增量碼盤接口 P_TMR0_Ctrl->B.MODE = CB_TMR0_MODE_Mode1; P_TMR0_Ctrl->B.CCLS = CB_TMR0_CCLS_Disabled; // 禁止計數(shù)器清除 P_TMR0_Ctrl->B.CKEGS = CB_TMR0_CKEGS_Rising; // 設(shè)定計數(shù)邊沿為上升沿 P_TMR0_Ctrl->B.TMRPS = CB_TMR0_TMRPS_FCKdiv1; // 設(shè)置時鐘 , 這是必需的 // 使能計數(shù)器的上溢下溢中斷 P_TMR0_INT->W |= CW_TMR0_TCUIE_Enable + CW_TMR0_TCVIE_Enable; P_TMR_Start->B.TMR0ST = 1; // 啟動定時器 } //===================================================================== // ----Function: void Time2_Init(void); // -Description: TMR2_module initialize function // --Parameters: None // -----Returns: None // -------Notes: //===================================================================== void Time2_Init(void) { P_TMR2_Ctrl->B.MODE = CB_TMR2_MODE_Normal; // 工作模式初始化為連續(xù)增計數(shù) P_TMR2_Ctrl->B.CCLS = CB_TMR2_CCLS_TPR; // 計數(shù)器清零源為周期匹配信號 P_TMR2_Ctrl->B.CKEGS = CB_TMR2_CKEGS_Rising; // 計數(shù)邊沿為上升沿 P_TMR2_Ctrl->B.TMRPS = CB_TMR2_TMRPS_FCKdiv4;// 計數(shù)時鐘為主時鐘的 1/4 P_TMR2_TPR->W = 6000*Samp_Time; // 定時周期設(shè)為 48000---8ms P_TMR2_INT->B.TPRIE = CB_TMR2_TPRIE_Enable; // 使能定時器的周期中斷 P_TMR_Start->B.TMR2ST = CB_TMR_TMR2ST_Start; // 啟動定時器 } //===================================================================== // Description: IRQ1 interrupt source is XXX,used to XXX // Notes: //===================================================================== void IRQ1(void) __attribute__ ((ISR)); void IRQ1(void) { if(P_TMR0_Status->B.TCUIF) { P_TMR0_Status->B.TCUIF = 1; //Clear TCUIF flag (int)Position_Count[1] --; // 位置計數(shù)下溢出 Over_flag = 1; } if(P_TMR0_Status->B.TCVIF) { P_TMR0_Status->B.TCVIF = 1; //Clear TCVIF flag (int)Position_Count[1] ++; // 位置計數(shù)上溢出 Over_flag = 1; } } //===================================================================== // Description: IRQ4 interrupt source is XXX,used to XXX // Notes: //===================================================================== void IRQ4(void) __attribute__ ((ISR)); void IRQ4(void) { long Temp; if(P_TMR2_Status->B.TPRIF) { P_TMR2_Status->B.TPRIF = 1; Position_Count[0] = P_TMR0_TCNT->W; if(Position_Count[0] < Old_Position_Count) // 計算位置增量 { if(Over_flag > 0) //1 正轉(zhuǎn) , 上溢 Temp = (0xffff - Old_Position_Count) + Position_Count[0] + 1; else //0 反轉(zhuǎn) , 沒有溢出 { Temp = Old_Position_Count - Position_Count[0]; Temp = -Temp; } } else { if(Over_flag > 0) // 反轉(zhuǎn) , 溢出 { Temp = (0xffff - Position_Count[0]) + Old_Position_Count + 1; Temp = - Temp; } else // 正轉(zhuǎn) , 沒有溢出 Temp = Position_Count[0] - Old_Position_Count; } Over_flag = 0; Old_Position_Count = Position_Count[0]; Moto_Speed = (int)((Temp*7500)/Encoder_Data);// 速度計算 } } //===================================================================== // Description: IRQ6 interrupt source is XXX,used to XXX // Notes: //===================================================================== void IRQ6(void) __attribute__ ((ISR)); void IRQ6(void) { if(P_UART_Status->B.RXIF && P_UART_Ctrl->B.RXIE) MC75_DMC_RcvStream(); } |
評論
查看更多