伺服电机主要适用于角度需要不断变化且可以保持的控制系统,常见的机械臂、多足机器人、遥
控船、摄像头云台等都可以使用伺服电机来实现。
1、简介
伺服电动机又被称为执行电动机、舵机,如图9.4所示,是由直流电机、减速齿轮组、电位器和控制电路组成的,封装在一个便于安装的外壳里,其主要作用是根据输入信号准确地转动到设定的角度。在自动控制系统中,通常用作执行元件,把接收到的电信号转换成电动机轴上的角位移或角速度输出。当给伺服电机地信号零电压时会出现无自转现象,转速随着转矩的增加而匀速下降。
通常情况下,伺服电机有3个输入引脚,GND(棕色、黑色)、VCC(红色)和 Signal(控制线、信号线,一般为橘色),中间的一条通常为电源线。
可以通过树莓派连接控制线,并发送一个PWM信号控制伺服电机转动到一个固定角度。这个PWM信号必须周期性发送,否则伺服电机就会转到一个
任意的角度。通常控制伺服电机的PWM 信号周期为20ms(50Hz),宽度在0.5~2.5ms(对应最小角度0°和最大角度180°),以周期为20ms、最大角度为180°为例的伺服电机为例。
由于RPiGPIO库只提供了控制PWM 信号占空比的功能,所以要将伺服电机旋转到指定的角度
就需要计算出对应的占空比,可以得出一个公式用于计算占空比(duty):
例如:如果转动的角度 direction为36°,代入公式中可得占空比为4.5%。
2、实验代码
控制sg90舵机旋转也比较简单,只需要给它输出PWM波,修改占空比就可以调整角度。这个和直流电机的PWM调制类似,只不过直流电机无法控制旋转的角度,只能控制旋转速度,而伺服电机可以精准的控制旋转的角度。SG90舵机的VCC接3.3V供电不足,要接5V供电引脚。
# 引入RPi.GPIO库
import RPi.GPIO as GPIO
# 指定编号方式为BOARD
GPIO.setmode(GPIO.BOARD)
# 定义接口
signal = 37
# 设置输出模式
GPIO.setup(signal, GPIO.OUT)
# PWM信号频率(1000/周期T)
frequency = 50
# 创建PWM对象,并设置频率为50
pwm = GPIO.PWM(signal, frequency)
def get_duty(direction):
"""计算占空比"""
# 如果转化为百分数,使用ChangeDutyCycle()方法时还需再转化回来
duty = (1 / 18) * direction + 2.5
return duty
if __name__ == '__main__':
try:
# 启动PWM,并设置初始占空比0
pwm.start(0)
while True:
# 输入一个角度
# 应该先判断用户输入是否合法
# 计算占空比
direction = float(input("Pleas input a direction between 0 an 180:"))
duty = get_duty(direction)
# 改变PWM占空比
pwm.ChangeDutyCycle(duty)
except Exception as e:
print('An exception has happened', e)
finally:
# 停止PWM
pwm.stop()
# 结束进程,释放GPIO引脚
GPIO.cleanup()
3、PCA9685
如果要驱动多个舵机,控制机械臂、摄像头云台等,为了防止占用过多的GPIO端口,可以使用PCA9685模块来驱动多个舵机。
PCA9685是一款基于I²C总线通信的12位精度16通道PWM波输出的芯片,该芯片最初由NXP推出时主要面向LED开关调光,同样可用于控制舵机、电机等任何可以适用PWM控制的电气设备。
利用I²C总线通信的功能特性,使其常用于拓展主控芯片的控制能力,因为其仅需两根线同主机芯片建立I²C通信,即可替代主控芯片的GPIO引脚来输出PWM波,节省主控芯片资源,这项特点在需要控制的设备数量超过主控芯片的可用GPIO引脚数量时将尤为突出。
供电部分
大多数的舵机设计电压都是在5~6V,尤其在多个舵机同时运行时,跟需要有大功率的电源供电。如果直接使用5V或3.3V引脚直接为舵机供电,会出现一些难以预测的问题,所以需要合适的外部电源为驱动板供电。外部电源通常5-7V或稍微高点也可以,接中央部分的绿色V+和GND。
4、安装adafruit_pca9685驱动多个舵机代码
# sudo pip3 install adafruit-blinka
# sudo pip3 install adafruit-circuitpython-pca9685
# sudo pip3 install adafruit-circuitpython-servokit
import time
from adafruit_pca9685 import PCA9685
from board import SCL, SDA
import busio
from adafruit_motor import servo
i2c_bus = busio.I2C(SCL, SDA)
pwm = PCA9685(i2c_bus) # 使用默认地址初始化PWM设备
pwm.frequency = 50 # 将频率设置为50 Hz
servo_12 = servo.Servo(pwm.channels[12]) # 指定第12通道的舵机(从0开始)
servo_15 = servo.Servo(pwm.channels[15]) # 指定第15通道的舵机
print('Moving servo on channel 0, press Ctrl-C to quit...')
servo_12.angle = 90
servo_15.angle = 90
while True:
# 伺服电机转动最小角度和最大角度
servo_12.angle = 0
servo_15.angle = 0
time.sleep(1)
servo_12.angle = 0
servo_15.angle = 180
time.sleep(1)