带好盈程序的电子调速器控制

最近制作四轴飞行器陷入困境,用手抓住它左右摇晃,能够感受到螺旋桨明显的阻力。但是PID参数调节的结果,要么就是飞行器剧烈摇摆失控,要么就是起飞后向一侧斜飞,很难达到一个较为稳定的状态。

应朋友们的建议,先陆陆续续写一些攻略和步骤。一来可以相当于做好笔记,二来也可以请大家帮忙查找原因,出谋划策。

前面几篇提到了目前控制电机的一些问题,正好在这里介绍下我控制电机的方式。

电机

首先,航模的电机一般都是无刷电机,这种高速的无刷电机不像直流电机那样,接上一定电压就可以旋转,一般需要在多个电源线中输入周期性的交流电。例如我买的电机就是下面这样的:

无刷电机

无刷电机

它有三根输入电源线,如果用单片机直接输出交变的电信号给它,因为单片机输出功率太低,是转不动的。
如果把单片机的输出经过电流放大电路,例如L298N,事实上很多步进电机就是这样控制的。它的问题在于一个单片机只能控制几个电机,并且很难再做其他的计算了。

电调

由于上面的原因,我们必须采用专门控制电机转速的设备,就叫做电调(全称电子调速器,英文electronic speed controller ,简称ESC)。它的作用就是接受单片机的PWM指令,并且生成成无刷电机需要的高频交流电。

电调

电调

大家可以看到电调有很多线,其中两根粗线连接的是电源的正负极;三根输出线分别连电机的三根输入线(如果需要电机反转,任意对换两根接线即可);另外还有三根细线,分别是单片机接地,5V输出电源和PWM信号线。

 根据航模标准,PWM信号线的频率应该是50Hz,对应的每个周期总时长是20ms。经过我的实测,基本上超过55Hz以后就不转了。
在这个20ms的周期中,高电平的持续时间应该在0.92ms到2.120ms之间,分别对应电机的最低转速和最高转速。

我曾经在想为什么只给转速控制留了这么小的PWM范围?如果是按Arduino系统PWM输出的话,用0~255来输出20ms之间的PWM值,有效控制转速的值范围大约只有pwm=(20~40)之间。后来大概明白了,这是为了给单片机节约宝贵的CPU资源,这样才可以在剩余的18ms中处理其他事务。

好盈程序

看电调的说明书,它有很多功能。比如设置电池的特性,设置刹车特性,设置最大转速等等。这些功能都可以通过遥控器进行设置,其中大部分功能我们使用默认值就可以,只有初始化一项是必须做的。
具体的设置方法是,把油门推到最大(2.12ms),这时候电调就会滴滴几声提醒你进入设置模式,然后就可以把油门迅速拉到最低(0.92ms)保持一会儿之后,电调就可以初始化成功了。

新手可能会有和我一样的疑问:把油门推到最大的时候,会不会电机突然暴走起来?
所以这里需要强调的是,电调的使用一定要按照说明书操作。单片机通电的时候,需要立刻给电调输出最低油门的PWM值(0.92ms),经过我的实验,0.85或0.95也没有太大关系。再低的话就会滴滴滴的报警,告诉你没有初始化成功;再高的话(0.95到2.1之间)只会有一声警报,但是无法正常转动;再再高到最高油门值(2.12ms)的时候,就会提醒你进入设置模式。

这样做是安全的,如果你不慎把遥控器留到了高位,这时候给电机通电,不至于突然上升到非常高的转速。前几天我企图修改PWM的时候,发生了一次这样的失误,手机控制的参数一下子升到最大,螺旋桨的风力大到手几乎抓不住,真是吓的屁滚尿流……

初始化和调速

之前有提到过用电脑通过串口通信控制电机,这里也是类似,在PC上写一段小程序,可以输出0~200之间的一个整数到Arduino。
在Arduino上,分别把0对应到0.9ms的高电平;200对应到2.1ms的高电平。

void loop()
{
  long t0 = micros(); //记录进入loop的时间
  while(Serial.available()) {
    // 这里是获取控制指令
    pushData(Serial.read());
  }
  //ctrlPower从串口读取,0~200分别对应高电平脉宽0.9ms~2.1ms
  double len = 1000 * (0.9 + ctrlPower * (2.1 - 0.9) / 200.0));
  // 输出高电平
  for(int i = 0; i < 4; i++) digitalWrite(motorPins[i], HIGH);
  // 延时len毫秒
  delayMicroseconds(len);
  // 输出低电平
  for(int i = 0; i < 4; i++) digitalWrite(motorPins[i], LOW);
  // 等待一段时间,形成20ms的周期
  delayMicroseconds(t0 + 20000 - micros());
}

其中ctrlPower就是从PC端读取的那个控制值。新电机和电调买回来,把4个装到一起,然后从这个程序统一进行初始化和控制转速。强烈建议第一次玩电机的朋友,先不要装上螺旋桨,应该等调试胸有成竹之后再安装。 :)



对 “带好盈程序的电子调速器控制” 的 24 条 评论

  1. boboking 说:

    飞控板做减震处理,拿橡皮筋勾着,试试?

  2. bohan 说:

    你可以试试bangbang控制,一般这种程度的模型比较适合这样控制。PID反而不容易调的很稳定,经常可能过调,

  3. jacob1990 说:

    动力哥,你文中提到的“这些功能都可以通过遥控器进行设置,其中大部分功能我们使用默认值就可以,只有初始化一项是必须做的。”
    指的是什么控制器?另外能在Ardunio上写CODE代替控制器来初始化电调吗?
    也就是能用ardunio来模拟你文中的“把油门推到最大(2.12ms),这时候电调就会滴滴几声提醒你进入设置模式,然后就可以把油门迅速拉到最低(0.92ms)保持一会儿之后,电调就可以初始化成功了”

    • 对,就是可以从Arduino来把油门推倒最大。我的意思是,你最终只要能输出高电平在0.92~2.12ms之间的PWM就可以 :)

      • jacob1990 说:

        不好意思,动力哥,打扰了,只是项目在快结束的时候出现了问题,很着急。怕挂了,毕不了业,所以才想加你QQ的。
        我用示波器测了下,我用PPM控制也是测出来无刷电机确实是在0.9ms的时候启动,这是正常的电机启动。但是我的现在的问题是我其中一个电机现在要1.1ms才启动(因为要调试PID的参数,所以我经常把它加到2.12ms)我看了说明书,和查了一些网上的资料,猜想是不是该电机进入了安全模式?或者这种0.9到2.12的这种1.22ms区间会移动?比如移到1.1到2.32ms?
        这个问题现在很纠结。

        • 这个不用纠结啦,电机的特性不是那么线性的,虽然期望的是0.9ms时启动,但是很多都要到推后的。我的电机大概在1.2ms左右陆陆续续起来,应该没关系的 :)
          有个说法是电调会把启动时的脉宽当作最低速度,但是我实验看不是这样,启动脉宽不对的话,直接就报警了

          • jacob1990 说:

            可是,我说的两种启动时间(0.9ms和1.1ms)在同样的PID参数效果确不一样。也就是说,我在0.9ms下能达到理想响应曲线的P,I,D在1.1ms
            下就失效了。而且过了一段时间后1.1ms启动的电机又会返回到0.9ms启动。这可怎么办?而且我发现COM口在第二次运行的开始会出现一些乱码,我想这是不是因为ESC有记忆功能?

          • jacob1990 同学,从网上的文档看,ESC确实有记忆功能。
            我印象中,它会把上电时的脉宽作为最低转速点(当然脉宽不能离0.9ms太远)。

            具体的文章可以看这篇:
            http://zhidao.baidu.com/question/247364848.html
            注意看这句话:
            ———————————-
            所以,你要做的是,把脉宽放在1ms,然后给电调上电,把0速度对应的脉宽值降下来,然后5us一个步进量调速度,最大加到2ms就不要再提高了。
            ———————————-
            也就是说,电调不是总把0.9ms作为最低转速的,而是看上电时的脉宽。
            假如你的单片机上电和电调上电是同时的,那么单片机在开始的时候可能会做一些操作,例如初始化传感器等等,可能就会造成电调的初始脉宽稍大

            今天有点生病,等会儿准备坚持做个小实验就去睡了 :)

  4. jacob1990 说:

    另外,动力哥,因为我的毕设截止时间快到,还有些地方没想通,请问能不能加个QQ,这样子,能方便很多,我保证绝不会没事骚扰您。
    QQ:522040987

    • SSS_SXS 说:

      兄弟,这是老哥哥们摆弄爱好的地方,意义在于实现自己的梦想,毕业设计主要是对自己学校所学东西的一个综合运用,照抄或者拿来主义欠妥阿,纯属友情提示,再有啥想法咱们私下聊,别坏了动力哥的宝地。QQ:227704

      • 多谢SSS_SXS兄弟帮我圆了场,现在不是学生时代了,上班的时候肯定不能用QQ,不然太影响工作。
        晚上回家就一点儿时间,做点事情,回复下评论就该睡觉了。

  5. r 说:

    arduino飞控可以参考下mwc嘛,可以在已有基础上开发更高级功能,没必要重新造轮子啊

  6. SSS_SXS 说:

    动力兄,还是围绕你不能试飞成功的话题考虑,我始终还是觉得PID公式运用上出了问题,侧飞的话,是不是因为在改参数的时候,飞行器就开始侧倾了?按照理论解释,因为你是乘上这个参数做积分的,而不是和这参数一起做积分的,所以修改瞬间会有一阵很大干扰在(所谓”风”),建议把PID代码发出来看一下

  7. js200300953 说:

    后来大概明白了,这是为了给单片机节约宝贵的CPU资源,这样才可以在剩余的18ms中处理其他事务。

    其实Arduino的PWM应该可以异步的。

  8. Junzhen 说:

    大哥,我有个问题,我DIY的是四个螺旋桨的飞行器,这样就有4个ESC,就是要4个PWM值。
    我的问题是,如果是这样我这接把这4个ESC接到MicroC上的PWM OUTPUT就可以了,还是一定要接个PPM ENCODER进行转化。
    如果是后者,,,我真不知道接线是如何的。

  9. Junzhen 说:

    我发现你的下一章就是更新。。。多路啊,,,期待

  10. xunmengdeganjue 说:

    这个电调可以自己做吧,芯片BTS7960,重量可以再轻点,呵呵

    • 多谢建议,请教一个非常外行的问题:比如我大概知道一个功能方面的需求,该去什么地方找合适的芯片和型号呢?
      比如这个电调,我只想到去百度搜场效应管,明显是不得要领,而你是怎么能知道该用BTS7960呢?

  11. 小小 说:

    动力哥,请教个问题,avr 2560虽然有11路pwm,想做8路的ppm遥控器。但是貌似频率不容易改到50hz啊,255对应20ms也有点粗糙啊。麻烦动力哥详细介绍下配置的细节。用增强单片机定时器模拟倒是还可以,就是有点抖。

  12. 冷树 说:

    楼主你好,我想用电脑串口和安卓串口控制无刷电机或者电调,请问有没有什么方法?我扣扣771839939,跪求解答

    • 这个貌似有点儿难,串口通信协议是固定的,不能随意的发送01数据。
      不过你也许可以用一个usb小板子接在手机上,通过这个小板子跟设备通信。具体的细节我就不清楚了

  13. 依然饭特稀 说:

    pushData();
    motorPins[i]
    micros()
    你好,我刚刚入手,arduino还有无刷电机,正在尝试,看到了你的代码,我想问下上面这三个函数的源码是啥?多谢了,或者你能把,setup()函数,以及全部的代码贴出来吗?谢谢了

发表评论

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