2017-08-03 48 views
2

我試圖用樹莓派中的python控制連續伺服(DF15RSMG),但連續伺服無法停止。代碼如下:在Raspberry Pi中使用python控制連續伺服,但連續伺服不能停止

import RPi.GPIO as GPIO 
import time 
import signal 
import atexit 

atexit.register(GPIO.cleanup)  

GPIO.setmode(GPIO.BCM) 
GPIO.setup(17, GPIO.OUT, initial=False) 
p = GPIO.PWM(17,50) #50HZ 
p.start(0) 
time.sleep(2) 

while(True): 
    for i in range(0,181,10): 
    p.ChangeDutyCycle(2.5 + 10 * i/180) 
    time.sleep(0.02)      
    p.ChangeDutyCycle(0)      
    time.sleep(0.2) 

    for i in range(181,0,-10): 
    p.ChangeDutyCycle(2.5 + 10 * i/180) 
    time.sleep(0.02) 
    p.ChangeDutyCycle(0) 
    time.sleep(0.2) 

上面的代碼爲SG90 Servo.Having工作看到了這個問題Raspberry pi servo doesn't stop,但我仍然不知道如何解決這個問題,我該怎麼辦?

回答

2

我認爲你可能有多個問題 - 例如你似乎用整數算術計算duy循環。要測試它,請在每個循環中添加一個print i,i/180, 2.5+10*i/180語句。使用我正在使用的python 2.7,因爲計算10 * i/180是使用整數算術計算的,所以您請求的佔空比以循環每隔1秒爲單位跳過一次。您只需更改寬度計算即可使用10.0 * i/180 - 但稍後更多。

然而看着你的代碼,它似乎簡單地將PWM設置爲7.5%,所以電機應該停止0.2秒。

也不需要在每次設置後將佔空比設置回0 - 不知道爲什麼你這樣做。

0.2s在速度增量之間等待的時間並不多(因此您可能會錯過停止的時間段),使其變慢可能會更容易看出發生了什麼。

最重要的是,對於連續運動伺服,它是由脈衝寬度控制的伺服的速度 - 所以當驅動脈衝寬度增加到高於標稱「零」寬度時,伺服更快地「前進」,並且隨着脈衝寬度的減小比零寬度更窄,反向更快。

所以伺服用於脈衝寬度w毫秒的速度被計算是這樣的:

speed% = (w-1.5)*100 

其中w變化毫秒0.5和2.5之間。 100%前進速度需要2.5ms的脈衝寬度,100%反向(即-100%)速度需要0.5ms的脈衝寬度。以20ms的重複間隔,這些對應於2.5-12.5%。

請注意,伺服將在1.5ms左右有一個小的死區,以便它可能會停止在1.45-1.55ms的輸入脈衝寬度範圍內,否則很難從中獲得精確的零速度。

因此,要停止伺服,請將脈衝寬度設置爲「零」寬度1.5ms,並保持該狀態,伺服將不會旋轉。正確的時候沒有問題 - 保持傳統模擬伺服所需的脈衝數量。這個伺服是一個數字伺服,因此可以有更快的重複頻率,所以你可以使用5ms,例如,它可以使脈衝寬度的分辨率從10-50%變化。作爲一個數字伺服器,它似乎只需要一個脈衝來設置它的速度,你也可以在沒有20ms重複頻率的情況下工作,當你想改變速度時只產生一個脈衝。

無論如何,回到您的代碼,基本上,對於20ms的重複和1.5ms的標稱寬度,您需要將佔空比設置爲7.5%,伺服將停止。你的代碼應該增加和減少這個,以使伺服反向和前進。

我的參考資料是amazon.co.uk上的這個信息https://www.amazon.com/DFRobot-DF15RSMG-Degree-Standard-Servo/dp/B014L5CBBA這是最高的搜索結果。

我沒有測試這個硬件,但這樣的事情應該更好地工作,我假設你使用作品的初始化代碼:

import RPi.GPIO as GPIO 
import time 
import signal 
import atexit 

atexit.register(GPIO.cleanup)  

GPIO.setmode(GPIO.BCM) 
GPIO.setup(17, GPIO.OUT, initial=False) 
p = GPIO.PWM(17,50) #50HZ 
p.start(0) 
time.sleep(2) 

STEPS=10 # the number of steps either side of nominal 
NOMINAL=7.5 # the 'zero' PWM %age 
RANGE=1.0 # the maximum variation %age above/below NOMINAL 

while(True): 
    # loop first over "forward" ramp up/down, then reverse. 
    for direction in [+1.0,-1.0]: 
     # step from 0 to 100% then back to just above zero 
     # (next time round the loop will do the 0) 
     for step in list(range(STEPS+1))+list(range(STEPS-1,0,-1)): 
      dutycycle = NOMINAL + direction*RANGE*step/STEPS 
      print direction, step, dutycycle 
      p.ChangeDutyCycle(dutycycle) 
      time.sleep(1.0) 

最後的意見 - 如果你想了解更多關於你的代碼在做什麼,分開計算佔空比的非常簡單的步驟允許你添加一個打印語句,而不用兩次寫入計算。 TBH這是一個原因,我不是Python的非常強大的單線程結構如列表理解的忠實粉絲:一旦你讓他們工作,他們是偉大的,但對於初學者他們不工作時,他們搶奪你的能力看看裏面發生了什麼。更好的方法是簡單地使用更多的代碼行和for循環,如果出現問題則添加打印,並在循環運行後評論打印輸出。

FINAL最後一件事 - 如果您希望伺服器在您退出代碼時停止,請給它一個零寬度爲1.5ms的脈衝,否則它不會停止。爲確保伺服器獲得此脈衝,在設置後至少進行20ms的睡眠:

p.ChangeDutyCycle(NOMINAL) 
time.sleep(0.1)