Arduino控制小型直流电机

电机俗称马达(Motor),有直流驱动的有交流驱动的,还有用汽油(航模车模)、液压驱动的马达(大型工业设备)。一般所指的电机是通过电生磁原理将电路中的电能转换成机械能的装置。本节仅讨论常见的小功率直流电机,对于工业上常用的异步交流电机的控制因涉及诸多电力电子技术细节超出本书细节,请有兴趣的读者可以参考电机学相关著作或教材。

DCmotor01

图所示为一直流电机(DC Motor)工作原理示意图。一对静止的磁极N和S之间,安装了一个可以绕中心轴旋转的漆包线线圈及其包裹的层叠硅钢片。硅钢片的目的是为了增强线圈产生的磁导,减少漏磁,而硅钢片叠加在一起相互又绝缘,是为了防止硅钢片内产生较大的涡流而损耗电能在发热上。中间转动的部分通常称为电枢,而线圈两端分别接在换向器的两个半圆铜片上,铜片之间相互绝缘,但分别接直流电源正负极。其中的磁场和产生的电枢转矩如何计算,为何需要设置换向器等问题在初中物理教科书中已有论述,在此不再赘述。

DCmotor02

需要说明的是,电机是较大功率的器件,他不能直接用Arduino的端口去驱动。一般来说,Arduino的每个引脚只能扇出(source)或者灌入(sink)最大40mA的电流,而所有端口的总电流不超过200mA(0.2A),而一般小电机也往往超过100mA。因此,只能采用放大驱动的方式,以晶体管(BJT)驱动电路为例,将端口连接至基极,就可以不到几mA的电流驱动流经电机的数百mA电流。下图晶体管集电极上连接的5V视直流电机的额定电压而定。一般按照直流电机上的铭牌来选择此路供电电源的电压和带负载能力,且最好将此路供电电源与Arduino的供电电源分开,以防止电机启停时对电源的干扰影响Arduino的正常工作。
针对不同电机(或者大负载),需要使用不同型号的晶体管放大,所以读取电机铭牌上的参数就显得尤为重要。下面是一款常见电机的说明书部分截取,资料来自Sparkfun官网,电机型号为Micro Metal Gearmotor 30:1 ROB-08911,从中我们可以获得相关信息,从而达到合理选用匹配的驱动器(三极管)。

DCmotor03
然后我们从常见的晶体管目录中选择,下面的较为常用的一些小功率晶体管型号,更多常用晶体管列表目录及其关键参数,请参考附录。

S9011 S9012 S9013 S9014 S9015 S9018 A1015 C1815
A42 A92 2N5401 2N5551 A733
C945 S8050 S8550 2N3906 2N3904
譬如在型号为S9013的晶体管的DataSheet说明中,我们看到如下表格数据
DCmotor04

可见S9013放大后连续正向电压和电流分别达到20V和500mA,完全能够满足额定电压和电流分别是6V和100mA的直流电机负载且有几倍的裕量,故可以满足要求。如果你手上的电机无法找到相应的规格书,你可以通过在电机工作时测量其电压和电流来进行简单的估计。
下面我们就来接线驱动小电机,不过我们不能忽略电机内的线圈,这意味着电机在断电一瞬间将产生巨大的自感电动势,其峰值很可能会超过晶体管所能承受的最大电压,所以必须减缓自感可能带来的不利因素。根据楞次定律,带有电感负载的通路端口的一瞬间,产生的自感有保持原有电流方向的趋势,所以我们可以在电机两旁并联一个二极管来释放因自感产生的尖峰电压。二极管选用较为常用的型号1N4001即可,关于二极管的参数选择过程与之前三极管的过程类同,请读者自行查阅Datasheet练习。

DCmotor05DCmotor07

 

DCmotor06

/* -----------------------------------------------------------
 * | Arduino小电机驱动电路示例程序 |
 * | 代码出处http://ardx.org/4001 |
 * | 连线时请注意参考右图引脚位置 |
 * -----------------------------------------------------------
 */

int motorPin = 9; //定义电机连接引脚

void setup()
{
  pinMode(motorPin, OUTPUT);
}

void loop()
{
  motorOnThenOff();
  //motorOnThenOffWithSpeed();
  //motorAcceleration();
}

//关闭电机
void motorOnThenOff(){
  int onTime = 2500; //调节开关占空比,也可使用PWM模拟输出方式
  int offTime = 1000;

  digitalWrite(motorPin, HIGH);
  delay(onTime);
  digitalWrite(motorPin, LOW);
  delay(offTime);
}

//电机以特定速度启停
void motorOnThenOffWithSpeed(){

  int onSpeed = 200;
  int onTime = 2500;

  int offSpeed = 50;
  int offTime = 1000;

  analogWrite(motorPin, onSpeed);
  delay(onTime);
  analogWrite(motorPin, offSpeed);
  delay(offTime);
}

//电机变速
void motorAcceleration(){
  int delayTime = 50; //调整速度的时间间隔

  //电机加速
  for(int i = 0; i < 256; i++){
    analogWrite(motorPin, i);
    delay(delayTime);
  }

  //电机减速
  for(int i = 255; i >= 0; i--){
    analogWrite(motorPin, i);
    delay(delayTime);
  }
}

由于一个晶体管驱动的电机只能单向驱动调速,有时候往往还需要电机能够正反转。如图所示,当Q1管和Q4管导通,Q2和Q3截止时,电流从电源正极经Q1从左至右流过直流电机,然后再经Q4回到电源负极,从而驱动直流电机沿一个方向旋转。反之,当Q2和Q3导通,Q1管和Q4管截止时,电流从直流电机右边流入,从而驱动直流电机沿另外一个方向旋转。这种驱动方式的电路和字母“H”非常相似,所以就往往被称为H桥驱动电路。这样类似的H桥组合驱动电路可以自行搭建,但要注意不能让Q1和Q2或者Q3和Q4同时导通,哪怕是较短的时间也不允许,因为这会使得电源正负极直接相连,可能损坏电源或晶体管。所以在执行使用H桥驱动直流电机电路前请务必仔细检查电路和程序,以防短路。

DCmotor08意法半导体公司(STMicroelectronics)生产的L293D和L298P两款芯片是市面上常见的H桥电机驱动集成芯片,它们的外形虽然看起来很不一样,但是只要掌握其中一种的原理和使用方法,再学习使用另外一个就不会太难。这两款芯片的细节参数请读者自行查阅AllDataSheet网站,但很多机器人或电子模块提供商已经将H桥做成了Arduino的专用模块甚至是盾牌(Sheild),配合专门的Arduino类库,使用起来会大为方便。本节以美国开源硬件商Adafruit制作的一款293 Motor Sheild为例来说明如何实现电机的调速与正反转。
DCmotor10

此款Motor Sheild采用了两个L293及一个74HC595芯片,可以同时控制4路直流电机或者两路步进电机和舵机。本节仅介绍此款Motor Sheild普通直流电机的使用,关于步进电机和舵机,请参考本书后续部分或Adafruit官网:
https://learn.adafruit.com/adafruit-motor-shield/using-dc-motors
DCmotor09

此款Motor Sheild使用前有专配类库,可以到GitHub网站下载
https://github.com/adafruit/Adafruit-Motor-Shield-library
需要注意的是,电机有四个连接口,如图所示,连接其中一个即可(下面的示例程序使用的是Motor #4)。此种连接端子用于连接电流较大的场合,故使用的是螺丝刀拧紧的方式,在把电线剥开一小段距离后,松开螺丝放入电线裸露端再拧紧螺丝即可。如果在使用过程中发现电机转向与你所需的方向相反,断开电源后将两根连接线交换位置后重新连接即可。

// Adafruit Motor shield library
// 此代码位于公共域

#include <AFMotor.h>
AF_DCMotor motor(4);

void setup() {
  Serial.begin(9600);
  Serial.println("Motor test!");
  //打开电机
  motor.setSpeed(200);
  motor.run(RELEASE);
}

void loop() {
  uint8_t i;
  Serial.print("tick");
  motor.run(FORWARD);
  for (i=0; i<255; i++) {
    motor.setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    motor.setSpeed(i);
    delay(10);
  }
  Serial.print("tock");
  motor.run(BACKWARD);
  for (i=0; i<255; i++) {
    motor.setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    motor.setSpeed(i);
    delay(10);
  }
  Serial.print("tech");
  motor.run(RELEASE);
  delay(1000);
}

上述示例程序实现的是电机简单的正反转加速减速,故不再添加注释。

打赏

Arduino控制小型直流电机》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注