天天看點

pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)

pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)
難度:

★★

讀者:

适合有

C語言

Python

程式設計基礎,對舵機和PWM等有一定了解的讀者。

往期相關文章:

  • 《 樹莓派4B-WiringPi庫的安裝和使用 》
  • 《 入門WiringPi庫的PWM接口 》
沒有安裝WiringPi的讀者,可先閱讀往期文章,搭建好環境。

本文将介紹如何在樹莓派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) 舵機轉過的角度(度)
pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)

當然,讀者也可以根據自己的需要,規定0.5ms的脈沖寬度為舵機的0度位置,2.5ms脈沖寬度為舵機的180度位置。

SG90模拟舵機實物圖

pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)
拆解圖:
pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)

可以看到舵機主要由

馬達

減速齒輪

控制電路

組成,其中綠色的是電位器,用來确定舵機輸出軸角度位置。

模拟舵機的程式設計

SG90舵機控制(C語言版)

使用硬體PWM接口

樹莓派預設PWM模式是

Balanced

模式,該模式下的PWM頻率遠大于舵機的50Hz,是以需要修改PWM的頻率,此時我們需要将PWM模式切換到

Mark:Space

模式(占空比模式)。查閱資料,樹莓派的PWM時鐘基礎頻率是19.2MHz,通過

pwmSetClock()

函數設定分頻(預設是32分頻),PWM頻率計算公式:

  1. pwmFrequency(Hz)

    =

    19.2*10^6

    Hz

    / pwmClock / pwmRange

為了得到更好的控制精度,這裡将

range

設定為2000,即周期分為2000步,控制精度更高。要取得PWM頻率為50Hz,那麼divisor為:

  1. 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,

指令如下:
  1. $ gpio mode 1 pwm # 設定GPIO1為PWM輸出腳

  2. $ gpio pwm-ms # 切換到占空比、傳統模式

  3. $ gpio pwmc 192

    # 設定時鐘分頻

  4. $ gpio pwmr 2000

    # 每個刻度 0.01 ms,2000 * 0.01ms = 20ms

  5. $ gpio pwm 1

    50

    # 0.5 ms (-90°) => Maxrange * 占空比 = 2000 * 2.5% = 50

  6. $ gpio pwm 1

    100

    # 1.0 ms (-45°) => 2000 * 5% = 100

  7. $ gpio pwm 1

    150

    # 1.5 ms (0°) => 2000 * 7.5% = 150

  8. $ gpio pwm 1

    200

    # 2.0 ms (45°) => 2000 * 10% = 200

代碼實作如下:
  1. #include

    <wiringpi.h>

  2. #include

    <softpwm.h>

  3. #include

    <stdio.h>

  4. // 定義控制舵機的引腳為:GPIO1

  5. #define PWM_PIN 1

  6. int main(void)

  7. {

  8. printf("wiringPi-C PWM test programn")

    ;

  9. wiringPiSetup();

  10. pinMode(PWM_PIN, PWM_OUTPUT);

    // 設定PWM輸出

  11. pwmSetMode(PWM_MODE_MS);

    // 設定傳統模式

  12. pwmSetClock(192);

    // 設定分頻

  13. pwmSetRange(2000);

    // 設定周期分為2000步

  14. printf("目前方向: -90度n");

  15. pwmWrite(PWM_PIN,

    50)

    ;

  16. delay(2000);

  17. printf("目前方向: -45度n");

  18. pwmWrite(PWM_PIN,

    100)

    ;

  19. delay(2000);

  20. printf("目前方向: 0度n");

  21. pwmWrite(PWM_PIN,

    150)

    ;

  22. delay(2000);

  23. printf("目前方向: 45度n");

  24. pwmWrite(PWM_PIN,

    200)

    ;

  25. delay(2000);

  26. printf("目前方向: 90度n");

  27. pwmWrite(PWM_PIN,

    250)

    ;

  28. delay(2000);

  29. int i =

    0;

  30. while(1)

    {

  31. printf("順時針n");

  32. for(i =

    250; i >=

    50; i--)

    {

  33. pwmWrite(PWM_PIN, i)

    ;

  34. delay(50);

  35. }

  36. printf("逆時針n");

  37. for(i =

    50; i <=

    250; i++)

    {

  38. pwmWrite(PWM_PIN, i)

    ;

  39. delay(50);

  40. }

  41. }

  42. return

    ;

  43. }

将代碼儲存到

pwm_sg90.c

檔案,編譯、運作。

  1. # 編譯

  2. gcc pwm_sg90.c -o pwm_sg90 -lwiringPi

  3. # 運作

  4. sudo ./pwm_sg90

效果如下圖:
pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)

使用軟體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
代碼實作如下:
  1. #include

    <wiringpi.h>

  2. #include

    <softpwm.h>

  3. #include

    <stdio.h>

  4. #define PWM_PIN 0

  5. int main(void)

  6. {

  7. printf("wiringPi-C PWM test programn")

    ;

  8. // 初始化

  9. wiringPiSetup();

  10. pinMode(PWM_PIN, OUTPUT);

  11. softPwmCreate(PWM_PIN,

    0,

    200);

    // 設定周期分為200步

  12. printf("目前方向: -90度n");

  13. softPwmWrite(PWM_PIN,

    5);

  14. delay(1000);

  15. printf("目前方向: -45度n");

  16. softPwmWrite(PWM_PIN,

    10);

  17. delay(1000);

  18. printf("目前方向: 0度n");

  19. softPwmWrite(PWM_PIN,

    15);

  20. delay(1000);

  21. printf("目前方向: 45度n");

  22. softPwmWrite(PWM_PIN,

    20);

  23. delay(1000);

  24. printf("目前方向: 90度n");

  25. softPwmWrite(PWM_PIN,

    25);

  26. delay(1000);

  27. int i =

    0;

  28. while(1)

    {

  29. printf("順時針n");

  30. for(i =

    25; i >=

    5; i--)

    {

  31. softPwmWrite(PWM_PIN, i)

    ;

  32. delay(20);

  33. }

  34. printf("逆時針n");

  35. for(i =

    5; i <=

    25; i++)

    {

  36. softPwmWrite(PWM_PIN, i)

    ;

  37. delay(20);

  38. }

  39. }

  40. return

    ;

  41. }

将代碼儲存到

pwms_sg90.c

檔案,編譯、運作。

  1. # 編譯

  2. gcc pwms_sg90.c -o pwms_sg90 -lwiringPi

  3. # 運作(可不加sudo)

  4. sudo ./pwms_sg90

效果如下圖:
pwm控制舵機轉動角度程式_[樹莓派系列] 使用WiringPi庫入門模拟舵機-SG90(C和Python)

由于PWM周期隻有200步,控制細分度較低。

SG90舵機控制(Python版)

使用硬體PWM接口

舵機接線、PWM頻率設定等和C語言版類似,具體

代碼如下:
  1. #!/usr/bin/env python

  2. # coding=utf-8

  3. # 檢視WiringPi源檔案獲得

  4. INPUT =

  5. OUTPUT =

    1

  6. PWM_OUTPUT =

    2

  7. GPIO_CLOCK =

    3

  8. SOFT_PWM_OUTPUT =

    4

  9. SOFT_TONE_OUTPUT=

    5

  10. PWM_TONE_OUTPUT =

    6

  11. LOW =

  12. HIGH =

    1

  13. PWM_MODE_MS =

  14. PWM_MODE_BAL =

    1

  15. import wiringpi

  16. # 設定舵機控制引腳為GPIO1

  17. PWM_PIN =

    1

  18. wiringpi.wiringPiSetup()

    # WiringPi初始化

  19. wiringpi.pinMode(PWM_PIN, PWM_OUTPUT)

    # 設定引腳為PWM模式

  20. wiringpi.pwmSetMode(PWM_MODE_MS)

    # 修改PWM為傳統模式

  21. wiringpi.pwmSetClock(192)

    # 設定分頻系數

  22. wiringpi.pwmSetRange(2000)

    # 設定周期步長(占空比範圍)

  23. print

    "目前方向: -90度n"

  24. wiringpi.pwmWrite(PWM_PIN,

    50)

  25. wiringpi.delay(1000)

  26. print

    "目前方向: -45度n"

  27. wiringpi.pwmWrite(PWM_PIN,

    100)

  28. wiringpi.delay(1000)

  29. print

    "目前方向: 0度n"

  30. wiringpi.pwmWrite(PWM_PIN,

    150)

  31. wiringpi.delay(1000)

  32. print

    "目前方向: 45度n"

  33. wiringpi.pwmWrite(PWM_PIN,

    200)

  34. wiringpi.delay(1000)

  35. print

    "目前方向: 90度n"

  36. wiringpi.pwmWrite(PWM_PIN,

    250)

  37. wiringpi.delay(1000)

  38. while

    1:

  39. print

    "順時針n"

  40. for duty in range(250,

    50,

    -1):

  41. wiringpi.pwmWrite(PWM_PIN, duty)

  42. wiringpi.delay(10)

  43. print

    "逆時針n"

  44. for duty in range(50,

    250):

  45. wiringpi.pwmWrite(PWM_PIN, duty)

  46. wiringpi.delay(10)

将代碼儲存到

pwm_sg90.py

檔案, 輸入以下指令運作程式:

  1. sudo python pwm_sg90.py

最終效果和C語言版本一樣,這裡就不再貼圖了。

使用軟體PWM接口

參數設定介紹具體可見上文C語言版本。

代碼如下: 檢視詳情:

https://www.icxbk.com/article/detail/1811.html