说在前面: 在网上找了一圈有关树莓派控制舵机的代码,发现好多都是一模一样的,重点是它们都贴着“原创”标签。 ^ __ ^!
一、所需材料
- 9 G 180°微型舵机。
- 树莓派4.
- 5 V 电源。(可选)
二、PWM如何工作
树莓派不能直接输出模拟电信号,但我们可以使用PWM(脉宽调制)方法来模拟这一点。我们制作一个固定频率的数字信号,在那里我们将改变脉冲宽度,将“转换”改为“平均”输出电压的电平,我们可以使用这个“平均”电压水平来控制LED亮度。
频率本身不是重点,而是“占空比”,即脉冲“高”的时间除以波周期之间的关系。例如,假设我们在树莓派的 GPIO上产生一个50Hz的脉冲频率。周期(p)将是频率的倒数或20ms(1 / f)。如果我们的LED达到“半”亮度,我们的占空比必须为50%,这意味着“脉冲”将是10ms的“高”。而在这里,我们将用“占空比”来定义舵机的位置。
三、接线
一般舵机有三根控制线,分别为黄、红、灰(黑),这三根线分别接树莓派GPIO数据输出引脚、5V电源正极、GND。
对于舵机的供电,可以选择树莓派的5V输出,但为了树莓派的安全起见,建议用外部5V电源。充电宝就可以。
四、舵机校准
- 舵机参数
首先,你要清楚你的舵机参数。我使用的舵机基本参数如下:
范围 | 0°~180° |
---|---|
电源 | 5VDC |
工作频率 | 50Hz(周期:20 ms) |
脉冲宽度 | 1ms~2ms |
理论上,1ms对应舵机0°,1.5ms对应舵机90°,2ms对应舵机180°。
在利用Python编写舵机位置时,利用的是上述位置所对应的的“占空比”。
位置角度 | 脉冲宽度 | 占空比 |
---|---|---|
0° | 1ms | 5.0% |
90° | 1.5ms | 7.5% |
180° | 2ms | 10% |
其中,占空比 = 脉冲宽度/周期。 5.0% = 1ms/20ms
可以看出,占空比理论上应该在5%到10%之间变化。但是,舵机在实际上会有一些误差,需要我们校正,得到它的准确值。
- 舵机校正
在树莓派中运行以下代码:
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD) # GPIO引脚编号的两种方式之一,另一种是BCM。所用编号方式不同,pin也不同。
GPIO.setwarnings(False) # 禁用警告。
GPIO.setup(pin,GPIO.OUT) # pin为你所接的数据输出GPIO引脚。
p = GPIO.PWM(pin,50) # 在pin脚上产生频率为50HZ的PWM信号。
p.start(0) # 在引脚上设置一个初始PWM信号。
p.ChangeDutyCycle(3) # 通过输入不同的“占空比值”来观察舵机的位置变化,这里的“占空比”是3%。
time.sleep(1)
p.stop() # 停止PWM。
GPIO.cleanup() # 清理GPIO。
最终得到的角度和“占空比”的关系为:
角度 | 占空比 |
---|---|
0° | 2% |
90° | 7% |
180° | 12% |
进而,我们可以通过一组简单的二元一次方程,得到占空比和角度的关系表达式:
DutyCycle = angle/18 + 2
五、舵机控制代码
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
def setServoAngle(angle):
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(32, GPIO.OUT)
tilt = GPIO.PWM(32, 50)
tilt.start(0)
DutyCycle = angle/18 + 2
tilt.ChangeDutyCycle(DutyCycle)
time.sleep(1)
tilt.stop()
c = input("If you want to continue, type 'c' please. Type 'e' to end.")
while c == 'c':
angle = input('Please type an angle:') # input输入的是字符串,需要用int()函数转化成数字。
angle = int(angle)
setServoAngle(angle)
c = input("'c' or 'e'?")
GPIO.cleanup()
exit()
如有问题,欢迎评论区交流啊!