關于舵機,目前網絡上和書本上,很難找到詳細可行的資料(如果有,那估計是我眼瞎,不要理我就好啦-
-!),我在制作ROBOTCUP搬運機器人的過程中,由于聽取學長的“建議”,采用舵機作為機器人的驅動,加之當時太年輕,使用90系列51單片機,所以一個舵機耗了3個月,并沒有按照預期,參加比賽(這個也真的不怪誰,不走個彎路,也不會對舵機和51單片機有如今的大徹大悟-
-!)。所以啊,如果有學弟學妹,想要在以后做之類的比賽甚至于從事相關的工作,那么好好研究下舵機的控制,對你是十分有幫助的(無論是對于舵機控制的原理還是對主控芯片的理解都很有幫助)。關于舵機的控制,我查詢過相關的資料,也請教過我的導師,但是結果都很不滿意,舵機亂轉,轉速控制不精確,出現過各種問題。最終,我也硬是通過砸錢和砸時間(20塊一個的PWM調制器不知道燒了多少-
-!這個反正燒的不是我的,不心疼,但是90塊一個舵機,加上60塊一個的航模PWM舵機調制器還是砸了幾百塊進去的),和小伙伴通過實驗,反復測試得到的結果,在這里分享出來,希望能幫助到學弟學妹。
首先,舵機是做什么的?舵機按照旋轉的角度,可以分為180°和360°連續旋轉舵機。180°舵機,顧名思義,就是只能旋轉180°的舵機,我們可以通過一定的方法,精確的控制舵機旋轉的角度,因此,就我目前接觸到的比賽來看,180°舵機在雙足機器人以及飛思卡爾競速車的轉向上使用的很多,雙足機器人就是模仿人走路的機器人,通過控制180°舵機轉動的角度,完成指定的動作。飛思卡爾轉向類似于汽車使用方向盤轉向,舵機就起到方向盤的作用。360°連續旋轉舵機,可以通過一定手段,控制舵機的旋轉方向和速度,因此,也常常用于小車型機器人的驅動上。這里需要說明的是,180°舵機是無法調速的,就是說,他始終會以最快速度,朝著你設定的角度旋轉,直到旋轉到目標角度停止。而360°舵機是無法控制旋轉的角度的,只可以控制轉和停,正轉和反轉以及轉速。
下面是舵機:
安裝有180°舵機的雙足機器人:
安裝有360°舵機的搬運機器人:
上一段中,我提到可以通過一定的方法,控制舵機,到底是什么方法?PWM!我也不是什么老教授,我不喜歡說太多抽象的理論,這里,只需要知道,要控制舵機,我們要讓單片機輸出一個周期為20ms-30ms,高電平為0.5ms-2.5ms的信號即可。
關于硬件上的設計,無非是保證供電的穩定和預留出PWM的接口,由于我本身也不是做硬件的,這里就不詳細說明了,這里附上一張圖,感興趣的小伙伴可以研究一下,如果對硬件上有其他的問題,也可以私下聯系我,我們組做硬件的小伙伴,還是很厲害的。
我這里對360°舵機如果通過51單片機的程序進行控制做詳細的說明。對于360°舵機而言,PWM高電平為0.5-1.5ms為正轉區間,1.5-2.5ms為反轉區間,1.5ms為舵機剎車點,實際測試過程中,我使用的舵機,高電平0.5ms-1.37ms為以最大速度正轉,正轉的調速高電平區間為1.37ms-1.47ms(高電平越靠近1.5ms,舵機轉速越慢),高電平1.53ms-2.5ms為以最大速度反轉,反轉調速高電平區間為:1.53-1.63ms(高電平越靠近1.5ms,舵機轉速越慢),剎車高電平區間為:1.47-1.53ms。是不是感覺很簡單呢?聽起來好像是挺簡單的,但是有沒有想過如何使用51單片機產生我們需要的PWM呢?有小伙伴會說,用定時器啊!當然,我一開始也是這么想的,看看下面這段程序:
unsigned int
i=1;
int n;
void
ste360(n){
TMOD=0X01;
TL0=0XF6; //
0.01ms
TH0=0XFF;
TR0=1;
EA=1;
ET0=1;
P1=0X00;
while(1);
}
void _pwm () interrupt 1
{
TH0=0xff; //
0.01ms
TL0=0xF6;
i++;
if(i<=n){
P1=0XFF; //
1.37<<1.47-1.54<<1.63
} else
P1=0x00;
if(i>=2000){
i=1;
}
}
看起來程序好像沒有什么問題,ste360(n)這個函數,n就可以控制pwm高電平的時間,我設定定時器為每0.01ms進入一次中斷,所以,要想得到1.5ms高電平,是不是n填寫150就行了?答案是否定的,至于具體結果怎么樣,我這里就不截圖了,沒有在學校沒法用示波器,之后完善吧。我這里告訴你,雖然程序邏輯是沒有問題的,計算出來確實是1.5ms,但是結果可能是高電平為3ms+,為什么?這個問題困惑了我挺久,我和學長也討論過,他說,編譯過程中,會將我們寫的c文件,編譯成匯編文件,然后轉成機器語言,這個過程中可能會有誤差。而我覺得,晶振本身是有誤差的,其次,這樣反復的進入中斷,細小的誤差會被無限的放大。同樣是使用c,stm32上pwm的精度高的離譜。所以,使用51單片機的8位定時器來控制舵機,在我看來,是完全不可行的(可以質疑我的能力,但是上面的程序是在我寫的眾多定時器控制pwm輸出程序中早期的一個,放出來理解簡單,但我在很長一段時間里,極力優化代碼,嘗試過各種思路,但是結果只能說有提升,但是遠遠達不到控制舵機的要求),有不怕死的小伙伴,也可以自己寫點小程序,打在示波器上看看。不能用定時器,那怎么辦?又有小伙伴說了,stc12系列的51單片機是自帶8位pwm模塊,是不是可以用12系列的單片機實現?看程序:
#include
//-----------------------------
// 7
6 5 4 | 3 2 1
0
sfr CCON=0xD8;//CF CR -
- | - - CCF1 CCF0
//-----------------------------
//CF:PCA計數陣列溢出標志.計數值翻轉時由硬件置位。
//CR:PCA計數陣列運行控制位。
//CCF1:PCA模塊1中斷標志。當出現匹配或者捕獲時由硬件置位。
//CCF0:PCA模塊0中斷標志。當出現匹配或者捕獲時由硬件置位。
/
sfr
CCAP0L=0xEA;//PCA模塊0的捕捉/比較寄存器低8位
sfr
CCAP0H=0xFA;//PCA模塊0的捕捉/比較寄存器高8位
sfr
CCAPM0=0xDA;//PCA模塊0的工作模式寄存器
//---------------------------------------
//7 6
5 4
3
2 1
0
//- ECMn CAPPn CAPNn MATn T0Gn PWMn
ECCFn
//----------------------------------------
//ECOMn:使能比較器,1時使能比較器功能
//CAPPn:正捕獲,1時使能上升沿捕獲
//CAPNn:負捕獲,1時使能下降沿捕獲
//MATn:匹配:1時,PCA計數器的值與模塊的比較/捕獲寄存器的值匹配將置位CCON寄存器中斷標志位CCFn
//T0Gn:翻轉,1時,工作在PCA告訴輸出模式,PCA計數器的值與模塊的比較/捕獲寄存器的值匹配將是CEXn腳翻轉
//PWMn:脈寬調節輸出模式,1時,使能CEXn腳用做PWM輸出
//EECFn:使能CCFn中斷,使能寄存器CCON中的捕獲/比較標志CCFn,用來產生中斷
sfr
PCA_PWM0=0xF2;//PCA模塊0,PWM寄存器
//-----------------------------------
//
7 6 5 4
3 2 1
0
//PCA_PWMn:- - - - | - -
EPCnH EPCnL
//-----------------------------------
sfr
CCAP1L=0xEB;
sfr
CCAP1H=0xFB;
sfr
CCAPM1=0xDB;
sfr
PCA_PWM1=0xF3;//
sbit
CR=0xDE;//因為只有能和8整除的才能位尋址,所以能些0xDE,看起來有沖突,實際上不會。
sfr AUXR1=0xA2;//PWM引腳位置
串口2位置 雙DPTR選擇 AD轉換結果存放方式調整 SPI位置調整
void
ini_T0(void)
{
TMOD=0x02;//T0方式2
TH0=0xb2;
//12MH時
TL0=0xb2;
TR0=1;
}
//
//頻率為50HZ
周期的1/50=0.02s,將0.02S分成256分:0.02/256=0.000078125S=0.078125ms
//0.078125為一份的時間
一共256份
//CCAP0L=223;CCAP0H=223;為2.5ms
//243時約為1ms (0.9375)
//CCAP0L=249;CCAP0H=248;為0.5ms
//236時為1.5ms (1.484375)
//230為2ms (2.03125)
void
main(void)
{
ini_T0();
//方式2,0.078125ms溢出,每溢出一次CL加1
CMOD=0x04;//定時器0溢出率作為時鐘輸入
//CIDL - -
- CPS2 CPS1 CPS0 ECF
//--------------------------------
//CIDL:計數陣列空閑控制,0時,空閑模式下PCA計數器繼續工作;1時空閑模式PCA停止工作。
//----------------------------------------------
//CPS2
CPS1 CPS0: PCA計數脈沖選擇
//000:系統時鐘,FOSC/12
//001:系統時鐘,FOSC/2
//010:定時器0的溢出,可實現可調頻率PWM輸出
//011:ECI/P3.4腳的外部時鐘輸入(最大速率FOSC/2)
//100:系統時鐘,FOSC
//101:系統時鐘/4,FOSC/4
//110:系統時鐘/6,FOSC/6
//111:系統時鐘/8,FOSC/8
//-----------------------------------------------
//ECF:PCA計數溢出中斷使能:1時,使能寄存器CCON CF位的中斷。0時禁止該功能。
CL=0x00;//清零自由遞增計數的16位定時器的值
CH=0x00;//CH0為00
看結構圖,CL前面是永遠是0
//CCAP0L=223;//裝入比較初值
//CCAP0H=223;
PCA_PWM0=0x00;
//EPC0H=0,EPC0L=0
CCAPM0=0x42;//設置ECOM1=1,PWM1=1.
//CCAP1L=223;
//CCAP1H=223;
PCA_PWM1=0x00;//EPC1H=0,EPC1L=0
CCAPM1=0x42;//設置ECOM1=1,PWM1=1.
CR=1;//CR=1,啟動PCA陣列計數。
看151頁,其中和CMOD的CIDL位有關,又和IDLE有關,看183頁。
//AUXR1=0xc0;//PWM0從P1.3切換到P4.2
//PWM1從P1.4切換到P4.3
while(1)
{
//========================兩舵機停止,中位調節用
CCAP0L=236;//裝入比較初值
CCAP0H=236;
CCAP1L=230;//裝入比較初值
CCAP1H=230;
while(1);
}
}
至于怎么調整pwm的高電平,修改上面CCAPXL和CCAPXH就可以了,這段代碼不是我寫的,但明顯是個高手寫的-
-!至于這段代碼是怎么實現的,程序里的注釋很詳細,小伙伴們在學了郭天祥的教程以后,嘗試著查看官方的手冊吧,學習單片機,重要的不是你學會了多少多少東西,更重要的還是一種自學能力,翻手冊,學這款芯片怎么用的能力。是不是大功告成了呢?并沒有!!測試中我發現,CCAPXH和CCAPXL的值每改變1,PWM高電平改變0.07ms左右。那么問題來了,在前面我提到過,360°舵機調速的區間,只有0.1ms(1.47-1.37=0.1),這個0.07,是可以讓舵機實現正轉反轉,以及停止,但是沒辦法調速,循跡小車是需要控制車子兩側的輪子產生轉速差來控制方向的,沒法調速,就沒法實現循跡。造成這個問題的原因是什么?8位的pwm模塊,8位的pwm,上面程序中的注釋中有這樣一段:
//頻率為50HZ
周期的1/50=0.02s,將0.02S分成256分: 0.02/256=0.000078125S=0.078125ms
//0.078125為一份的時間
一共256份
很清楚了吧!那么是不是51單片機控制不了360°舵機呢?在我制作搬運機器人的過程中,有一段時間我是想過放棄的,但是最終,我發現了stc15系列單片機,很有意思的是,我在查詢芯片的時候,15這款單片機是沒有pwm模塊的,后來才知道,這款芯片帶有16位的定時器,這樣,問題就迎刃而解了,官方提供的手冊中,有用16位定時器(自動重裝模式)實現8~16位PWM的示例,具體的程序在這里我就不列出來了,在15的手冊100頁,感興趣的小伙伴,自己去看看吧。
好了,360°舵機基本上說完了,其實180°舵機也是相似的,只是高電平的不同代表著不同的角度,0.5ms為0°,2.5為180°。程序都是一樣的。我在這里說下比較容易出現的問題吧。首先,電路上的設計,舵機要求的電壓為6v-7.2v,你也許會發現5v其實舵機也能轉,但是,低電壓會帶來很多未知的問題,比如舵機亂轉,曾經有一段時間,我陷入舵機亂轉的怪圈,我以為是我程序的問題,但是示波器顯示沒問題,以至于我以為是舵機壞了。實際上,是電池的問題,電池用的時間長了,電壓不足,讓舵機亂轉。所以,電池我建議使用航模sss電池,這個電池是11.2V的,使用降壓模塊,降成7.2v,給舵機供電,將成5v給單片機和傳感器供電就行了。另外,舵機的自己的電路有時候會對單片機有影響,最好加上光耦隔離,防止舵機電路對單片機的干擾。
最后,簡單說下使用舵機驅動小車和電機相比,有什么優劣。首先,就電路而言,由于舵機內置有電路,因此我們做機器人設計電路的時候,僅需要設計好陰陽極和PWM信號輸入的接口,非常簡單。而普通的減速電機在設計電路的時候,則需要考慮到驅動芯片,就比較復雜了。淘寶上有現成的驅動模塊,買回來也就直接用了。而在控制上,舵機對于PWM的精度要求也更高,上文中已經論述過了。價格方面,舵機的價格是普通減速電機的很多倍,但是昂貴的價格帶來的是拖剎的快速響應,給定高電平1.5ms的pwm,舵機會立刻剎住以及其充沛的動力這一點是減速電機做不到的。所以到底是采用舵機還是電機,學弟學妹自己斟酌吧。
一不留神竟然寫了4000字-
-!可以可以,如果覺得這篇文章不錯,對你有幫助,也歡迎轉載啦(請注明本文出處及作者)。我在大一加入了很多組織,最終在機器人協會找到了落腳點,從最初沒有目的學習51單片機,做機器人,到現在有了目標,學習linux,學習開發智能路由器,在這個協會我還是學到了很多的東西的。現在呢,其實是以一種感恩的心態,在重復著往屆學長學姐做的事情,很多優秀都是一種傳承嘛!也歡迎各位小伙伴加入到重郵基協,加入到我們這個基情四射,整天撕逼的陣營中來吧-
-!我相信在這個良心協會(真的良心),你會學習到你想學的東西噠!若是對舵機的控制仍有疑問,可以在下方評論留言,我看到會盡快回復。
重慶郵電大學機器人協會
|