★★
讀者:适合有
C語言
或
Python
程式設計基礎,對舵機和PWM等有一定了解的讀者。
往期相關文章:
- 《 樹莓派4B-WiringPi庫的安裝和使用 》
- 《 入門WiringPi庫的PWM接口 》
本文将介紹如何在樹莓派4B上控制舵機運轉,比如控制角度、方向等,帶你入門模拟舵機。
準備工作:- SG90(或其他型号)模拟舵機
- 樹莓派4B
- 面包闆及若幹導線
舵機簡介
模拟舵機與數字舵機
數字舵機(Digital Servo)和模拟舵機(Analog Servo)在基本的
機械結構方面是完全一樣的,主要由
馬達、
減速齒輪、
控制電路等組成,而數字舵機和模拟舵機的最大
差別則展現在
控制電路上,數字舵機的控制電路比模拟舵機的多了
微處理器和
晶振。模拟舵機一般通過PWM波來控制,采用并行通信,會占用較多的IO口。數字舵機是多是采用串行通信,通過指令以總線的形式控制,常見接口有UART、RS485等,比PWM波控制方式高端一點。多個數字舵機可以串連接配接線,每個舵機都有唯一的ID,隻需将靠近控制器的舵機連到控制器上,就能控制所有舵機,占用IO口比較少。
模拟舵機是直流伺服電機控制器晶片,一般隻能接收 50Hz 頻率(周期 20ms)~300Hz 左右的 PWM外部控制信号,太高的頻率可能就無法正常工作了。數字舵機通過MCU可以接收比 50Hz 頻率更高的 PWM 外部控制信号。
模拟舵機的控制
舵機的頻率一般為頻率為50HZ,也就是一個20ms左右的時基脈沖,而脈沖的高電平部分一般為0.5ms-2.5ms範圍。來控制舵機不同的轉角。以筆者購買的180度SG90小舵機為例,假定1.5ms的脈沖寬度為舵機的0角度,那麼對應的控制關系如下:
占空比與角度位置表高電平持續時間(ms) | 占空比(周期20ms) | 舵機轉過的角度(度) |
---|
當然,讀者也可以根據自己的需要,規定0.5ms的脈沖寬度為舵機的0度位置,2.5ms脈沖寬度為舵機的180度位置。
SG90模拟舵機實物圖
拆解圖:可以看到舵機主要由
馬達、
減速齒輪、
控制電路組成,其中綠色的是電位器,用來确定舵機輸出軸角度位置。
模拟舵機的程式設計
SG90舵機控制(C語言版)
使用硬體PWM接口
樹莓派預設PWM模式是
Balanced
模式,該模式下的PWM頻率遠大于舵機的50Hz,是以需要修改PWM的頻率,此時我們需要将PWM模式切換到
Mark:Space
模式(占空比模式)。查閱資料,樹莓派的PWM時鐘基礎頻率是19.2MHz,通過
pwmSetClock()
函數設定分頻(預設是32分頻),PWM頻率計算公式:
-
pwmFrequency(Hz)
=
19.2*10^6
Hz
/ pwmClock / pwmRange
為了得到更好的控制精度,這裡将
range
設定為2000,即周期分為2000步,控制精度更高。要取得PWM頻率為50Hz,那麼divisor為:
-
divsior =
19200*1000
/
(50
*
2000)
=
192
角度對應range值為:
舵機角度(度) | range值 | 占空比 |
---|
筆者也試了一下
divisor=1920
,
range=200
的配置方式,這樣設定PWM Freq = 50Hz的,但是實際控制舵機和理論的占空比有差異,0.5ms對應range為15。
将SG90舵機連接配接到樹莓派上,接線如下:
SG90 Pin | 樹莓派 Pin |
---|
舵機連接配接好後,可先通過gpio指令,測試一下GPIO1,
指令如下:-
$ gpio mode 1 pwm # 設定GPIO1為PWM輸出腳
-
$ gpio pwm-ms # 切換到占空比、傳統模式
-
$ gpio pwmc 192
# 設定時鐘分頻
-
$ gpio pwmr 2000
# 每個刻度 0.01 ms,2000 * 0.01ms = 20ms
-
$ gpio pwm 1
50
# 0.5 ms (-90°) => Maxrange * 占空比 = 2000 * 2.5% = 50
-
$ gpio pwm 1
100
# 1.0 ms (-45°) => 2000 * 5% = 100
-
$ gpio pwm 1
150
# 1.5 ms (0°) => 2000 * 7.5% = 150
-
$ gpio pwm 1
200
# 2.0 ms (45°) => 2000 * 10% = 200
-
#include
<wiringpi.h>
-
#include
<softpwm.h>
-
#include
<stdio.h>
-
// 定義控制舵機的引腳為:GPIO1
-
#define PWM_PIN 1
-
int main(void)
-
{
-
printf("wiringPi-C PWM test programn")
;
-
wiringPiSetup();
-
pinMode(PWM_PIN, PWM_OUTPUT);
// 設定PWM輸出
-
pwmSetMode(PWM_MODE_MS);
// 設定傳統模式
-
pwmSetClock(192);
// 設定分頻
-
pwmSetRange(2000);
// 設定周期分為2000步
-
printf("目前方向: -90度n");
-
pwmWrite(PWM_PIN,
50)
;
-
delay(2000);
-
printf("目前方向: -45度n");
-
pwmWrite(PWM_PIN,
100)
;
-
delay(2000);
-
printf("目前方向: 0度n");
-
pwmWrite(PWM_PIN,
150)
;
-
delay(2000);
-
printf("目前方向: 45度n");
-
pwmWrite(PWM_PIN,
200)
;
-
delay(2000);
-
printf("目前方向: 90度n");
-
pwmWrite(PWM_PIN,
250)
;
-
delay(2000);
-
int i =
0;
-
while(1)
{
-
printf("順時針n");
-
for(i =
250; i >=
50; i--)
{
-
pwmWrite(PWM_PIN, i)
;
-
delay(50);
-
}
-
printf("逆時針n");
-
for(i =
50; i <=
250; i++)
{
-
pwmWrite(PWM_PIN, i)
;
-
delay(50);
-
}
-
}
-
return
;
-
}
将代碼儲存到
pwm_sg90.c
檔案,編譯、運作。
-
# 編譯
-
gcc pwm_sg90.c -o pwm_sg90 -lwiringPi
-
# 運作
-
sudo ./pwm_sg90
使用軟體PWM接口
由于硬體PWM接口隻有4個,有時可能會被其他資源占用,此時就需要使用軟體模拟PWM接口,wiringpi的軟體PWM可以在任意一個GPIO口上實作。接口函數介紹詳見 《 入門WiringPi庫的PWM接口(C和Python) 》
根據公式:
PWMfreq = 1 x 10^6 / (100 x range)
,要得到PWM頻率為50Hz,則range為200,即周期分為200步,控制精度相比硬體PWM較低。
舵機接線:舵機 Pin | 樹莓派 Pin |
---|
-
#include
<wiringpi.h>
-
#include
<softpwm.h>
-
#include
<stdio.h>
-
#define PWM_PIN 0
-
int main(void)
-
{
-
printf("wiringPi-C PWM test programn")
;
-
// 初始化
-
wiringPiSetup();
-
pinMode(PWM_PIN, OUTPUT);
-
softPwmCreate(PWM_PIN,
0,
200);
// 設定周期分為200步
-
printf("目前方向: -90度n");
-
softPwmWrite(PWM_PIN,
5);
-
delay(1000);
-
printf("目前方向: -45度n");
-
softPwmWrite(PWM_PIN,
10);
-
delay(1000);
-
printf("目前方向: 0度n");
-
softPwmWrite(PWM_PIN,
15);
-
delay(1000);
-
printf("目前方向: 45度n");
-
softPwmWrite(PWM_PIN,
20);
-
delay(1000);
-
printf("目前方向: 90度n");
-
softPwmWrite(PWM_PIN,
25);
-
delay(1000);
-
int i =
0;
-
while(1)
{
-
printf("順時針n");
-
for(i =
25; i >=
5; i--)
{
-
softPwmWrite(PWM_PIN, i)
;
-
delay(20);
-
}
-
printf("逆時針n");
-
for(i =
5; i <=
25; i++)
{
-
softPwmWrite(PWM_PIN, i)
;
-
delay(20);
-
}
-
}
-
return
;
-
}
将代碼儲存到
pwms_sg90.c
檔案,編譯、運作。
-
# 編譯
-
gcc pwms_sg90.c -o pwms_sg90 -lwiringPi
-
# 運作(可不加sudo)
-
sudo ./pwms_sg90
由于PWM周期隻有200步,控制細分度較低。
SG90舵機控制(Python版)
使用硬體PWM接口
舵機接線、PWM頻率設定等和C語言版類似,具體
代碼如下:-
#!/usr/bin/env python
-
# coding=utf-8
-
# 檢視WiringPi源檔案獲得
-
INPUT =
-
OUTPUT =
1
-
PWM_OUTPUT =
2
-
GPIO_CLOCK =
3
-
SOFT_PWM_OUTPUT =
4
-
SOFT_TONE_OUTPUT=
5
-
PWM_TONE_OUTPUT =
6
-
LOW =
-
HIGH =
1
-
PWM_MODE_MS =
-
PWM_MODE_BAL =
1
-
import wiringpi
-
# 設定舵機控制引腳為GPIO1
-
PWM_PIN =
1
-
wiringpi.wiringPiSetup()
# WiringPi初始化
-
wiringpi.pinMode(PWM_PIN, PWM_OUTPUT)
# 設定引腳為PWM模式
-
wiringpi.pwmSetMode(PWM_MODE_MS)
# 修改PWM為傳統模式
-
wiringpi.pwmSetClock(192)
# 設定分頻系數
-
wiringpi.pwmSetRange(2000)
# 設定周期步長(占空比範圍)
-
print
"目前方向: -90度n"
-
wiringpi.pwmWrite(PWM_PIN,
50)
-
wiringpi.delay(1000)
-
print
"目前方向: -45度n"
-
wiringpi.pwmWrite(PWM_PIN,
100)
-
wiringpi.delay(1000)
-
print
"目前方向: 0度n"
-
wiringpi.pwmWrite(PWM_PIN,
150)
-
wiringpi.delay(1000)
-
print
"目前方向: 45度n"
-
wiringpi.pwmWrite(PWM_PIN,
200)
-
wiringpi.delay(1000)
-
print
"目前方向: 90度n"
-
wiringpi.pwmWrite(PWM_PIN,
250)
-
wiringpi.delay(1000)
-
while
1:
-
print
"順時針n"
-
for duty in range(250,
50,
-1):
-
wiringpi.pwmWrite(PWM_PIN, duty)
-
wiringpi.delay(10)
-
print
"逆時針n"
-
for duty in range(50,
250):
-
wiringpi.pwmWrite(PWM_PIN, duty)
-
wiringpi.delay(10)
将代碼儲存到
pwm_sg90.py
檔案, 輸入以下指令運作程式:
-
sudo python pwm_sg90.py
最終效果和C語言版本一樣,這裡就不再貼圖了。
使用軟體PWM接口
參數設定介紹具體可見上文C語言版本。
代碼如下: 檢視詳情:https://www.icxbk.com/article/detail/1811.html