于乃功
(1.北京工業大學 信息學部,北京 100124; 2.計算智能與智能系統北京重點實驗室,北京 100124; 3.數字社區教育部工程研究中心,北京 100124)
隨著自動化設備和機器人需求的穩步增長,作為它們的關鍵驅動部件步進電機或伺服電機配套的驅動器及脈沖控制器需求也相應增加,而常用的脈沖控制器一般情況下依靠PLC即可實現,但其在機器人控制中無法靈活使用,所以很有必要開發一款基于STM32的實時定時脈沖發生器。并且STM32F103芯片也有結構簡單[1],成本低廉,占用空間小等諸多優點。
電機起步速度過快時會發生堵轉,具體原因是因為由靜止狀態到動態,如果速度過高的話,會引起各軸之間產生沖擊,超程,失步等現象[2],而停止時因為工件在快速運行狀態,若突停的話,因機械慣性較大,嚴重的話會引起機械損傷,或定位不準現象為了使執行機構能平穩定位,就要求電機在開機速度達到給定進給速度的過程中有一個加減速過程,使其能平滑過渡,避免電機速度突變給其帶來損傷。
大多數運動控制系統都采用兩種加減速控制算法:梯形加減速算法,S形加減速算法。因梯形加減速方案[2]便于計算,實現方式簡單,系統響應快,已能滿足一般多軸加減速控制場合應用需求所以在多軸脈沖控制器中獲得廣泛應用,本文主要采用梯形加減速方法實現。
STM32F103在發送多路脈沖方面,如果選擇用多個定時器來發送,那么在速度非常高的時候就會導致發送的脈沖不準確。這是因為STM32F103芯片是單核單線程的,無法同時處理多個中斷,利用多個定時器來發送多路脈沖經常就會發生同一時間觸發多個中斷的情況。因此本文克服了常規采用多路定時器方案只能實現中低速下(50 kHz以下)多路脈沖發生方法,采用只使用一個定時器發送主軸脈沖,從軸脈沖通過插補算法跟隨主軸的方法實現多路高速脈沖發送。
定時器采用向上計數模式,從零開始累加到設定值后溢出,設定值由自己設置并存放在ARR(自動重裝載寄存器)中[3]。當達到設定值時進入中斷,每次進入定時中斷后,將單片機某一I/O口翻轉,即可產生脈沖,通過改變定時中斷的時間即ARR值,就可以控制輸出脈沖的頻率。為了防止ARR寄存器中的值超過16位導致溢出,利用TIMx_PSC(預分頻寄存器),預分頻器可以將計數器的時鐘頻率按1到65536之間的任意值分頻。它是基于一個(在TIMx_PSC寄存器中的)16位寄存器控制的16位計數器。這個控制寄存器帶有緩沖器,它能夠在工作時被改變。新的預分頻器參數在下一次更新事件到來時被采用。
當預分頻器的參數從1變到2時,計數器的時序圖如圖1所示。
插補法常見的有:逐點比較插補法,比值積分法和數字積分插補法。

圖1 計數器的時序圖
當預分頻器的參數從1變到4時,數器的時序圖如圖2所示。

圖2 計數器的時序圖
本文的插補方法主要采用數字積分法,數字積分法就是把給定的形成數據存儲到有限長度的寄存器里進行微分累加,通過判斷寄存溢出產生脈沖作為進給輸出脈沖。數字積分的插補方法(DDA)具有邏輯強的特點,可以實現復雜曲線的插補運算,適用于多軸聯動控制;只要輸入幾個初始數據,就能計算出執行機構所需要的運行軌跡數據,從而加工出直線、圓弧或由直線和圓弧組成的更復雜的輪廓曲線。在進行插補時選擇位置值大的作為長軸,這樣長軸就能均勻輸出進給脈沖,其余軸就能根據與長軸的關系輸出進給脈沖。另外在進行直線插補運算控制時,插補運算的輸出脈沖比較均勻。
步進電機的轉速和步進電機驅動器接收的脈沖頻率成正比,如果控制器發出的脈沖頻率越高則步進電機的轉速越快[4]。利用這個特點通過設定發出脈沖的頻率控制步進電機的轉速是一種行之有效的方法。通過更改定時器ARR的值即可控制輸出脈沖的速度[5]。
(1)
脈沖加減速采用常用的梯形加減速方式,參數為初始速度v0,最終速度vmax,加速度acctime,脈沖總數L。當這些參數確定后可以確定一個脈沖序列及速度序列(定時器ARR值),以1 ms為一個單位來改變定時器的裝載值,來改變其頻率。程序中將每毫秒應輸出的脈沖數和該毫秒內定時器的自動裝載值都放在查找表中。定時器工作時按照順序首先按照最初的裝載值定時中斷,當輸出完對應裝載值設定的脈沖后,更新裝載值。如此復,直到整個加減速過程完成。
計時器初始化參數有如下公式:
(2)
那么:
(3)
定時器裝載值:
(4)
因為定時器的頻率應該是脈沖頻率的兩倍,所以實際的定時器裝載值為:
(5)
確定最高速脈沖為主軸,其他路為從軸[5]。每次中斷開始計算其他從軸是否發送脈沖。主軸速度與從軸速度為已知量,主軸速度由Vmain表示,從軸速度用Vsub表示。計算方法如下:

(6)
st=Vmain-Vsub
(7)
如果sy≥st那么發送脈沖,并且:
sy=sy-st
(8)
如果sy sy=sy+Vsub (9) 如此往復循環就可以得到從軸脈沖。 步進電機單軸速度與位置控制程序流程圖如圖3所示。首先,設置步進電機的初始轉速v0,最高轉速vmax, 加速時間acctime,總脈沖數L。然后,計算出加速段截止脈沖數S1,勻速段截止脈沖數S2。根據不同區間的位置S使用不同的賦值方式[6]。接著利用上述給定條件,計算出每毫秒發送的脈沖數與截止至該毫秒的總脈沖數 (每毫秒發送的脈沖數實際上是只有加速階段的速度值并且是經過1.3節算法計算出的定時器裝載值),并設置兩個數組分別裝載所有計算結果。接著每毫秒都先進行判斷,首先判斷總脈沖值是否小于S1,如果小于則說明目前為加速階段,將數組中的每毫秒發送脈沖數按正序賦值給定時器,如果不再滿足小于S1的條件,則開始循環判斷是否小于S2,如過小于則說明目前在勻速段,將數組中每毫秒發送的脈沖數中最大值賦給定時器,如果不再滿足小于S2的條件,則開始循環判斷是否小于L,如果小于說明目前為減速階段,將數組中的每毫秒發送脈沖數按倒序賦值給定時器,如果不再滿足小于L的條件,說明脈沖已全部發送完畢。采用先計算再用數組存儲的方法是為了使輸出脈沖具有連續性與準確性,并能夠減少CPU占用。 圖3 單軸脈沖加減速流程圖 在輸入完設定值后,如果無法在總脈沖為L時完成一次完整的從v0加速到vmax再減速回v0時,說明vmax設置值過大。而實際的發送情況是加速到發送脈沖總數為1/2L就立刻開始減速,實際最大速度應為v1,所得速度函數應為三角形而非梯形。考慮到此情況,當按梯形加減速求出的S1>1/2L時,則不使用設置的vmax為最大速度而利用1/2L、v0、acctime求出實際最大速度v1替換掉梯形加減速情況的vmax,1/2L替換掉S1,取消掉勻速段部分S2的判斷與賦值,即可實現準確的三角形加減速。 實際代碼: (1)主程序配置代碼如下: ifndef _DRIVE_H_ define _DRIVE_H_ include "sys.h" define PULSEARRAY_SIZE 500 extern u16 psc; struct PULSE { u16 pulsearray[PULSEARRAY_SIZE]; //存放每毫秒要發送的脈沖數,脈沖頻率 u32 pulse_num; //定時器中對發送脈沖計數 int pulsearray_index; //中間變量,用于定時器值累加 u16 state_status; //運行狀態標志 u16 state1; //S1分割點 u16 state2; //S2分割點 u16 state3; //L結束 u16 time_up; //加速時間acctime u16 time_stable; //平穩運行時間 u32 pulse_num_stable; //平穩運行時的脈沖總數 u16 v0; //初始速度 u16 vmax; //最終速度 float acc; //加速度 u32 pulse_totalnum; //脈沖總數 }; extern struct PULSE pulse_x; extern struct PULSE pulse_y; extern struct PULSE pulse_z; extern struct PULSE pulse_a; extern struct PULSE pulse_b; extern struct PULSE pulse_c; u8 Init_Pulsetable(u16 v0,u16 vmax,u16 acc,u32 pulse_totalnum,struct PULSE *pulse);//聲明使用的速度計算函數 endif /* __DRIVE_H__ */ (2)主程序代碼如下: u8 Init_Pulsetable(u16 v0,u16 vmax,u16 acc_time,u32 pulse_totalnum,struct PULSE *pulse) { u16 i = 0; u32 pulse_num_temp = 0; //先判斷速度是否滿足要求 if(v0 < 1)v0 = 1; if(vmax > 100) vmax = 100; pulse->v0 = v0; pulse->vmax = vmax; pulse->time_up = acc_time; pulse->pulse_totalnum = pulse_totalnum; pulse->state_status = 1; pulse->acc = (float)(vmax-v0) / acc_time*1.0; if(pulse->time_up*2+2 > PULSEARRAY_SIZE) return 0; pulse_num_temp = (v0 + v0 + pulse->acc * (pulse->time_up-1)) * pulse->time_up; if(pulse_num_temp < pulse->pulse_totalnum) { //梯形加減速 for(i = 0;i < pulse->time_up-1;i++) { pulse->pulsearray[2*i] = v0 + pulse->acc * i; pulse->pulsearray[2*i+1] = 36000 / pulse->pulsearray[2*i] / (psc+1)-1; }//將每毫秒計算出的自動重裝載值存入數組 pulse->pulsearray[2*pulse->time_up-2] = pulse->vmax; pulse->pulsearray[2*pulse->time_up-1] = 36000 / pulse->pulsearray[2*pulse->time_up-2] / psc / 2;//將實際算出的脈沖總數存入數組 pulse_num_temp = (v0 + v0 + pulse->acc * (pulse->time_up-2)) * (pulse->time_up-1); pulse_num_temp += pulse->vmax * 2; pulse->pulse_num_stable = pulse->pulse_totalnum-pulse_num_temp; pulse->time_stable = pulse->pulse_num_stable / vmax; pulse->state1 = pulse->time_up; } else { //三角形加減速 pulse->time_up = (sqrt(4*v0*v0+4*pulse->acc*pulse_totalnum)-2*v0)/(2*pulse->acc); pulse_num_temp = (v0 + v0 + pulse->acc * pulse->time_up) * (pulse->time_up + 1); pulse->pulse_num_stable = pulse->pulse_totalnum-pulse_num_temp; for(i = 0;i <= pulse->time_up;i++) { pulse->pulsearray[2*i] = v0 + pulse->acc * i; //將實際算出的脈沖總數存入數組 pulse->pulsearray[2*i+1] = 36000 / pulse->pulsearray[2*i] / (psc+1)-1; //將每毫秒計算出的自動重裝載值存入數組 } pulse->state1 = pulse->time_up+1; } return 1; } 多路脈沖發送流程圖如圖4所示。由于STM32F103性能不夠強大,不能夠同時使用多個定時器同時發送多路高速脈沖,所以選擇最高速脈沖為主軸[9],用定時器來控制,其余各路作為從軸用插補算法來控制發送速度,從而避免使用多個定時器。流程是先判斷是否發送,然后進入中斷,通過比較找出最高速的一路脈沖作為主軸,其余路脈沖為從軸,然后通過差補算法算出從軸在此次中斷時是否發送脈沖。如此不斷重復即可實現單個定時器實現多路不同速度脈沖的發送。實際上,在主函數中也需要先判斷一次最高速脈沖,然后才能確定主軸與中斷觸發條件。實現從軸發送與不發送脈沖的方法是不斷改變一個設定好的全局變量標志位,目標從軸的標志位為1時從軸發送,為0時不進行發送,在主函數里則通過判斷這些標志位來判斷是否發送,這樣是因為中斷函數里不能出現循環語句導致的。 將按照要求實現的程序燒錄進STM32F103開發板中,輸入初始速度,最大速度,加速時間acctime,總步長L。然后開始發送脈沖并用示波器測量波形,得到3個階段的波形如圖5、圖6和圖7所示。可以發現由控制I/O口發送脈沖的方法更加精準且更易于計數。在實際自動化生產與機器人運用中,精確的速度控制往往能夠成為是否可應用化的關鍵標準,所以開發以一款基于STM32F103由控制I/O口發送脈沖的方法是十分必要的。 圖4 多路脈沖發送流程圖 圖5 脈沖發送加速段 圖6 脈沖發送勻速段 圖7 脈沖發送減速段 在原有程序基礎上加入多路脈沖插補算法重新燒錄進STM32F103開發板中,設定主軸脈沖最高速度為50 kHz,其余兩路分別為30 kHz與20 kHz。得到的三路脈沖波形圖如圖8所示,圖9為由3個定時器發送三路脈沖的方案,通過對比可以看出由差補算法得到的速度比為精確的5:3:2, 而利用3個定時器發送的方式主軸實際速度為30 kHz,無法達到50 kHz且速度不穩定,這是由于STM32F103本身性能不夠的原因導致的,所以使用插補算法發送多路脈沖是十分有必要的。 圖8 利用差補算法方案的多路脈沖 圖9 利用多個定時器發送多路脈沖 本文中設計的基于STM32F103的控制多軸梯形加減速脈沖發送方法具有精度高,硬件結構簡單,適應性強等特點[10],可降低運動控制器的成本。該方法已經應用于工業自動化控制領域,證明了該方法的可行性與實用性。2 步進電機速度與位置控制的實現
2.1 梯形加減速情況

2.2 三角形加減速情況
3 多路脈沖發送實現
4 測試與實驗結果分析
4.1 單路加減速脈沖實現




4.2 多路脈沖發送實現


5 結束語