Arduino开发板实验三:舵机控制

经常玩NXT的朋友肯定对NXT的电机印象深刻,使用非常方便。转速,角度和方向都可以随意控制。

在计划制作小爱的时候,我也一直希望能找到这样的电机。查了一些资料,觉得比较容易控制的有舵机和步进电机。舵机的主要玩家是船模和航模的爱好者们。大海航行靠舵手,舵机就是用来控制舵角的,它的最大特点是可以方便的控制角度,它的限制是舵角一般不超过180度。步进电机就强多了,既可以控制角度,还可以连续旋转,它的问题是输出就是一个光轴,需要加工配套的零件才能使用,另外价格好像会更贵一点。

我计划用舵机来实现小爱的机械臂,最主要的考虑原因是舵机自带很多舵角之类的配件,比较容易安装,毕竟机械加工是制作过程中最麻烦的部分。另外,一般机械臂的关节转角也不需要大于180度,用舵机就足够了。下面是使用Arduino开发板控制舵机的一个小实验。

先抄一段说明:舵机,又称伺服马达,是一种具有闭环控制系统的机电结构。舵机主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由控制器发出PWM(脉冲宽度调制)信号给舵机,经电路板上的IC处理后计算出转动方向,再驱动无核心马达转动,透过减速齿轮将动力传至摆臂,同时由位置检测器(电位器)返回位置信号,判断是否已经到达设定位置,一般舵机只能旋转180度。

舵机结构图

舵机结构图

舵机有3根线,棕色为地,红色为电源正,橙色为信号线,但不同牌子的舵机,线的颜色可能不同,请大家注意。

舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的,标准PWM(脉冲宽度调制)信号的周期固定为20ms(50Hz),理论上脉宽分布应在1ms到2ms之间,但是,事实上脉宽可由0.5ms到2.5ms之间,脉宽和舵机的转角0°~180°相对应。有一点值得注意的地方,由于舵机牌子不同,对于同一信号,不同牌子的舵机旋转的角度也会有所不同。

舵机角度和占空比的关系

舵机角度和占空比的关系

 下面这个小实验的目标是用电位器控制舵机的角度,正好在前一个实验里,电位器都还没有拆掉。需要特别注意的是供电部分,舵机转动时电流会比较大,Arduino上的电源芯片可能会因过流保护到发热而损坏,电源需要接到外部供电,切不可使用USB供电。
舵机的棕色线接GND,红色线接VIN(我猜这个是直接连到外接电源的正极),黄色是数据线,接在PWM的7号管脚。电位器的连接稍微有点变换,因为管脚们施展不开,我把正极连在3.3V的接口上,这样模拟输入的范围就变成了0到660左右。前面说了,舵机分别用0.5ms到2.5ms之间的脉冲来对应0到180度左右的角度,我们可以用pulsewidth=(angle*11)+500这样的公式,把0到180度的转角映射到500到2480的脉冲时间。

接线图

接线图

下面看代码:

int readPin = 6;   //用来连接电位器
int servopin = 7;    //定义舵机接口数字接口7

void servopulse(int angle)//定义一个脉冲函数
{
  int pulsewidth=(angle*11)+500;  //将角度转化为500-2480的脉宽值
  digitalWrite(servopin,HIGH);    //将舵机接口电平至高
  delayMicroseconds(pulsewidth);  //延时脉宽值的微秒数
  digitalWrite(servopin,LOW);     //将舵机接口电平至低
  delayMicroseconds(20000-pulsewidth);
}

void setup()
{
   pinMode(servopin,OUTPUT);//设定舵机接口为输出接口
}

void loop()
{
  //读取电位器(传感器)的读数,接到3.3V,值范围从0到660左右
  int readValue = analogRead(readPin);
  //把值的范围映射到0到165左右
  int angle = readValue / 4;
  //发送50个脉冲
  for(int i=0;i<50;i++)
  {
     //引用脉冲函数
     servopulse(angle);
  }
}

实验结果:当旋转电位器的时候,舵机的角度随之改变。不过最终转角并没有达到180度,在某些范围内,电位器旋转时,舵机没有转动。网上舵机的说明也提到了这点,识别的角度范围是有限的。具体的有效角度范围,我还没有测量,等将来开始制作的时候再说。



对 “Arduino开发板实验三:舵机控制” 的 19 条 评论

  1. xin zhao 说:

    请问下,您目前有小爱的标准设计图纸么?

  2. dead_lee 说:

    你做小爱, 让你老婆做伊娃…

  3. 秦大少 说:

    拜年喽,恭喜发财!
    你很强啊!点GG以示支持了!

  4. Jim 说:

    貌似博主的程序会不停的负责脉冲调制
    可否采用Arduino自带的脉冲调制模块,也就是analogWrite(A_PIN, i);
    0 <= i <= 255
    这样你的loop程序可以用来做其它的
    你就有个多线程Arduino了

    • 感谢Jim的建议,我曾经也想过这个问题。
      但当时觉得analogWrite的脉冲跨度太大,没法精确控制,看下面的数据:
      一个PWM宽度是20ms=20,000μs
      analogWrite(A_PIN, i); //i=0~255
      i增大1的时候,脉冲宽度增加20,000/256=78μs

      而电机的控制脉冲是500μs~2480μs,对应180度,每度对应的脉冲宽度是11μs

      也就是说,analogWrite参数只有i=7~31左右有效,而且i增大1的时候,电机会增加7度左右,这样就不能精确控制了

      不过现在回头看来,这些号称精确到度的电机,其实误差非常大,所以用analogWrite控制应该也没有问题。:)

    • 更正一下,用这种方式是不行的
      舵机标准的脉冲周期是20ms,我查了下资料,arduino的pwm模拟输出脉冲周期只有2ms左右(490Hz)所以不能用这种方式来实现“多线程”
      如果想同时控制多个电机,只能通过编程的方式,类似于CPU的分片思想

  5. bobingwang 说:

    我想知道博主的舵机什么型号,在那里买的

  6. 你说呢 说:

    博主,你的程序我编译后为什么会出现
    error: expected unqualified-id before numeric constant 这个错误啊,程序一样,板子也一样,就是不明白。。

  7. 你说呢 说:

    请问博主,Arduino Mega上的Analog In和PWM上都有0-13管脚,这是引脚复用吗?

  8. 你说呢 说:

    再问一句,USB供电是+5V,板子上只连USB供电是不是就够了?

  9. 菜鸟 说:

    我想请教一下控制速度的程序,你这发送脉冲控制不了电机的转速啊?
    请教

发表评论

可以使用下列 XHTML 标签:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>