MG996R舵機180度與360度驅動,ULN2003A步進電機驅動,觸控開關控制

  • 產品類型: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()  

------------------------------------------------------------------------------------------------------------------

時基脈衝:一般舵機的控制需要一個20ms左右的時基脈衝
頻率:1s/0.020s=50Hz,也就是說最多1秒鐘內可以轉動50次
脈寬:週期20ms,脈寬0.5ms-2.5ms,當脈寬1.5ms時舵機在中立點(0度)
佔空比:脈寬0.5ms-2.5ms 對應的佔空比爲2.5% - 12.5% (脈寬/週期=0.5/20-2.5/20)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章