树莓派控制舵机

from time import sleep
import RPi.GPIO as GPIO
 
GPIO.setmode(GPIO.BCM)#以BCM模式使用引脚
GPIO.setwarnings(False)# 去除GPIO警告
 
 
def setServoAngle(servo, angle):#此函数将角度转换为占空比
    pwm = GPIO.PWM(servo, 50)#设置pwm波为50Hz,也就是20ms一周期
    pwm.start(8)#启动pwm
    dutyCycle = angle / 18. + 3.#此公式由舵机调零推算得出(+3是偏移量)(占空比=%2.5+(目标角度/180°)*(%12.5-%2.5))
    pwm.ChangeDutyCycle(dutyCycle)#调整pwm占空比
    sleep(0.3)
    pwm.stop()#关闭pwm
 
 
if __name__ == '__main__':
    import sys
 
    servo = int(sys.argv[1])#外部输入参数
    GPIO.setup(servo, GPIO.OUT)#设置指定的引脚为输出模式
    setServoAngle(servo, int(sys.argv[2]))
    GPIO.cleanup()#清除引脚占用

python3 文件名 舵机引脚 舵机角度

  • 注意:控制舵机转动时,发送的控制舵机旋转的两条命令之间要有一定间隔,因为舵机执行转动命令转到固定角度需要一定的时间。
  • 有时执行时需要以sudo执行

硬件连接部分:
舵机为MG90S型号,由三根线控制,棕色为负,红色为正,橙色是信号线

此舵机可以由树莓派直接供电,不需要外接电源

棕色GND

红色VCC

橙色GPIO

舵机接线后一定要检查连接是否正确再上电!!!否则可能会烧坏树莓派!可以在舵机和树莓派之间接一10k电阻。保护树莓派。

此引脚图为网口对着自己时
舵机调零:
舵机旋转角度是绝对位置,每一个位置对应固定的角度(类似于tab缩进,光标在屏幕上有固定的位置,当按下tab键时,光标跳到固定位置而不是固定缩进多少格),mg90s的旋转角度为0°~180°。

舵机调零是指当代码控制舵机在某一位置时(例如0度),舵机臂有可能不在0°位置,此时要通过改变舵机臂的固定位置,使舵机臂物理上处于0°位置。

舵机控制原理:(引用于此秒懂舵机角度控制原理 – 八色木)
舵机内部的控制电路,电位计(可变电阻器)和电机均被连接到电路板上,如内部结构图的右边部分。控制电路通过电位计可监控舵机的当前角度。

如果轴的位置与控制信号相符,那么电机就会关闭。如果控制电路发现这个角度不正确,它就会控制马达转动,直到它达到指定的角度。舵机角度根据制造商的不同而有所不同。比如,一个180度的舵机,它可以在0度至180度之间运动。由于限位装置被安装在主输出装置上,超出这个范围机械结构就不能再转动了。

舵机的输出功率与它所需要转动的距离成正比。如果输出轴需要转动很长的距离,马达就会全速运转,如果它只需要短距离转动,马达就会以较慢的速度运行,这叫做速度比例控制。

控制线用于传输角度控制信号。这个角度是由控制信号脉冲的持续时间决定的,这叫做脉冲编码调制(PCM)。舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围,总间隔为2ms。脉冲的宽度将决定马达转动的距离。例如:1.5毫秒的脉冲,电机将转向90度的位置(通常称为中立位置,对于180°舵机来说,就是90°位置)。如果脉冲宽度小于1.5毫秒,那么电机轴向朝向0度方向。如果脉冲宽度大于1.5毫秒,轴向就朝向180度方向。以180度舵机为例,对应的控制关系是这样的:

0.5ms———— 0度;

1.0ms———— 45度;

1.5ms———— 90度;

2.0ms———– 135度;

2.5ms———– 180度;

占空比是指在一个脉冲循环内,通电时间相对于总时间所占的比例。占空比(Duty Ratio)在电信领域中有如下含义:例如:脉冲宽度1μs,信号周期4μs的脉冲序列占空比为0.25。
舵机代码中是以占空比来进行舵机旋转角度的控制,而占空比和角度的变化是线性,所以可以得到计算公式为:

占空比 = (0.5ms/20ms) + (旋转角度/180°)((2.5ms/20ms) – (0.5ms/20ms))

20ms是一个脉冲循环的周期,由设置的pwm波的频率为50Hz计算得到。

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
signal = 18
GPIO.setup(signal, GPIO.OUT)
frequency = 50
pwm = GPIO.PWM(signal, frequency)
def get_duty(direction):
    duty = (1/18)*direction + 2.5
    return duty

if __name__ == '__main__':
    try:
        pwm.start(0)
        while True:
            direction = float(input("Please input a direction between 0 and 180:"))
            duty = get_duty(direction)
            pwm.ChangeDutyCycle(duty)            
    except Exception as e:
        print('An exception has happened',e)        
    finally:
        pwm.stop()
        GPIO.cleanup()