前言
今天记录一下有关舵机的学习,由于我的舵机在51和STM32系列单片机上都好像有供电不足的情况,然后我的电源模块也没到,所以就用Arduino uno R3板对舵机相关学习进行记录。由于Arduino系列单片机代码都比较简单,所以本次主要记录舵机的原理。

一、学习目的
我的学习目的就是学习了解舵机的工作原理,并且通过蓝牙控制舵机的0-180°的转动。

二、模块介绍
这次用到的模块有两个:

1、蓝牙模块HC-05:之前已经记录过AT指令的使用和简单应用,这次就不多说了。相关的记录在下面两篇文章。

HC-05蓝牙模块的使用_KAIs32的博客-CSDN博客

STM32学习记录——使用蓝牙点亮LED_KAIs32的博客-CSDN博客

2、舵机: 舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。简单来说就是一个会转的东西,并且可以起到减速缓冲的作用。主要应用有智能车转向模块,智能开门等一些需要转动的项目。

原理方面:舵机是通过PWM设置占空比来控制转动角度的。

首先讲一下PWM如何控制占空比,有时候我们只需要3V电压,但只有5V的电源,这时可以通过控制一个周期时间内的供电时长来变相控制输入电压,比如某一个供电周期是10ms,我们只在前6ms供5V电压,在后4ms不供电(0V),此时可以由下面的公式算出来总供电为3V。

总供电压U=(6ms_5V+4ms_0V)/10ms=3V

我们使用舵机也是相同原理,舵机在不同的供电下转动的角度不同,所以我们只需要改变舵机在一个周期内的供电时长即可改变舵机转动的角度。

舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度伺服为例,那么对应的控制关系是这样的:

0.5ms———————0度;

1.0ms——————45度;

1.5ms——————90度;

2.0ms—————-135度;

2.5ms—————-180度;

即当占空比为0.5/20时,舵机转动0°,当占空比为1.0/20时,舵机转动45°,以此类推。

如何在代码中实现占空比的设置?我们用到的是DAC,即通过数字信号转化为模拟信号的方法,由于我这次用到的是arduino开发板,代码比较简单,所以只讲一下大概思路。
如果用STM32或者51系列单片机,就是通过使用单片机的定时器功能,定时一个1ms,再设置一个每过1ms自加一次的总量count为20(即舵机的周期20ms),然后设置一个比较量(假设为compare),比较值(compare)是一个变量,可以随意设置,例如将比较值设为1,用定时器功能使单片机在compare‹count时为高电平,由于count每过1ms自加一次,所以20ms内只有1ms的时间满足compare‹count(即20ms内,高电平只有1ms),占空比就是1.0/20,舵机转动45°。
如果我还是没有记录清楚不要紧,我以后会结合51或者STM32的代码进行详细记录。

我使用的是MG995这款舵机,如下图,它的工作电压是3-7.2V,所以一般接5V即可。



所有的舵机都有三根接线,分别是棕色,红色,黄色。

接线方法:
红————————————-VCC(5V)
棕色———————————GND
黄色———————————信号线(arduino板的pin9口)

三、代码记录
代码上已经详细注释过,也比较简单,就不做过多记录了。下次学习STM32的舵机时,会进行详细记录。

#include <Servo.h>            //加载文件库(舵机)
int pos = 0;                  //设置舵机的角度值
Servo myservo;                //创建舵机对象

#define led 13                //指示灯13
int state = 0;                //蓝牙信号变量
void setup() {
  pinMode(led, OUTPUT);       //设置pin13为输出模式
  digitalWrite(led, LOW);     //初始为低电平
  Serial.begin(9600);         //设置波特率
   myservo.attach(9, 500, 2500);          //修正脉冲宽度
}
void loop() {

  if(Serial.available() > 0)
  { 
    state = Serial.read();      //读取蓝牙信号
 }
  if (state == '0')              //发送信号
  {
  digitalWrite(led, LOW);
  Serial.println("关灯"); 
  myservo.write(0);            //舵机转动0度
  state = 0;
  }
  else if (state == '1')
  {
  digitalWrite(led, HIGH);
  Serial.println("开灯");
  myservo.write(90);           //舵机转动90度
  state = 0;
  } 
}