Posts Tagged ‘步进电机’

Arduino开发板实验四:步进电机控制

上周总算做成了点事,其实很简单,就是用Arduino实现了步进电机的正转和反转。因为总是很忙,所以拖到现在才有时间补上攻略。感慨一下,IT民工真辛苦啊,有位同事的昵称已经改成 “还是古代好,切掉小JJ就可以当公务员了”。 好吧,祝这位朋友心想事成,我还是坚持当民工好了 :)

在步进电机实验前,从网上找到了一个关于步进电机驱动的文档,使用的是L298N的驱动芯片。这个文档里面有些错误,导致我浪费了大量时间。也许不同的电机和芯片版本也许有区别吧,请大家慎重使用。先借用一下原理图:

L298N步进电机驱动芯片原理图

错误的L298N步进电机驱动芯片原理图

其中IN1~IN4以及ENA,ENB在之前的一篇关于直流电机驱动中有介绍过,分别对应输入的六个管脚。这个图里有两处错误,首先可以看到有两个ENA,其中一个应该是ENB;另外这两个EN都是接地的,但是经我实验看来,应该接+5V的电压才对。

所以正确的原理图应该是这样的:

正确的L298N原理图

正确的L298N原理图

下面是对应的接线图:

乱七八糟的接线图

乱七八糟的接线图

接线之后按照说明书里的时序图写了一段程序,呼呼,一次就通过了电机的正转实验。可是在企图实现反转的时候,总是不成功。在焦头烂额之后,终于开始怀疑文档是否正确。事实证明,大家做任何事情都要相信伟大的党而不是万恶的“文档”,下面是错误的反转时序图和经我验证可行的时序图:

步进电机驱动的时序图

步进电机驱动的时序图

基于以上时序图,我写了一段代码,让步进电机实现下面的动作:
正转一圈 -> 暂停1秒钟 -> 反转一圈 -> 暂停一秒钟 ->循环

代码如下:

int LeftI1 = 28;     //连接电机驱动板的I1接口
int LeftI2 = 22;     //连接电机驱动板的I2接口
int LeftEA = 8;      //连接电机驱动板的EA接口
int RightI1 = 36;    //连接电机驱动板的I1接口
int RightI2 = 42;    //连接电机驱动板的I2接口
int RightEB = 6;     //连接电机驱动板的EB接口
int StepCount = 0;
int StepDelayTime=1500;

void setup()
{
  pinMode(LeftI1, OUTPUT);     //I1和I2都是数字信号
  pinMode(LeftI2, OUTPUT);     //通过设置I1和I2来控制电机旋转方向
  pinMode(LeftEA, OUTPUT);     //按占空比方式输出的模拟信号
  pinMode(RightI1, OUTPUT);    //I1和I2都是数字信号
  pinMode(RightI2, OUTPUT);    //通过设置I1和I2来控制电机旋转方向
  pinMode(RightEB, OUTPUT);    //按占空比方式输出的模拟信号
  Serial.begin(9600);          //设置波特率
}
void ForwardInit()
{
  digitalWrite(LeftEA, HIGH);
  digitalWrite(RightEB,HIGH );
  digitalWrite(LeftI1, LOW);
  digitalWrite(LeftI2,HIGH );
  digitalWrite(RightI1,HIGH);
  digitalWrite(RightI2, HIGH);
  StepCount=0;
}
void BackwardInit()
{
  digitalWrite(LeftEA, HIGH);
  digitalWrite(RightEB,HIGH );
  digitalWrite(LeftI1, LOW);
  digitalWrite(LeftI2,LOW );
  digitalWrite(RightI1,LOW);
  digitalWrite(RightI2, HIGH);
  StepCount=0;
}
void ForwardOneStep()
{
  delayMicroseconds(StepDelayTime);
  switch(StepCount)
  {
    case 0:
      digitalWrite(RightI2,LOW);
      digitalWrite(LeftI1,HIGH);
      break;
    case 1:
      digitalWrite(RightI1,LOW);
      digitalWrite(RightI2,HIGH);
      break;
    case 2:
      digitalWrite(LeftI2,LOW);
      digitalWrite(RightI1,HIGH);
      break;
    case 3:
      digitalWrite(LeftI1,LOW);
      digitalWrite(LeftI2,HIGH);
      break;
  }
  StepCount=(StepCount + 1) % 4;
}

void BackwardOneStep()
{
  delayMicroseconds(StepDelayTime);
  switch(StepCount)
  {
    case 0:
      digitalWrite(RightI2,LOW);
      digitalWrite(LeftI1,HIGH);
      break;
    case 1:
      digitalWrite(LeftI1,LOW);
      digitalWrite(LeftI2,HIGH);
      break;
    case 2:
      digitalWrite(LeftI2,LOW);
      digitalWrite(RightI1,HIGH);
      break;
    case 3:
      digitalWrite(RightI1,LOW);
      digitalWrite(RightI2,HIGH);
      break;
  }
  StepCount=(StepCount + 1) % 4;
}

void loop()
{
  while(1)
  {
    ForwardInit();
    for(int i=0;i<200;i++)
    {
      ForwardOneStep();
    }
    delay(1000);
    BackwardInit();
    for(int i=0;i<200;i++)
    {
      BackwardOneStep();
    }
    delay(1000);
  }
}

除了实现了动作之外,我还搭车实验了下面几件事情:

1,步进电机的转角相当精确,我捆了根电线当指针,反复转了几百圈之后,指针的位置几乎没有变化

2,扭矩还挺大,我选用的是标称扭矩是3.4Kg.cm的步进电机,用铅酸蓄电池供电,旋转时我用爪子完全不能把它捏住(NXT的电机貌似没有这么强劲)。

3,经我测试,每个脉冲之间的间距最好大于1500μs(1.5ms),如果间距太小的话,就会出现失步的情况。

思考问题:基本上来说,每个步进电机都需要一个驱动板(L298N)和一个控制板(Arduino或其它单片机)。如果需要控制多个电机的话(小爱也许会有20多个关节),买这么多板子成本就太高了。实际上,每个脉冲间距之间有1500微秒的空闲时间,对CPU来说简直是漫漫长夜。所以我觉得可以用类似于操作系统多任务的思想来生成时序,充分利用脉冲间距之间的剩余价值,这样就可以只用一块Arduino实验板来控制多个电机了。

呵呵,又想多了,等下周有空再试试吧!

神奇的电机们

前几天有几个小朋友给我发邮件,说是打算自己动手设计电路和机械结构来制作魔方机器人,其中提到了用步进电机来旋转魔方。

说来惭愧,电子电路和嵌入式我还真是门外汉,连步进电机都没玩过。看他们如火如荼的进展着,我也心痒痒的,迅速在淘宝上订了一个步进电机。这几天查了点资料,总算对步进电机有了一点了解。

想起给小爱选电机的时候,发现电机的种类真不少,常见的有:直流电机,舵机,步进电机和伺服电机。这是按原理分类的,如果考虑一些附件的话,又有减速电机,直线电机等等,看的我眼花缭乱。这里稍微总结一下,以供跟我一样的初学者参考。

直流电机
小时候经常拆东西的破坏大王们,最熟悉的就是这种电机了,刮胡刀玩具车里都有这个。只有两根线,通过电压来调节转速,把电池反过来接,电机就反向旋转。破坏力更强的一定也知道,里面一般会有电刷和几个转子,还有两块永磁铁,原理就不介绍了。
优点:控制简单,还没学物理的时候就知道怎么玩了
缺点:不能精确的控制旋转角度和速度

舵机
现在终于明白这种电机为什么叫舵机了。大海航行靠舵手,舵机一般用来控制角度,所以经常用来航模和船模上。这种电机内部其实也是普通的直流电机,区别在于加上了一个小电路,用一个电位器(模拟型舵机)来读取电机的当前转角,并不断的调节直流电机两端的电压来让这个转角维持在设定值。一般来说,舵机都会带一个齿轮箱,用来提高精度和扭力。
优点:可以精确控制角度
缺点:角度范围有限,一般小于180度,不能连续旋转,不能设置速度

步进电机
从名字就可以看出来,步进电机是“一步一步”旋转的。例如我买的电机步距角是1.8度,按照指定的时序发送脉冲信号,每收到一个脉冲电机就旋转1.8度。你想让电机转5度?抱歉,这是不行滴,换一个不同步距角的型号吧。另外,通过控制发脉冲的频率,就可以控制步进电机的转速了。哇,角度和速度都可以控制,这下貌似完美了。先别激动,因为步进电机是一个开环系统(简单的说就是无反馈),很可能会发生失步或者越步的现象。当脉冲发的太快或者负载太大的时候,电机还没反应过来,下一个脉冲就到了,这就失步了;当电机带动的转子惯性很大时,脉冲停止后,转子可能还会继续转动,这就是越步了。
优点:角度和速度都可以控制
缺点:失步或越步

伺服电机
完美的电机终于出现了,给步进电机加上伺服电路,检测它是否转到了指定的角度,这就是伺服电机了。一般是靠电机屁股上的一种编码器来读取角度,这玩意儿据说非常精确,当然,这个东西如果价格再便宜点就真的完美了。
优点:角度和速度都可以精确控制
缺点:价格高,控制最复杂
值得一提的是,乐高的NXT系列,用的就是伺服电机,加上开发API接口后,控制非常方便!

对于以上几种电机,如果想用程序控制的话,都需要加上控制器和驱动器。其中控制器一般可以用单片机,相当于发送时序指令给电机。对于小功率的电机,其实用控制器就可以带动了。但是对于功率较大的电机,就需要加上驱动器。驱动器可以简单理解为功率放大器,接受控制器的信号,然后输出大电流给电机。

另外两个概念:减速电机是通过齿轮箱或蜗杆给电机减速,用来提高扭矩;直线电机是通过丝杠,把电机的转动变成丝杠的平动,一般用来做推杆。

倒腾了一晚上,终于用我的Arduino开发板实现步进电机正转和反转了。之前在小爱成长记里写过直流电机舵机的控制,周末整理一下,把步进电机的控制也加上。至于伺服电机,等以后用的上的时候再研究吧 :)