- 產品類型:MG996R舵機
- 產品扭矩:9kg/cm(4.8V),11kg/cm(6V)
- 產品速度:0.19秒/60°(4.8V),0.18秒/60°(6V) #0.19/60=0.0032s/度
- 轉動角度:180°
- 工作電壓:4.8 ~ 6V
- 齒輪形式:金屬齒輪
- 死區設定:5us (微秒)
- 產品重量:55g
- 產品尺寸:40.7mm × 19.7mm × 42.9mm
舵機的控制原理:
舵機是一種位置伺服的驅動器,與馬達不同,我們需要馬達提供的是旋轉,控制的是轉速和方向。而舵機不需要整圈的旋轉,需要的是旋轉角度並維持住。一般舵機旋轉的角度範圍是0 度到180 度。舵機引線爲3線,分別用棕、紅、橙三種顏色進行區分,舵機品牌和生產廠家不同,會有些許差異,使用之前需查看資料。我們使用的是最常見的舵機,棕、紅、橙分別對應“電源負極,電源正極,控制信號”。
舵機的伺服系統由可變寬度的脈衝來進行控制,橙色的控制線是用來傳送脈衝的。脈衝的參數有最小值,最大值,和頻率。一般而言,PWM控制舵機的基準信號週期爲20ms,基準脈寬爲1.5ms(中位),理論上脈寬應在1ms到2ms 之間,但是,實際上脈寬可由0.5ms 到2.5ms 之間,脈寬和舵機的轉角0°~180°相對應。這個基準脈寬信號1.5ms定義的位置爲中間位置。不同舵機的最大轉動角度可能不相同,但是其中間位置的脈衝寬度是一定的,那就是1.5ms。(以下爲PWM控制信號:20ms/2.5ms=8位)
舵機的PWM控制一般需要一個20ms的時基脈衝,該脈衝的高電平部分一般爲0.5ms~2.5ms範圍內的角度控制脈衝部分。以180度角度舵機爲例,對應的控制關係是這樣的:
0.5ms--------------0度; 2.5% (0.5ms高電平+19.5低電平)
1.0ms------------45度; 5.0% (1.0ms高電平+19.0低電平)
1.5ms------------90度; 7.5% (1.5ms高電平+18.5低電平)
2.0ms-----------135度;10% (2.0ms高電平+18.0低電平)
2.5ms-----------180度;12.5%(2.5ms高電平+17.5低電平)
角度轉換佔空比:2.5+角度/180*10 或 2.5+12.5/180*角度
#! /usr/bin/env python3
# encoding=utf-8
import RPi.GPIO as GPIO
import time
import signal
import atexit
atexit.register(GPIO.cleanup)
servopin=4
GPIO.setmode(GPIO.BCM)
GPIO.setup(servopin,GPIO.OUT,initial=False)
p=GPIO.PWM(servopin,50) #50HZ:頻率就是週期脈衝的週期的倒數 1s/0.02s=50Hz
p.start(2.5) #start(initdutycycle):佔空比0-100間,0表示暫不輸出
time.sleep(2)
while(True):
for i in range(0,181,10):
p.ChangeDutyCycle(2.5+i/180*10) #設置轉動角度:佔空比:2.5+10*角度/180
time.sleep(0.04) #等該20ms週期結束,防抖
p.ChangeDutyCycle(0) #歸零信號,防抖
time.sleep(0.2)
for i in range(181,0,-10):
p.ChangeDutyCycle(2.5+i/180*10)
time.sleep(0.04)
p.ChangeDutyCycle(0)
time.sleep(0.2)
GPIO.cleanup()
舵機轉動的方向不是由佔空比決定的,而是由脈衝長度 t 決定的。有的舵機使用的PWM頻率爲 fPWM=50HZ,其對應於的PWM週期 T=20 ms。脈衝長度 t 和轉動方向之間的關係是線性的,但也取決於電機和齒輪的配合。
注意:以下代碼中的a和b參數必須與您所使用的舵機類型相匹配。如下圖,舵機的佔空比:
import RPi.GPIO as GPIO
import time
P_pin=4
P_fpwm=50
a=12.5 #最大值180度
b=2.5 #最小值0度
def setup():
global pwm
GPIO.setmode(GPIO.BCM)
GPIO.setup(P_pin,GPIO.OUT)
pwm=GPIO.PWM(P_pin,P_fpwm)
pwm.start(0)
def setDirection(direction):
duty=b+a/180*float(direction) #佔空比:0度+每度佔空*角度
pwmChangeDutyCycle(duty)
print"角度=",direction,"->佔空比=",duty
time.sleep(0.04)
print "starting"
setup()
while(True):
for direction in range(0,180,1):
setDirection(direction)
time.sleep(0.02)
for direction in range(180,1,-1):
setDirection(direction)
time.sleep(0.02)
direction=0
setDirection(0)
GPIO.cleanup()
print "ok"
360度舵機控制:
#! /usr/bin/env python3
# encoding=utf-8
import RPi.GPIO as GPIO
import time
import signal
import atexit
atexit.register(GPIO.cleanup)
servopin=4
GPIO.setmode(GPIO.BCM)
GPIO.setup(servopin,GPIO.OUT,initial=False)
p=GPIO.PWM(servopin,50) #50HZ:頻率就是週期脈衝的週期的倒數
p.start(0) #start(initdutycycle):佔空比0-100間,0表示暫不輸出
time.sleep(2)
while(True):
p.ChangeDutyCycle(3) #正轉2.5高速-6.5-7.5底速-12.5高速反轉(調校以抖動穩定性爲準)
#time.sleep(1)
print 'jiaodu=',3
time.sleep(60)
p.ChangeDutyCycle(12)
#time.sleep(1)
print 'jiaodu=',12
time.sleep(60)
#p.ChangeDutyCycle(0) #歸零信號
time.sleep(0.2)
GPIO.cleanup()
---------------------------------------
ULN2003A控制步進電機
步進電機能夠被精確定位,正向或反向一次性轉動“一步”,並且也能夠連續轉動。連接方式如下圖:
#! /usr/bin/env python3
# encoding=utf-8
import RPi.GPIO as GPIO
import time
IN1 = 11 # pin11
IN2 = 12
IN3 = 13
IN4 = 15
def setStep(w1, w2, w3, w4): #啓用pin
GPIO.output(IN1, w1)
GPIO.output(IN2, w2)
GPIO.output(IN3, w3)
GPIO.output(IN4, w4)
def stop():
setStep(0, 0, 0, 0)
def forward(delay, steps): #正向步進
for i in range(0, steps):
setStep(1, 0, 0, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 0, 0, 1)
time.sleep(delay)
def backward(delay, steps): #反向步進
for i in range(0, steps):
setStep(0, 0, 0, 1)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(1, 0, 0, 0)
time.sleep(delay)
def setup():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # 引腳編碼方式
GPIO.setup(IN1, GPIO.OUT) # 引腳模式
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
def loop():
while True:
print "backward..."
backward(0.003, 512) # 512步--- 360 angle
print "stop..."
stop() # stop
time.sleep(3) # sleep 3s
print "forward..."
forward(0.005, 512)
print "stop..."
stop()
time.sleep(3)
def destroy():
GPIO.cleanup() # 清除
if __name__ == '__main__': # 程序入口
setup()
try:
loop()
except KeyboardInterrupt: # 當'Ctrl+C' 中斷
destroy()
加了個觸控開關:
#! /usr/bin/env python3
# encoding=utf-8
import RPi.GPIO as GPIO
import time
IN1 = 17 #電機
IN2 = 18
IN3 = 27
IN4 = 22
IN5 = 23 #觸控
IN6 = 13
IN7 = 26
IN8 = 19
IN9 = 4 #舵機
def setStep(w1, w2, w3, w4): #邁步函數
GPIO.output(IN1, w1)
GPIO.output(IN2, w2)
GPIO.output(IN3, w3)
GPIO.output(IN4, w4)
def stop():
setStep(0, 0, 0, 0)
def forward(delay, steps): #正向延遲,邁步循環
for i in range(0, steps):
setStep(1, 0, 0, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 0, 0, 1)
time.sleep(delay)
def backward(delay, steps): #反向延遲,邁步循環
for i in range(0, steps):
setStep(0, 0, 0, 1)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(1, 0, 0, 0)
time.sleep(delay)
def setup(): #gpio加載
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # Numbers GPIOs by physical location
GPIO.setup(IN1, GPIO.OUT) #電機
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
GPIO.setup(IN5, GPIO.IN) #觸摸開關
GPIO.setup(IN6, GPIO.IN)
GPIO.setup(IN7, GPIO.IN)
GPIO.setup(IN8, GPIO.IN)
GPIO.setup(IN9, GPIO.OUT) #舵機
def duoji360():
p=GPIO.PWM(IN9,50) #50HZ:頻率就是週期脈衝的週期的倒數
p.start(0) #start(initdutycycle):佔空比0-100間,0表示暫不輸出
p.ChangeDutyCycle(3.5) #正轉2.5高速-7.5底速-12.5高速反轉
print 'jiaodu=',3.5
time.sleep(1)
def loop():
while 1:
if(GPIO.input(IN5)==1):
print "backward..."
if(GPIO.input(IN8)==0):
i=1
i=i+1
backward(0.002, i) # 延遲0.002,邁512步- 360 angle
if(GPIO.input(IN8)==1):
print "stop..."
stop() # stop
time.sleep(1)
if(GPIO.input(IN6)==1):
print "forward..."
if(GPIO.input(IN8)==0):
i=1
i=i+1
forward(0.003, i)
if(GPIO.input(IN7)==1):
print "duoji360..."
duoji360()
time.sleep(1)
def destroy():
GPIO.cleanup()
if __name__ == '__main__':
setup()
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child function destroy() will be executed.
destroy()