树莓派操控SG90舵机

时间:2018-08-23 20:09:51   收藏:0   阅读:6968

这里使用树莓派来操作sg90的舵机。先看一下这个舵机的样子:

技术分享图片

这就是传说中的SG90舵机啦,转角是0~180.


 SG90舵机接线:

  SG90舵机有三条线:黄线红线(还是黑?)线

  这三条线的作用是:红线VCC,灰线GND,黄线控制线。所以我们这里主要是操控黄线来控制舵机。

然后这里有个非常非常坑的地方,就是这个舵机是需要5V电压输入的。所以你在把VCC接到树莓派上时你得接5V的引脚而不是3.3V的。这个情况我当时在stm32也遇到过:明明程序写的是对的,但是舵机就是转不起来。。。因为stm32的GPIO一般都是3.3V的,我也就没能幸免??(谁让我是硬件白痴呢??)。所以一开始接线要接对了。


PWM介绍

  我们如何通过一根操作线来操作舵机呢?答案就是使用PWM脉冲宽度调制技术。那么啥叫PWM呢?这里我简单的说一下我的理解:

  我们树莓派或者是其他单片机一个引脚只能输出两个特定的电平——高电平和低电平。在树莓派上大多的GPIO都是高电平3.3V,低电平0V。但是如果我想要输出3.3~0V之间的电压怎么办呢?比如输出一个2V?树莓派(以及stm32,C51之类的)是没有办法直接设置引脚的电平来达到输出2V的。因为通过树莓派来说,你的GPIO.setup(channel,state)里的state只能是GPIO.HIGH和GPIO.LOW,没有什么GPIO.twoV之类的东西。那么我们就要使用PWM来输出介于低电平和高电平之间的电压。

  那么PWM是怎么做到的呢?很简单:我们不能直接输出2V,那我们换一种方式——通过给引脚一个周期脉冲,然后看这个脉冲的高电平部分占整个脉冲的比例,从而计算这个输出的电平。举个栗子??:比如我给出一个周期为20s的周期脉冲,然后让其中的高电平为12s,这样的话输出的电平就是(12/20)*3.3V≈2V,那么2V就输出了??。

  也就是说,PWM是根据周期脉冲中高电平所占的比例来确定GPIO输出的电压的。这里,高电平所占周期电平周期的比例称为占空比。这是个很重要的概念,要记住了。

  下面这个GIF就说明了PWM产生的结果。代码如下(待会会说这个代码):

技术分享图片 

 1 import RPi.GPIO as GPIO
 2 import time
 3 
 4 if __name__==‘__main__‘:
 5     GPIO.setmode(GPIO.BOARD)
 6     GPIO.setup(33,GPIO.OUT,initial=GPIO.LOW)
 7     GPIO.setup(35,GPIO.OUT)
 8     GPIO.setup(37,GPIO.OUT,initial=GPIO.HIGH)
 9     p=GPIO.PWM(35,150)
10     p.start(0)
11     try:
12          while True:
13             for dc in range(0,101,1): 
14                 p.ChangeDutyCycle(dc)
15                 time.sleep(0.1)
16             for dc in range(100,-1,-1):    
17                 p.ChangeDutyCycle(dc)
18                 time.sleep(0.1)
19     except KeyboardInterrupt:
20         pass
21     p.stop()
22     GPIO.cleanup()

 这个本来是我做PWM呼吸灯的代码,是循环输出0~3.3V的程序,这里我用电表测量了35(PWM输出)脚。通过电表的示数可明显看到引脚输出的电压的确在变化。

 

接下来说说树莓派里面如何实现PWM。主要就是在第9,10,14,21行:


 如何使用PWM操控舵机?

我们查看SG90的文档可以看见其占空比与转动角度的关系:

在周期20ms下:

  角度            占空比

  0.5ms-------------0度;   2.5% 
  1.0ms------------45度;   5.0% 
  1.5ms------------90度;   7.5%
  2.0ms-----------135度;  10.0%
  2.5ms-----------180度;  12.5%

这里直接给出了占空比与角度的关系,我们就不用关系电压的大小了。

这里SG90舵机的参考周期是20ms,也就是50KHZ。那么按照这个方法我们可以写出如下代码:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

Vcc_Pin=37
In_Pin=35  #操控线(黄线)

GPIO.setup(Vcc_Pin,GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(In_Pin,GPIO.OUT,initial=GPIO.LOW)
p=GPIO.PWM(In_Pin,50)  #设置频率为50KHz
p.start(0)
str1="please input the degree(0<=a<=120)\nor press q to quit\n"
r=input(str1)
try:
    while not r=="q":
        if r.isdigit():  #判断输入的字符串是不是数字
            r=int(r)    #是数字转换成数字
        else:
            print("please input a number(0<=num<=120)")
            continue
        if r<0 or r>180:  #越界提示
            print("a must be [0,120]")
            continue
        p.ChangeDutyCycle(2.5+r/360*20)  #通过用户输入的角度来改变舵机的角度
        time.sleep(0.02)
        r=str(input(str1))
except KeyboardInterrupt:
    pass
p.stop()
GPIO.cleanup()

 

这个程序让用户输入舵机转动的角度,从而转动舵机到相应的角度。

这里的p.ChangeDutyCycle(2.5+r/360*20)中的2.5+r/360*20是我推导的公式,用于转动舵机到指定的角度。这个公式使用比例来推导,很简单的。

最后的成果如下:

技术分享图片

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!