加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

步進(jìn)電機(jī)驅(qū)動(dòng)編后感

2020/07/02
97
閱讀需 12 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

以下是魚鷹當(dāng)初完成公司第一個(gè)項(xiàng)目時(shí)寫的總結(jié),大家可以看看能否得到一些啟發(fā)(或許會(huì)比較枯燥,畢竟這是魚鷹自己的經(jīng)驗(yàn)總結(jié))。

這個(gè)步進(jìn)電機(jī)說起來挺簡(jiǎn)單的,就是用戶輸入指令,讓兩個(gè)電機(jī)上下運(yùn)動(dòng)或者停止。并且運(yùn)動(dòng)范圍通過紅外對(duì)管限制,并且有步進(jìn)電機(jī)的硬件驅(qū)動(dòng),我只要控制 IO 并且輸出 PWM 脈沖就行。驅(qū)動(dòng)每收到一個(gè)脈沖走動(dòng)一步。

這是公司的第一個(gè)項(xiàng)目,因?yàn)槭褂脤?duì)象是人,所以必須對(duì)一些輸入進(jìn)行參數(shù)檢查。實(shí)際上該項(xiàng)目完成的時(shí)候,雖然有一些檢查,但是卻沒有全部檢查,所以還是會(huì)有可能出現(xiàn) bug 現(xiàn)象。本來在第三次更新該驅(qū)動(dòng)程序的時(shí)候,也準(zhǔn)備將其改寫的,但是我發(fā)現(xiàn)目前的水平實(shí)在有限,即使再改寫,對(duì)于參數(shù)檢查還是沒有更好的方法去優(yōu)化算法。所以在所有函數(shù)都重寫的情況下唯有這部分代碼保留下來了。

這個(gè)程序一共進(jìn)行了三次更新,第一次花了一個(gè)星期將基本功能實(shí)現(xiàn)了。

當(dāng)時(shí)采用計(jì)時(shí)的方式進(jìn)行運(yùn)行距離的控制。1 ms 中斷,每次變量自加 1,這樣通過時(shí)間乘以速度的方式就可以得到電機(jī)的運(yùn)行距離了,而整個(gè)指令組的運(yùn)行控制在主函數(shù)執(zhí)行。

想法很正確,當(dāng)時(shí)確實(shí)也運(yùn)行起來了,但是后來測(cè)試人員告訴我,當(dāng)設(shè)定運(yùn)行時(shí)間很短暫的時(shí)候,電機(jī)不運(yùn)行,想想也是,時(shí)間太短,并且指令運(yùn)行的控制是在主函數(shù)的,必然有比較大的誤差。

雖然第一次寫這個(gè)程序的時(shí)候也想過通過對(duì)脈沖計(jì)數(shù)的方式來實(shí)現(xiàn)對(duì)電機(jī)的控制,這樣只要知道我輸出了多少個(gè)脈沖,就能確定運(yùn)行了多大的距離。但是當(dāng)時(shí)卻不知道該如何獲取脈沖數(shù)。因?yàn)橹爸恢垒敵?PWM 波,根本沒想過如何獲取 PWM 的數(shù)量。

能想到的也就是改硬件了,就是再用一個(gè)定時(shí)器作為脈沖計(jì)數(shù)器,這樣兩個(gè)電機(jī)就需要兩個(gè)定時(shí)器,包括輸出 PWM 的一個(gè)定時(shí)器,共用三個(gè)……所以這個(gè)項(xiàng)目當(dāng)時(shí)對(duì)于我來說有心無力了,只能將就,只能等以后了。

而且這個(gè)程序還有兩個(gè)缺陷,就是兩個(gè)電機(jī)速度不能單獨(dú)控制,因?yàn)殡姍C(jī)速度是通過單位時(shí)間內(nèi)的脈沖數(shù)決定的,而輸出 PWM 的兩個(gè)引腳使用了同一個(gè)定時(shí)器。

而控制 PWM 周期的方式有兩種,一種是修改定時(shí)器的基本時(shí)鐘,另一個(gè)就是修改計(jì)數(shù)周期,但這兩種方法實(shí)際上在一個(gè)定時(shí)器上都只有一個(gè)寄存器。

另一個(gè)問題就是當(dāng)時(shí)需要暫停功能,我沒辦法實(shí)現(xiàn),因?yàn)槲腋静恢莱绦蜻\(yùn)行到哪里了,又如何從原來的地方開始運(yùn)行呢?

后來在看一個(gè)有五年工作經(jīng)驗(yàn)的高手寫的代碼發(fā)現(xiàn),我其實(shí)可以開啟定時(shí)器的更新中斷的,每輸出一個(gè)脈沖,必然是要進(jìn)入更新中斷的,只要在更新中斷完成計(jì)數(shù)即可。

還有高級(jí)定時(shí)器有一個(gè)寄存器是可以控制輸出脈沖數(shù)的,這個(gè)另說。

因?yàn)檫@個(gè)問題一直在腦海,所以在看一篇文章的時(shí)候,雖然它不是說如何獲取脈沖數(shù),但是也給了我一個(gè)靈感,那就是可以同步開啟一個(gè)定時(shí)器的,知道輸出 PWM 頻率,只要在輸出 PWM 的同時(shí)開始另一個(gè)定時(shí)器,就能在控制時(shí)間的情況下精確的控制輸出 PWM 數(shù),雖然和之前的定時(shí) 1ms 計(jì)數(shù)類似,但精度更高,畢竟對(duì)于人來說,1ms 的誤差精度雖然高,但是對(duì)于 1ms 輸出幾千個(gè)脈沖來說,誤差不是一般的大。

這樣一來,馬上就開始了程序的更新,所以花了大概三天的時(shí)間完成了程序的修改,并且因?yàn)橐呀?jīng)能對(duì)輸出的脈沖數(shù)進(jìn)行計(jì)數(shù),對(duì)于之前要求的在到達(dá)紅外對(duì)管的下限之后再運(yùn)行電機(jī)的功能也就能實(shí)現(xiàn)了。

但是實(shí)際運(yùn)行之后,設(shè)置向下向上的脈沖數(shù)相同的情況下,它是不能回到原點(diǎn)的位置。因?yàn)檫@個(gè)程序是在第一個(gè)程序上寫的,第一次寫的時(shí)候需求不明,考慮的不夠完善,所以整個(gè)程序的結(jié)構(gòu)比較混亂,對(duì)電機(jī)運(yùn)行方向的判斷上可能會(huì)有誤差,所以在更新完成之后,就已經(jīng)打算有機(jī)會(huì)再更新一次,這一次更新將推翻之前的程序結(jié)構(gòu),要考慮的更完善才行,這是自我提高。

所以從家里回來之后,我就開始考慮更新這個(gè)程序了,只是沒想到花了這么久時(shí)間才完成。我也沒想過在公司去完善這個(gè)程序,公司有公司的事,而且這個(gè)程序問題的主因還是自己能力不夠,而且我需要更輕松的狀態(tài)去慢慢考慮清楚,并嘗試使用新方法去重新設(shè)計(jì)程序的結(jié)構(gòu)。

有了前兩個(gè)程序的基礎(chǔ),所以知道程序設(shè)計(jì)的時(shí)候該考慮哪些問題。

變量設(shè)計(jì)考慮:首先就是反映電機(jī)狀態(tài)的變量必須保證緊隨實(shí)際的狀態(tài),并且改變這個(gè)狀態(tài)的位置只能是一個(gè)地方,而不能這個(gè)函數(shù)改一下,那個(gè)程序改一下,這樣肯定會(huì)導(dǎo)致整個(gè)程序的混亂。

還有就是變量的作用要明確且單一,不要一個(gè)變量給它附加多種用途,這樣也可能會(huì)程序混亂。

除此之外,還要考慮這個(gè)變量是否必須一直存在,還是說多個(gè)變量其實(shí)歸納為一個(gè)變量。

一個(gè)例子就是,輸入用戶指令后,有多個(gè)參數(shù)變量,并且要指示這條指令是否完成,這條指令的當(dāng)前輸出脈沖數(shù)等等。

其實(shí)對(duì)于一個(gè)執(zhí)行器來說,只要將最基本的用戶指令保存即可,根本不需要附加其他的,即使有附加,也是在執(zhí)行的過程存在,也就是說這個(gè)命令組的其它附加信息其實(shí)只要共用一個(gè)變量即可,因?yàn)楫?dāng)前運(yùn)行的只能是一條指令,只要在運(yùn)行下一條指令時(shí)將上一條指令信息清除(可以清除一個(gè)標(biāo)志,作為整條指令信息清除的標(biāo)志,比如將下行指令標(biāo)志改為無指令狀態(tài)即可)并重新初始化就可以繼續(xù)為下一條指令服務(wù)了。
時(shí)間同步:就是每次開始處理數(shù)據(jù)的時(shí)候都統(tǒng)一在定時(shí)器更新中斷執(zhí)行(前提是這個(gè)數(shù)據(jù)處理必須能在中斷時(shí)間內(nèi)處理完成),這樣每處理一次,都是在定時(shí)器重新計(jì)數(shù)的情況下,而不會(huì)出現(xiàn)這里剛處理完數(shù)據(jù),那里就中斷數(shù)據(jù)處理產(chǎn)生一個(gè)脈沖的情況,這樣必然可能出現(xiàn)脈沖計(jì)數(shù)不準(zhǔn)的情況。

而且在進(jìn)行數(shù)據(jù)處理的時(shí)候,對(duì)關(guān)鍵數(shù)據(jù)的處理可以采用關(guān)閉全局中斷和停止定時(shí)器的方式來確保數(shù)據(jù)處理的完整性。

啟動(dòng)操作、結(jié)束操作:就是一個(gè)完整動(dòng)作的執(zhí)行其實(shí)只有啟動(dòng)和停止而已,在將所有數(shù)據(jù)處理完之后就可以進(jìn)行啟動(dòng)操作,在該動(dòng)作完成之后只要處理身后事即可,這個(gè)身后事包括停止上一個(gè)動(dòng)作的所有影響,以防出現(xiàn)下一個(gè)動(dòng)作還未啟動(dòng)而上一個(gè)動(dòng)作繼續(xù)執(zhí)行的情況。

當(dāng)然還有一種情況就是在啟動(dòng)該動(dòng)作之后,有可能出現(xiàn)意外情況,而需要將該動(dòng)作停止,所以需要定時(shí)監(jiān)視。但是定時(shí)監(jiān)視有一個(gè)缺陷,就是你不能及時(shí)查看異常。所以如果硬件允許的話,可以采用硬件中斷來監(jiān)視。

走一步看一步:在硬件條件不允許的情況下可以采用走一步看一步的方法。就是每輸出一個(gè)脈沖(之后停止定時(shí)器),然后看有沒有到限制位置,如果沒到,就繼續(xù)走,如果到了,就停止該動(dòng)作。這樣看起來效率挺低的,可實(shí)際上,單片機(jī)的速度很快,對(duì)于我們?nèi)藖碚f,我們根本感覺不到它是邊走邊看的,你看到的只有一個(gè)完整動(dòng)作執(zhí)行的現(xiàn)象。

暫停動(dòng)作:之前提到如何暫停動(dòng)作,并且重新執(zhí)行問題,之前想的是從程序本身考慮(離開代碼執(zhí)行,然后重新返回該代碼位置重新執(zhí)行,有點(diǎn)像操作系統(tǒng)切換任務(wù)的情況)。

其實(shí)我只要停止這個(gè)動(dòng)作的執(zhí)行并且不破壞這個(gè)動(dòng)作的相關(guān)的變量即可,我根本不需要知道它執(zhí)行到了哪個(gè) PC 地址。比如電機(jī)的執(zhí)行靠 PWM 輸出,相關(guān)變量的變化是在中斷執(zhí)行的,我只要停止了定時(shí)器,就一了百了了。既停止了 PWM 輸出(停止動(dòng)作),又不會(huì)讓它繼續(xù)執(zhí)行相關(guān)變量的操作,這樣一旦重新啟動(dòng)定時(shí)器,變量繼續(xù)變化,PWM 繼續(xù)輸出,變量條件達(dá)到即可像沒事一樣繼續(xù)執(zhí)行停止操作并完成身后事。

所有動(dòng)作暫停一下:這里所謂的動(dòng)作暫停不是外部現(xiàn)象的暫停,而是內(nèi)部的。

并且這個(gè)動(dòng)作應(yīng)該是內(nèi)部控制情況下才可以暫停,否則如果是外部控制的情況下暫停內(nèi)部運(yùn)行,必然會(huì)因?yàn)轫憫?yīng)不及時(shí)丟失重要東西。這里因?yàn)殡姍C(jī)運(yùn)行動(dòng)作全靠自身輸出 PWM 來控制的,所以暫停幾十毫秒在外界看來沒什么影響,也看不出來。

那為什么要暫停呢?比如你要在中斷串口輸出一個(gè)信息,如果采用查詢的方式輸出的話,必然需要十幾毫秒才能輸出完成,而這個(gè)時(shí)間遠(yuǎn)大于你的中斷時(shí)間,所以必然會(huì)錯(cuò)過下一次中斷的執(zhí)行,導(dǎo)致外部已經(jīng)輸出了一個(gè) PWM,而相關(guān)變量計(jì)數(shù)器沒有計(jì)數(shù)的情況。所以這個(gè)時(shí)候就可以通過停止定時(shí)器的方式來停止動(dòng)作的執(zhí)行,這樣定時(shí)器的寄存器計(jì)數(shù)器就不會(huì)繼續(xù)累加了,也不會(huì)產(chǎn)生脈沖。當(dāng)輸出完之后就可以繼續(xù)開啟定時(shí)器。

那為什么不采用關(guān)閉全局中斷的方式呢?你要知道的是,你關(guān)閉全局中斷只是屏蔽了中斷,而不能阻止中斷的發(fā)生,只是說,中斷發(fā)生后,因?yàn)槟愕钠帘危瑢?dǎo)致該中斷處理程序的延后執(zhí)行而已。

之前說過兩個(gè)電機(jī)不能獨(dú)立設(shè)置速度的問題,主要就是因?yàn)閮蓚€(gè)引腳共用同一個(gè)定時(shí)器,后來在偶然情況下想到其實(shí)引腳有一個(gè)復(fù)用功能的,有可能一個(gè)引腳是其他定時(shí)器的復(fù)用輸出引腳呢?或許是對(duì)于問題的執(zhí)著,我幸運(yùn)的發(fā)現(xiàn)真的有一個(gè)引腳是高級(jí)定時(shí)器的一個(gè)復(fù)用 PWM 輸出引腳,這樣我就不用采用模擬的方式輸出 PWM 波了。

到此,當(dāng)初所有的功能需求完成了。越努力越幸運(yùn)或許真是如此!

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

六年開發(fā)經(jīng)驗(yàn),豐富的KEIL調(diào)試經(jīng)驗(yàn),STM32使用經(jīng)驗(yàn),C語言運(yùn)用經(jīng)驗(yàn)。