分享

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

 共同成长888 2015-07-17

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

 

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

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

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

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

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

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

正确的L298N原理图

正确的L298N原理图

下面是对应的接线图:

乱七八糟的接线图

乱七八糟的接线图

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

步进电机驱动的时序图

步进电机驱动的时序图

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

代码如下:

  1. int LeftI1 = 28;     //连接电机驱动板的I1接口  
  2. int LeftI2 = 22;     //连接电机驱动板的I2接口  
  3. int LeftEA = 8;      //连接电机驱动板的EA接口  
  4. int RightI1 = 36;    //连接电机驱动板的I1接口  
  5. int RightI2 = 42;    //连接电机驱动板的I2接口  
  6. int RightEB = 6;     //连接电机驱动板的EB接口  
  7. int StepCount = 0;  
  8. int StepDelayTime=1500;  
  9.   
  10. void setup()  
  11. {  
  12.   pinMode(LeftI1, OUTPUT);     //I1和I2都是数字信号  
  13.   pinMode(LeftI2, OUTPUT);     //通过设置I1和I2来控制电机旋转方向  
  14.   pinMode(LeftEA, OUTPUT);     //按占空比方式输出的模拟信号  
  15.   pinMode(RightI1, OUTPUT);    //I1和I2都是数字信号  
  16.   pinMode(RightI2, OUTPUT);    //通过设置I1和I2来控制电机旋转方向  
  17.   pinMode(RightEB, OUTPUT);    //按占空比方式输出的模拟信号  
  18.   Serial.begin(9600);          //设置波特率  
  19. }  
  20. void ForwardInit()  
  21. {  
  22.   digitalWrite(LeftEA, HIGH);  
  23.   digitalWrite(RightEB,HIGH );  
  24.   digitalWrite(LeftI1, LOW);  
  25.   digitalWrite(LeftI2,HIGH );  
  26.   digitalWrite(RightI1,HIGH);  
  27.   digitalWrite(RightI2, HIGH);  
  28.   StepCount=0;  
  29. }  
  30. void BackwardInit()  
  31. {  
  32.   digitalWrite(LeftEA, HIGH);  
  33.   digitalWrite(RightEB,HIGH );  
  34.   digitalWrite(LeftI1, LOW);  
  35.   digitalWrite(LeftI2,LOW );  
  36.   digitalWrite(RightI1,LOW);  
  37.   digitalWrite(RightI2, HIGH);  
  38.   StepCount=0;  
  39. }  
  40. void ForwardOneStep()  
  41. {  
  42.   delayMicroseconds(StepDelayTime);  
  43.   switch(StepCount)  
  44.   {  
  45.     case 0:  
  46.       digitalWrite(RightI2,LOW);  
  47.       digitalWrite(LeftI1,HIGH);  
  48.       break;  
  49.     case 1:  
  50.       digitalWrite(RightI1,LOW);  
  51.       digitalWrite(RightI2,HIGH);  
  52.       break;  
  53.     case 2:  
  54.       digitalWrite(LeftI2,LOW);  
  55.       digitalWrite(RightI1,HIGH);  
  56.       break;  
  57.     case 3:  
  58.       digitalWrite(LeftI1,LOW);  
  59.       digitalWrite(LeftI2,HIGH);  
  60.       break;  
  61.   }  
  62.   StepCount=(StepCount + 1) % 4;  
  63. }  
  64.   
  65. void BackwardOneStep()  
  66. {  
  67.   delayMicroseconds(StepDelayTime);  
  68.   switch(StepCount)  
  69.   {  
  70.     case 0:  
  71.       digitalWrite(RightI2,LOW);  
  72.       digitalWrite(LeftI1,HIGH);  
  73.       break;  
  74.     case 1:  
  75.       digitalWrite(LeftI1,LOW);  
  76.       digitalWrite(LeftI2,HIGH);  
  77.       break;  
  78.     case 2:  
  79.       digitalWrite(LeftI2,LOW);  
  80.       digitalWrite(RightI1,HIGH);  
  81.       break;  
  82.     case 3:  
  83.       digitalWrite(RightI1,LOW);  
  84.       digitalWrite(RightI2,HIGH);  
  85.       break;  
  86.   }  
  87.   StepCount=(StepCount + 1) % 4;  
  88. }  
  89.   
  90. void loop()  
  91. {  
  92.   while(1)  
  93.   {  
  94.     ForwardInit();  
  95.     for(int i=0;i<200;i++)  
  96.     {  
  97.       ForwardOneStep();  
  98.     }  
  99.     delay(1000);  
  100.     BackwardInit();  
  101.     for(int i=0;i<200;i++)  
  102.     {  
  103.       BackwardOneStep();  
  104.     }  
  105.     delay(1000);  
  106.   }  
  107. }  

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

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

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

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

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

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多