树莓派操控SG90舵机

目录

  1. 舵机接线
  2. PWM介绍
  3. 使用PWM控制舵机

 

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

sg90舵机

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


SG90舵机接线:

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

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

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


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行:

  • 首先只要想使用GPIO,就一定要初始化GPIO,这里的第7行先初始化35脚的GPIO为输出
  • 然后要说明哪个引脚使用PWM功能。第9行的GPIO.PWM(channel,frequency)指定channel脚使用PWM功能,这个PWM的频率为frequency。所谓频率就是周期的倒数嘛,也就是你的周期脉冲的周期的倒数啦。然后这个函数返回一个PWM对象,这里为p
  • 然后开始PWM,第10行p.start(initdutycycle)说明现在开始PWM输出啦,这里的initdutycycle是在开始时指定的占空比。这里为0也就是说0/frequency*5V为0V,暂时不输出电平。由于是指定占空比,所以initdutycycle在[0,100]区间之内。超出这个区间Python会报错。
  • 那么如何更改占空比呢?使用第14行的p.ChangeDutyCycle(dutycycle)来改变占空比。
  • 最后你用完PWM了需要将PWM停掉,也就是第21行的p.stop()

如何使用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)

In_Pin=35  #操控线(黄线)
        #VCC接在5V脚上,GND接在GND脚上
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是我推导的公式,用于转动舵机到指定的角度。这个公式使用比例来推导,很简单的。

最后的成果如下:

 

posted @ 2018-08-23 19:52  VisualGMQ  阅读(5665)  评论(0编辑  收藏  举报