不管是小馬達,還是大馬達,嗯,也就是電機,相信大夥伴們也不會陌生。四驅車是一種很優秀的玩具,從老周小時候就開始流行(動畫片《四驅兄弟》估計很多大朋友都看過),直到現在還能看到很多賣四驅車的。為啥會想起四驅車呢?因為小時候玩四驅車讓老周認識了很多奇葩馬達,什麼“紅魔鬼”、“藍芯”、“紫魔鬼”……也不知道是什麼邏輯的命名方式,反正那時候大家都這麼叫。
這些馬達的結構有一個轉軸,繞有紅色或橙色的線圈(記憶中是這些顏色),有四塊磁鐵。金屬外殼,上部開有兩個散熱孔。整體形狀有圓的也有扁的,許多遙控車的馬達是圓的。還有一馬達像個竹筒似的,一些太陽帽小風扇裡面有。
一般的馬達的特點,就是一通電就往一個方向轉(正負接反它就反向轉),但舵機比普通馬達更好玩。360度的舵機與一般馬達相似,加電後會往一個方向轉動,訊號線控制其轉動方向和轉速;不過我們常說的舵機一般是指 180 度的舵機,這種舵機可以通過訊號線讓它轉動一定的角度,當到達指定的角度後舵機會停下來。
180 度舵機可以:
1、機器人各個關節的運動,可模擬人的關節活動。因為程式可以控制舵機轉到指定的角度。
2、遙控小車可以用舵機來拐彎。
3、機械臂 / 機械爪。
4、製作可以轉動的攝像頭。
5、3D 列印的零部件。
……
只要需要控制轉動方向的,都用得上。
舵機依據其工作負荷以及扭力可以有很多種,我們們用來開發做實驗的,最好選 9 克舵機。儘管這種舵機力氣不大,但是開發板可以直接供電,不用外加電源補電。就是這種,藍色透明外殼的。
正因為外殼是透明的,所以你能看到裡面有什麼。當然了,你如果像老周這樣喜歡搞破壞的,可以把拆開玩玩。
拆的時候最好戴個手套,畢竟這是電機,你拆過就知道,裡面有很多潤滑油的。裝回去的時候要注意那幾個減速齒輪,有的大夥伴一時衝動拆了,然後裝不回去。雖然這種舵機一般幾塊錢一個,但你也不能這麼浪費。
舵機裡面主要這幾個部件:
1、馬達。這個肯定有的,不然怎麼轉。
2、電位器。不同角度會改變不同的電阻值,使控制板能驅動馬達轉多少圈。
3、控制板。
4、N 個減速齒輪。
上面只是瞭解一下舵機,接下來看重點——怎麼控制角度。一般的教程會跟你說,通過 PWM 設定不同佔空比來控制舵機轉動角度。這並不算錯,因為控制舵機確實是用 PWM 實現的。不過,這樣說其實不準確。實際上,讓舵機轉動多少度是通過高電平的持續時間來控制的。
通常情況下,控制脈衝的週期時長是 20 毫秒,即 20000 微秒。故用PWM時,頻率設定 50 Hz(1 / 0.02秒 = 50 Hz)。舵機識別高電平的時間範圍為 0.5 ms 到 2.5 ms,即 500 us 到 2500 us。下圖是老周盜來的動圖。
這就是為什麼PWM能控制舵機的原因,在 0.5ms 之前的時間舵機不關心,所以這段時間無論輸出訊號是高電平還是低電平都可以,因此關注的核心變為高電平什麼時候關閉(變為低電平)。
如上圖,如果高電平持續到 0.5 毫秒時變為低電平,則舵機旋轉至 0 度。
如果高電平在 1.5 毫秒時關閉,則舵機旋轉到 90 度。
如果高電平在 2.5 毫秒時關閉,舵機旋轉至 180 度。
綜上所述,將控制舵機的訊號換算為PWM的佔空比,需要準備以下條件:
1、週期時間長度,一般為 20000 us,換算為PWM頻率為 50Hz。
2、高電平有效的持續時間,一般值為:min = 500us,max = 2500us。
3、500 - 2500 us,其時間段為 2500-500 = 2000us,用180度平分這2000微秒,即每一度角對應的時間為 2000 / 180 ≈ 11.11 us / deg。
綜合一下,佔空比可這樣算:
假設要旋轉 90 度,即佔空比:
把公式翻譯成中文,就是這樣
有了上面的基礎,寫程式碼就好辦了。這裡老周寫了一個測試程式,這個命令列程式可以通過輸入命令來修改引數,這樣方便大家做實驗。命令幫助資訊如下:
using static System.Console; static void ShowHelps() { WriteLine("{0,-15}{1}", "h", "顯示幫助資訊"); WriteLine("{0,-15}{1}", "x", "退出"); WriteLine("{0,-15}{1}", "d n", "設定週期(微秒)"); WriteLine("{0,-15}{1}", "t n", "高電平起始時間(微秒)"); WriteLine("{0,-15}{1}", "p n", "高電平結束時間(微秒)"); WriteLine("{0,-15}{1}", "a n", "角度"); WriteLine("{0,-15}{1}", "o", "傳送脈衝訊號"); WriteLine("{0,-15}{1}", "s", "停止脈衝"); WriteLine(); }
下面的程式碼是計算 1 度角對應的時間長度(微秒)。
static void ComputeMicroToAngle() { microForAngle = (maxMicrosec - minMicrosec) / 180.0d; }
minMicrosec 是高電平持續的最小時間:500us;maxMicrosec 是高電平持續的最大時間:2500us。
這幾個變數的宣告如下:
/// <summary> /// 高電平持續的最小時間,一般為 500us /// </summary> static int minMicrosec = 500; /// <summary> /// 高電平持續的最大時間,一般為 2500us /// </summary> static int maxMicrosec = 2500; /// <summary> /// 一度角對應的持續時間,單位為微秒(us) /// </summary> static double microForAngle = 0d;
主體程式碼如下,其餘的可以下載原始碼檢視。
// 建立PWM通道例項 PwmChannel ch = PwmChannel.Create(0, 0); ShowHelps(); //執行後列印一次幫助資訊 bool working = true; //用來跳出迴圈的標誌變數 while(working) { Write(">>>"); // 讀取鍵盤輸入的一行文字 string line = ReadLine(); // 讀取第一個字元 char first = line[0]; // 分析命令 switch(first) { case 'h': //顯示幫助資訊 ShowHelps(); break; case 'x': //跳出迴圈,退出程式 working = false; break; case 'd': //設定週期,一般是20000us ch.Frequency = ParseFreq(line[1..].Trim()); break; case 't': //設定高電平持續的最小時間 ParseMinMicrosecond(line[1..].Trim()); ComputeMicroToAngle(); break; case 'p': //設定高電平持續的最大時間 ParseMaxMicrosecond(line[1..].Trim()); ComputeMicroToAngle(); break; case 'a': //設定要旋轉的角度 double angle = ParseAngle(line[1..].Trim()); ch.DutyCycle = ComputeDuty(angle, ch.Frequency); break; case 'o': //開始傳送脈衝 ch.Start(); break; case 's': //停止傳送脈衝 ch.Stop(); break; default: WriteLine("<<< 無效命令"); break; } } ch.Dispose();
編譯,釋出,上傳到樹莓派。注意舵機有三條線:
1、紅線(一般在中間),接樹莓派 5V 引腳(供電正極)。
2、黑線或棕色線,接樹莓派任意一個 GND 引腳(供電負極)。
3、黃色(有的是白色)是訊號線,用來控制舵機,接樹莓派的 GPIO 18,這個是樹莓派全系列通用的預設 PWM 引腳。
執行程式,第一步,輸入 d 20000,設定週期(為了統一,所有時間引數都是以微秒為單位)。
輸入 t 500 設定高電平控制角度的起始時間,就是持續最小值,取500。
輸入 p 2500,設定高電平的結束時間,即持續的最大值,一般取 2500。
輸入小寫字母 o,開始PWM。
輸入 a 120,旋轉至 120 度。
輸入 a 30 ,旋轉至 30 度。
輸入小寫字母 s ,停止PWM訊號,輸入 x 退出。
看看效果。
相關原始碼,請點這裡下載