增量式編碼器是直接利用光電轉換原理輸出三組方波脈沖A、B和Z相;A、B兩組脈沖相位差90o,從而可方便地判斷出旋轉方向,而Z相為每轉一個脈沖,用于基準點定位。它的優點是原理構造簡單,機械平均壽命可在幾萬小時以上,抗干擾能力強,可靠性高,適合于長距離傳輸。其缺點是無法輸出軸轉動的絕對位置信息。增量式編碼器是一種測量設備轉動的傳感器,在電機驅動控制中得到廣泛應用。
關鍵詞:SPMC75? 增量編碼器
1?引言
? 本文主要是講解SPMC75F2413A的PDC定時器模塊的增量碼盤接口功能,用這個接口可以測量增量碼盤轉軸的角位移,同時還可根據單位時間的角位移計算出增量碼盤轉軸的角速度,進而得到轉軸的轉速。本例使用的增量碼盤接口模式1,這是四倍頻接口模式,適合圖2-1中所示類型的波形。
2?系統框圖
系統結構如圖2-1所示,主要由信源模擬發生模塊和速度測量模塊組成。兩個模塊均由SPMC75F2413A構成。信源模擬發生模塊產生如中A、B所示的信號波形,A、B信號相差90度,圖中只示出了B超前A的情況,信號的頻率由電位器調整。
圖 2-1 系統結構圖
?
3?增量編碼盤接口原理
3.1 設計原理
增量編碼盤是一種測量角位移增量的傳感器,根據其工作方式的不同可分為光電式、磁電式和純機械式等幾種,光電式和磁電式是現今最常用的方式。其中光電式用得最多是光電透射式,而磁電式主要是利用類式磁帶的原理在一個圓周上均布了N、S的磁信號,利用磁敏組件檢出信號。
SPMC75F2413A的增量編碼盤接口模式1工作原理如圖3-1所示:外部輸入信號TCLKA、TCLKB頻率相同但相位互差90度,其頻率與其轉速成正比,比例為增量編碼的細分數(每轉1轉所輸出的脈沖個數)。而兩路信號的相位關系則代表了轉向信息。當TCLKA超前TCLKB時為正轉,反之當TCLKA滯后TCLKB時為反轉。同時,由于這兩路信號是互差90度的,為了提高測量的精度,計數器是在兩路信號的跳變沿都計數,而計數的方向則由兩路信號的相位關系確定。TCLKA超前時計數器增計數,TCLKA滯后時計數器減計數。如此,用戶便可以得到從計數器開始計數后增量編碼轉軸的角位移量(如當增量編碼盤的細分數為N時,增量編碼盤的每一個脈沖代表的角位移為由于為四倍頻計數,因此,當計數器的值為K時,所代表的角位移為)。同時,用戶可以通過測量單位時間內的角位移而得到當前轉軸的轉速。其轉速為:
??????? ------(式3-1)
式中:為轉軸角速度;
為測量時間;
為內的計數器增量;
N為碼盤的細分數;
圖2-1 相位計數模式1
?
4?硬件說明
4.1 信號模擬發生電路
這部分電路如圖4-1所示,使用SPMC75F2413A的MCP3實現雙線增量碼盤輸出信號的模擬,并根據AD采集的數據設置信號的頻率和方向,以滿足系統測試的需要。
圖4-1信號模擬發生電路
4.2 測量接口電路
電路如圖4-2所示,這部分是本例的主體部分,它主要是利用SPMC75F2413A的PDC定時計數器的相位計數(碼盤接口)模式1完成位置信號的采集、速度的測量。為了提高測量精度,使用了四倍頻技術。
圖4-2測量接口電路
?
5?軟件說明
5.1 軟件說明
系統的軟件部分主要是系統所用到的硬件的初始化,并在硬件中斷時進行相應的的處理。同時利用DMC的通信軟體庫完成與PC的通信,以便對系統狀態和結果進行監控。
5.2 軟件流程
5.2.1?主程序流程
主程序在完成系統初始化以后,就不斷檢測有沒有來自PC的控制信息,如果有便完成相應的控制功能,沒有就繼續檢測。同時將當前系統測得數據送入DMC接口區,以便系統狀態的監示。
圖5-1 主程序流程圖
5.2.2?中斷流程
中斷服務主要有三個,一個是系統通信中斷服務,主要是在DMC庫中完成;一個是PDC定時器的溢出中斷服務,在這里主要完成位置計數溢出的處理,以保證位置單元的正確性;最后一個是定時器的周期中斷服務,這里主要完成當前位置信息的采集,同時根據位置增量計算當前的轉速。
5.3 程序代碼
使用SPMC75F2413A的PDC0的相位計數模式(即兩線增量碼盤接口)實現使用兩線增量碼盤測量電機轉速。
#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; // 電機轉速 static int Over_flag = 0; // 位置計數器溢出標志 static int Encoder_Data = 256*4; // 編碼盤的細分常數 // 電機絕對位置 ( 長整數 , 為了計算方便 , 高低分開定義 ) static unsigned int Position_Count[2] = {0,0}; static unsigned int Old_Position_Count = 0; // 上一次電機位置 ( 低 16 位 ) //===================================================================== // ----Function: main(void); // -Description: 主函數 // -----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; // 設置用到的 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; // 設置采樣時鐘為主系統時鐘 // 設置定時計數器模式為四倍頻增量碼盤接口 P_TMR0_Ctrl->B.MODE = CB_TMR0_MODE_Mode1; P_TMR0_Ctrl->B.CCLS = CB_TMR0_CCLS_Disabled; // 禁止計數器清除 P_TMR0_Ctrl->B.CKEGS = CB_TMR0_CKEGS_Rising; // 設定計數邊沿為上升沿 P_TMR0_Ctrl->B.TMRPS = CB_TMR0_TMRPS_FCKdiv1; // 設置時鐘 , 這是必需的 // 使能計數器的上溢下溢中斷 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; // 工作模式初始化為連續增計數 P_TMR2_Ctrl->B.CCLS = CB_TMR2_CCLS_TPR; // 計數器清零源為周期匹配信號 P_TMR2_Ctrl->B.CKEGS = CB_TMR2_CKEGS_Rising; // 計數邊沿為上升沿 P_TMR2_Ctrl->B.TMRPS = CB_TMR2_TMRPS_FCKdiv4;// 計數時鐘為主時鐘的 1/4 P_TMR2_TPR->W = 6000*Samp_Time; // 定時周期設為 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] --; // 位置計數下溢出 Over_flag = 1; } if(P_TMR0_Status->B.TCVIF) { P_TMR0_Status->B.TCVIF = 1; //Clear TCVIF flag (int)Position_Count[1] ++; // 位置計數上溢出 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 正轉 , 上溢 Temp = (0xffff - Old_Position_Count) + Position_Count[0] + 1; else //0 反轉 , 沒有溢出 { Temp = Old_Position_Count - Position_Count[0]; Temp = -Temp; } } else { if(Over_flag > 0) // 反轉 , 溢出 { Temp = (0xffff - Position_Count[0]) + Old_Position_Count + 1; Temp = - Temp; } else // 正轉 , 沒有溢出 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(); } |
評論
查看更多