舵机的控制原理:
舵机是一种位置伺服的驱动器,与马达不同,我们需要马达提供的是旋转,控制的是转速和方向。而舵机不需要整圈的旋转,需要的是旋转角度并维持住。一般舵机旋转的角度范围是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()
---------------------------------------
步进电机能够被精确定位,正向或反向一次性转动“一步”,并且也能够连续转动。连接方式如下图:
#! /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()