01背景與介紹
?步進電機是一個用數(shù)字來控制運動的數(shù)字化電機,特別適用于精準控制場合。今天,我們將通過步進電機控制云臺準確定位轉(zhuǎn)動的應用,詳細講解一下對步進電機運動的控制。
?
首先,云臺通過一個搖桿控制器進行控制,速度分為0~63。其中,0即為停止,63即為最快速度。該產(chǎn)品模型,如圖1所示:
?
?圖1:云臺控制模型 ?在控制邏輯上,這里使用的方案是一片2051作為步進電機驅(qū)動,一片80C5x作為主控芯片實現(xiàn)產(chǎn)品功能,從而形成了一個雙機系統(tǒng),如圖2所示: ?圖2:云臺雙機控制系統(tǒng) ?雙機通信口線定義如下: ?- ?
- ?
- ?
- ?
? ?sbit Cdata = P?^?; // ->2051
sbit Cctrl = P?^?; // -INT0
sbit Crclk = P?^?;
sbit Ctclk = P?^?;
02分析與對策
?我們都知道,51單片機的客觀條件不怎么好。
?
首先是工作頻率較低。傳統(tǒng)的51單片機是12T機,也就是說,執(zhí)行一條指令的速度是1/12主頻,即12M的晶振執(zhí)行指令的速度只有1M。當然,后來出了一些變種51單片機是1T機,大部分指令速度是1T的,無論這個大部分有多大概率,至少執(zhí)行速度是提高了不少。
?
這里采用的就是1T機,因為這款產(chǎn)品實際上有兩個步進電機,如果單片機速度太慢,有很多產(chǎn)品功能就無法流暢實現(xiàn)。要充分利用JBC指令來實現(xiàn)判斷跳轉(zhuǎn),這條指令對應的C語言語句是_testbit_(abitvar)。不能小看這一點點的節(jié)省,這對一個功能復雜、運行速度敏感的產(chǎn)品來說非常重要!
?
其次是定時器數(shù)量少,單次計時時間短。作為一個產(chǎn)品的主控芯片,因為51單片機是8位機,定時器資源也非常緊缺,所以本產(chǎn)品利用了定時器0的模式3,將定時器0一拆為二,變成了兩個不能自動重載的8位定時器(此時原定時器1只能作為波特率發(fā)生器<這也正是我們需要的>,原定時器1的寄存器都作為定時器0的第二個定時器<新定時器1>的控制寄存器,一旦啟動,無法更改)。
?
因為這種模式一旦啟動,后期不能進行修改。所以,為了極大地減少指令數(shù)量,可將這兩個定時器工作于偽重載的模式下。即當定時器計數(shù)寄存器溢出為0后,直接將這個0作為重載數(shù)據(jù),從而避免通過命令進行重載。對于一個反復運行的代碼來說,精簡一條指令的收益是不容小覷的。
?
定時器初始化代碼如下:
?- ?
setBaud(BaudID); // 先初始化定時器1作為波特率發(fā)生器
?
?第三是內(nèi)存資源很有限。變種的51單片機有一個神奇的現(xiàn)象,那就是代碼存儲器容量足夠大,而RAM(即使用MOV來訪問)卻依然很少,片內(nèi)擴展的外部存儲器(即使用MOVX來訪問)執(zhí)行時耗又比較大。所以,將好鋼用在刀刃上就變得非常重要了,甚至我們經(jīng)常還需要用代碼來換取RAM的節(jié)約使用。
?03編程魔法師觀點
?編程魔法師的觀點,就是要面向?qū)ο筇幚怼?/span>也就是后面使用步進電機時,不能夾帶控制代碼,只能設(shè)置設(shè)置參數(shù)(屬性)、調(diào)用調(diào)用動作(函數(shù))。
?
為了減少生澀的說明,這里直接用云臺自檢為例簡要說明。云臺x軸自檢過程,如圖3所示:
?
圖3:自檢流程 ?光電管口線定義: ?- ?
sbit Pos0x = Px^?; // x光電管信號
?
?我們先來看一下自檢的代碼:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
?voidSelfChk(void)
{
? ?? ? Pscx= (Pos0x)?0:1;
? ?? ?while(fx)
? ?? ?{
? ?? ? WDI = !WDI;? ?? ?// ******** 喂狗 ********
? ?? ? if(NdCtrlx)
? ?? ???{
? ?? ?? ?? ?NdCtrlx = 0;
? ?? ?? ?if(fx)
? ?? ?? ?{
? ?? ?? ?? ?? ?? ? Pscx++;
? ?? ?? ?? ?? ?? ? switch(Pscx)
? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??2: xRun321(0,CVauto,CWavoid);
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? Sx = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? xRun();
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? break;
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??1: Pscx = 3;
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??3: Sx = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? xRun321(1,CVauto,0xFFFF);
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? xRun();
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? break;
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??5: CSmaxx1 = Sx;
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??4: Sx = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? break;
? ?? ?? ?? ?? ?? ?? ?? ?? ? case??6: CSdelta = Sx - 1;? ?? ?? ?? ? // 自檢確定光電管寬度
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? fx = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? xStop();
? ?? ?? ?? ?? ???}
? ?? ?? ?}
? ?? ???}
? ?? ?}
}
從自檢代碼中,我們可以看出,對步進電機的控制只使用了一些方法(函數(shù)/宏)。這是一種擼碼的較高境界,即代碼與日常語義貼近。
?
接下來,我們再看一下步進電機的方法代碼:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
?/*--------------------------------------------------------
??功能:x方向運動預備
? ?? ?? ???填入目標Sendx、速度Vobj、運行方向mmd
??參數(shù):o1: 運行方向
? ?? ?? ???o2: 目標速度
? ?? ?? ???o3: 目標行程
--------------------------------------------------------*/
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?mmCmdx =((o2)>CVmax)?CVmax:o2;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?mmSx =o3; mmcx = 1;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
/*--------------------------------------------------------
??功能:x方向運動開始
? ?? ?? ???調(diào)用之前要確認目標Sendx、速度Vobj、運行方向mmd
--------------------------------------------------------*/
void xRun(void)
{
? ?? ?if(TR0) return;
? ?? ?TL0? ? = CT2Vooo; // 進入運行的時間
? ?? ?NdCtrlx = 0;
? ?? ?TR0? ? = 1;
}
/*--------------------------------------------------------
??功能:x方向運動停止
--------------------------------------------------------*/
很顯然,通過控制步進電機的運行參數(shù)設(shè)置、步進電機的起與停,符合我們的日??刂屏晳T,這就是工程學與實際應用完美統(tǒng)一的境界。
?04步進電機運動控制策略
?控制步進電機運動有兩種方式:一種是速度控制方式,另一種是終點控制方式。
?
速度控制方式是指在實時控制時,只有目標速度,沒有目標位置的控制方式。這種控制具有隨意性,它可能是從一個速度到另一個速度的變化,也可能是保持某個速度的運動;而速度的變化可以是增速,也可以是減速;一個速度與另一個速度可以是0,也可以不是0(如圖4所示)。
?
圖4:速度控制中的速度變化 ?目標控制方式是指在**了預存點坐標的再現(xiàn)控制時,讀出當前運行的目標終點坐標并以一定的速度走到該點的控制方式。這種控制目標確定,運行速度確定,對運動的控制要求就是走位精確(如圖5所示)。 ?圖5:終點控制的速度行程曲線 ?確定了步進電機控制策略后,我們就需要不斷掃描步進電機的控制策略,一旦出現(xiàn)變化,我們就立即響應。這些在時間上的微分控制用程序來實現(xiàn)我們利用定時器,這樣做的好處就是時間微分量能夠得到保證,時間微分量的均勻性也能夠得到保證,從而在體驗上獲得一種穩(wěn)定的感覺。 ?其實,這種需求就是一種確定的、機械的需求,我們可以將其整合到步進電機運動的定時器中去。這樣一來,我們就能得到一個步進電機微分控制邏輯圖了(如圖6所示)。 ?圖6:步進電機控制微分流程圖 ?05代 碼
?我知道很多小伙伴不喜歡啰嗦、只喜歡代碼,所以這里就不多說了,大家直接復制代碼就行了。
?
定時器0(x電機)的ISR如下:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
?voidTimer0(void) interrupt 1 using 1
{
? ?? ?static UINT??data Dis=0;? ?? ?? ?? ???//剩余行程
? ?? ?static bit? ?? ???D=0;? ?? ?? ?? ?? ?? ?//運動方向
? ?? ?static UCH? ?data Vend=0;? ?? ?? ???//目標速度
? ?? ?static UCH? ?data V=0;? ?? ?? ?? ?? ?? ?? ? //當前速度
? ?? ?static UCH? ?data lps=0;? ?? ?? ?? ???//定時器延時倍率計數(shù)器
? ?? ?static bit? ?? ???Wavoid=0;
? ?? ?//--------------------------------------------------------------------------------
? ?? ?if(_testbit_(mmcx))? ?? ?? ?? ?// 存在立即執(zhí)行命令
? ?? ?{
? ?? ?? ???switch(mmCmdx)
? ?? ?? ???{
? ?? ?? ?? ?? ???case 0x40:??// 停止
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(Dis>V)Dis = V;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Vend= 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? mmCmdx = 0x00;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? break;
? ?? ?? ?? ?? ???default??:? ?// 開始命令解釋: mmcx = 0 表示速度變化,其他命令必須mmcx = 1
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(V&&(D!=mmdx)) // 如果速度大于0反向則執(zhí)行減速到自動停止
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(Vend){Dis= V; Vend = 0;}
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?D = mmdx;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Vend = mmCmdx;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Sendx =mmSx;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(Sendx<(CSmaxx1))
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Dis= (fx)?(Sendx -Sx):((D)?((Sendx>=Sx)?(Sendx-Sx)((Sendx<=Sx)?(Sx-Sendx):(CSmaxx1-Sendx+Sx)));
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Dis= 0xFFFF;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(!Dis)StopRunx();
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(!lps) lps = CT2Vooo; //以最快速度進入第一步
? ?? ?? ???}
? ?? ?}
? ?? ?// 運行處理
? ?? ?if(++lps) return;? ?? ?? ?? ?? ?? ?? ?// 延長定時器定時時間,lps自增到溢出(==0)才進行一次運動運動處理
? ?? ?SendMx();? ?? ?? ?? ?? ?? ? //根據(jù)當前方向運動一步
? ?? ?NextPx();? ?? ?? ?? ?? ?? ???//求下一個圓周坐標Sx,以及剩余行程Dis(行程不能大于等于最大圓周坐標,自動計算近距離及方向到達目標)
? ?? ?WidAvd();? ?? ?? ?? ?? ?? ? //光電管處同步處理(自檢正方向從未遮擋到遮擋處為0,從遮擋到未遮擋處為光電管寬度,反方向倒著處理)
? ?? ?NxtxAn();? ?? ?? ?? ?? ?? ???//求下一個速度參數(shù)
}
步進電機走一步代碼如下(此處代碼根據(jù)硬件確定,以下僅供參考):
?- ?
- ?
- ?
- ?
?? ?? ?? ?? ?? ?? ?? ?? ?? ? Cctrl = 1; Cdata =0; Cctrl = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ? Cctrl = 1; Cdata =!D; Cctrl = 0;
???????????????????????}
步進電機走一步后坐標與行程處理的代碼如下:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
?#define NextPx(){
?? ?? ?? ?? ?? ?? ?? ?? ? if(fx)
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? Sx++;
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(D)
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Sx++;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(Sx>=CSmaxx1)Sx = 0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(Sx)Sx--; else Sx = CSmaxx1 - 1;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? if(Dis &&(Dis<(CSmaxx1))) Dis--;
????????????????????????}
每次檢測到光電管后同步處理的代碼如下:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
?#define WidAvd(){
?? ?? ?? ?? ?? ?? ?? ?? ? if(Wavoid)
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(Pos0x)
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Wavoid =0;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(fx)if(Pscx==5) NdCtrlx = 1;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(!Pos0x)
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Wavoid =1;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(fx)
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if((Pscx==3)||(Pscx==4))NdCtrlx = 1;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?Sx= (D)?0:CSdelta;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
???????????????????????}
步進電機走一步后速度處理的代碼如下:
?- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
- ?
? ?#define NxtxAn(){
?? ?? ?? ?? ?? ?? ?? ?? ? if(Dis)
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? if(Dis>V)
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(V
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?V++;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?if(V>Vend)V--;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?V--;
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? lps = CxT2Vmin+ V;
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
? ?? ?? ?? ?? ?? ?? ?? ?? ? else
? ?? ?? ?? ?? ?? ?? ?? ?? ? {
? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ? StopRunx();
? ?? ?? ?? ?? ?? ?? ?? ?? ? }
???????????????????????}
06相關(guān)問題與處理方法
?1、由于步進電機是一種電轉(zhuǎn)換率很低的設(shè)備,因此,當負載與輸出功率出現(xiàn)矛盾時,一定要保證設(shè)備不能出現(xiàn)失步,盡可能降低負載影響是重中之重。例如,減輕負載質(zhì)量、降低負載運動阻力等,都是很重要的工作。
?
2、選擇銅耗鐵耗低的步進電機,是在體積一定的情況下提高步進電機帶載能力的優(yōu)選方案,如果你能接受這樣做帶來的成本增加的話。
?
3、速度突變?nèi)菀讓е虏竭M電機失步,這主要是“既想步進電機小,又想步進電機快”導致的步進電機功率跟不上速度變化。在不提高步進電機功率的前提下,利用合適的加速曲線能一定程度上抑制失步。
?
4、光電管位置同步,是避免步進電機控制時,因機械誤差導致數(shù)位累積誤差的有效辦法。由于這種誤差通常只會在整周轉(zhuǎn)動時產(chǎn)生累積,因此只要在每次經(jīng)過零位光電管時進行一次同步即可消除。
?
5、對于計算時出現(xiàn)位置速度偏差的處理方法是,當?shù)竭_指定目標前速度按加減速曲線應該變?yōu)?時,保持速度1不變,直到到達終點。當?shù)竭_指定目標時速度按加減速曲線計算無法到達0時,到達終點時速度直接降為0。
?
盡管這種處理看起來不太合理,但這種偏差在運算出現(xiàn)±1誤差時進行強制修正,實際造成的影響可以忽略不計。
?
6、如果出現(xiàn)步進電機在某個速度時抖動特別厲害(電機運行聲音明顯變大),可以通過改變負載結(jié)構(gòu)與質(zhì)量的方式修改產(chǎn)品的固有諧振頻率,以避開結(jié)構(gòu)共振點造成的抖動。 ?好了,以上就是今天分享的所有內(nèi)容了,如果有需要查看原圖和代碼的小伙伴,請點擊底部“閱讀原文”進行下載。 ?
評論
查看更多