raspberry pi 控制舵机

技术经验 dingxiao 阅读数:2862 2018年8月9日 10:12

Rpi控制舵机

0x01-舵机

舵机(英文叫Servo):它由直流电机、减速齿轮组、传感器和控制电路组成的一套自动控制系统。通过发送信号,指定输出轴旋转角度。舵机一般而言都有最大旋转角度(比如180度。)与普通直流电机的区别主要在,直流电机是一圈圈转动的,舵机只能在一定角度内转动,不能一圈圈转(数字舵机可以在舵机模式和电机模式中切换,没有这个问题)。普通直流电机无法反馈转动的角度信息,而舵机可以。用途也不同,普通直流电机一般是整圈转动做动力用,舵机是控制某物体转动一定角度用(比如机器人的关节)。

普通模拟舵机的分解图,其组成部分主要有齿轮组、电机、电位器、电机控制板、壳体几大部分组成。

电机控制板主要是用来驱动电机和接受电位器反馈回来的信息。电机嘛,动力的来源了,这个不用太多解释。电位器这里的作用主要是通过其旋转后产生的电阻的变化,把信号发送回电机控制板,使其判断输出轴角度是否输出正确。齿轮组的作用主要是力量的放大,使小功率电机产生大扭矩。

0x02-舵机控制

舵机的伺服系统由可变宽度的脉冲来进行控制,控制线是用来传送脉冲的。脉冲的参数有最小值,最大值,和频率。一般而言,舵机的基准信号都是周期为20ms,宽度为1.5ms。这个基准信号定义的位置为中间位置。舵机有最大转动角度,中间位置的定义就是从这个位置到最大角度与最小角度的量完全一样。最重要的一点是,不同舵机的最大转动角度可能不相同,但其中间位置的脉冲宽度是一定的,都是1.5ms。

当舵机接收到一个小于1.5ms的脉冲,输出轴会以中间位置为标准,逆时针旋转一定角度。接收到的脉冲大于1.5ms情况相反。不同品牌,甚至同一品牌的不同舵机,都会有不同的最大值和最小值。一般而言,最小脉冲为1ms,最大脉冲为2ms。

0x03-Rpi控制舵机

前段时间购入舵机平台,想用此来作为摄像头云台控制。编程语言可通过两种方式进行控制。

  • Java-本人习惯在Rpi平台上使用java进行编程,且java有专门针对Rpi嵌入式控制的开发库pi4j,里面提供了Rpi几乎所有接口的java控制api,当然也提供了控制舵机的PWM控制。

  • Python-最近一段时间都在折腾python,python确实很强大,社区发展很完善,对Rpi支持也很好,随便一搜就是一大堆资料,故用之。

0x04-实践之-Java&Pi4j库

代码参考pi4j-pwmExample

实现2路舵机控制,实现代码为:

   public static Pin pin_pwm1 = CommandArgumentParser.getPin(
           RaspiPin.class,    // pin provider class to obtain pin instance from
           RaspiPin.GPIO_24);  // default pin if no pin argument found

public static Pin pin_pwm2 = CommandArgumentParser.getPin(
           RaspiPin.class,    // pin provider class to obtain pin instance from
           RaspiPin.GPIO_23);  // default pin if no pin argument found

public static  GpioPinPwmOutput pwm1 = gpio.provisionPwmOutputPin(pin_pwm1);
public static  GpioPinPwmOutput pwm2 = gpio.provisionPwmOutputPin(pin_pwm2);
public static int PWM_Count = 50;

   public void PWM_Java(int pwm)
   {
       com.pi4j.wiringpi.Gpio.pwmSetMode(com.pi4j.wiringpi.Gpio.PWM_MODE_MS);
       com.pi4j.wiringpi.Gpio.pwmSetRange(1000);
       com.pi4j.wiringpi.Gpio.pwmSetClock(500);
    pwm1.setPwm(pwm);
    pwm2.setPwm(pwm);
   }

其中,PWM_Java(int pwm)的给定值范围为(20-90).。

0x05-实践之-Python

python参考代码为:

  import RPi.GPIO as GPIO
import time

servoPIN = 19
GPIO.setmode(GPIO.BCM)
GPIO.setup(servoPIN, GPIO.OUT)

p = GPIO.PWM(servoPIN, 50) # GPIO 17 for PWM with 50Hz
p.start(2.5) # Initialization
try:
 while True:
   p.ChangeDutyCycle(5)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(7.5)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(10)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(12.5)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(10)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(7.5)
#    time.sleep(0.5)
#    p.ChangeDutyCycle(5)
   time.sleep(1)
   p.ChangeDutyCycle(2.5)
   time.sleep(1)
except KeyboardInterrupt:
 p.stop()
 GPIO.cleanup()

在此基础试验了python带命令行参数运行,代码参考地址编写带命令行参数的 Python 程序

最终修改代码为:

  # -*- coding:utf-8 -*- 

import RPi.GPIO as GPIO
import time
import sys, getopt

def PWM(argv):

   pwm_fy = ""
   pwm_xh = ""

   try:
       # 这里的 h 就表示该选项无参数,i:表示 i 选项后需要有参数
       opts, args = getopt.getopt(argv, "hf:x:",["pwm_fy=","pwm_xh"])
   except getopt.GetoptError:
       print 'Error: servo.py -f <pwm_fy> -x <pwm_xh>'
       sys.exit(2)

   for opt, arg in opts:

       if opt == "-h":
           print 'servo.py -f <pwm_fy> -x <pwm_xh>'
           sys.exit()
       elif opt in ("-f"):
           pwm_fy = arg
       elif opt in ("-x"):
           pwm_xh = arg

   print("pwm_fy"+pwm_fy)
   print("pwm_xh"+pwm_xh)

   servoPIN_fy = 13
   servoPIN_xh = 19
   GPIO.setmode(GPIO.BCM)
   GPIO.setup(servoPIN_fy,GPIO.OUT)
   GPIO.setup(servoPIN_xh,GPIO.OUT)

   p_fy = GPIO.PWM(servoPIN_fy, 50) # GPIO 17 for PWM with 50Hz
   p_fy.start(float(pwm_fy)) # Initialization
   p_fy.ChangeDutyCycle(float(pwm_fy))

   p_xh = GPIO.PWM(servoPIN_xh, 50) # GPIO 17 for PWM with 50Hz
   p_xh.start(float(pwm_xh)) # Initialization
   p_xh.ChangeDutyCycle(float(pwm_xh))

   time.sleep(3)
   p_fy.stop()
   p_xh.stop()
   GPIO.cleanup()

命令行运行时,输入python servo.py -f 9 -x 3

高低运行至9,方位运行至3。

0x06-舵机测试平台

此次试验使用Rpi3配合3.5寸tft作为测试平台。



captcha
    暂无评论