极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 48269|回复: 13

请问Arduino如何同时驱动两个步进电机,分别走不同步数?(使用TB6560驱动)

[复制链接]
发表于 2013-4-23 21:41:16 | 显示全部楼层 |阅读模式
本帖最后由 JasmineL 于 2013-4-23 21:42 编辑

http://www.geek-workshop.com/for ... thread&tid=3266
我使用了了大连好人写的库函数,链接在上面
现在的主要问题是两个步进电机可以以不同速度运行,但是是同时开始同时停。
时间以运行时间长的步进电机为主,另一个步进电机走的比输入进去的步数多。

目前我能想到的解决办法是:在相同时间内,两个步进电机以一定比例的速度运行,以期盼能得到成比例的步数。
但又发现一个问题,如果比例较大,例如步数比为8:1时,一个电机转8圈的时候,另一个电机会转的比1圈多大概30度。
也就是说,速度成比例的时候,步数不完全成这个比例,转的数量少的时候,不明显,多了就不行了.....

求问大家,怎样才能同时驱动两个步进电机,且让他们走不同的步数...

我的代码如下:


  1. //1,2电机以不同速度转动相同步数

  2. #include <EasyStepper.h>
  3. #define STEP1_PIN 2
  4. #define STEP2_PIN 4
  5. #define DIR1_PIN 6
  6. #define DIR2_PIN 8
  7. #define EN1_PIN 12
  8. #define EN2_PIN 13//两个EN端悬空
  9. #define DIR1_PIN_INVERTED true
  10. #define DIR2_PIN_INVERTED true
  11. #define EN1_PIN_INVERTED true
  12. #define EN2_PIN_INVERTED true
  13. EasyStepper stepper1(STEP1_PIN, DIR1_PIN, EN1_PIN, DIR1_PIN_INVERTED, EN1_PIN_INVERTED);
  14. EasyStepper stepper2(STEP2_PIN, DIR2_PIN, EN2_PIN, DIR2_PIN_INVERTED, EN2_PIN_INVERTED);
  15. int times=0;
  16. int stepps=0;
  17. void setup()
  18. {
  19.   Serial.begin(9600);
  20.   stepper1.debugMode(false);
  21.   stepper1.startup();
  22.   stepper2.debugMode(false);
  23.   stepper2.startup();
  24. }
  25. void loop(){
  26.   if (Serial.available() > 0)
  27.   {
  28.       stepps=Serial.parseInt();
  29.       Serial.println(stepps);
  30.       stepper1.rotate(400.0,stepps/2);
  31.       stepper2.rotate(50.0,-stepps/2);
  32.   }
  33.     while(stepps!=0)
  34.     {
  35.      
  36.       if (times < 2)  
  37.       {
  38.         stepper1.run();
  39.         if (stepper1.isDone())
  40.         {      
  41.         // go back
  42.         stepper1.rotate(400.0,stepps/2);
  43.         Serial.println("Iner1"+times);
  44.          }
  45.         stepper2.run();
  46.         if (stepper2.isDone())
  47.         {      
  48.         // go back
  49.         stepper2.rotate(50.0,-stepps/2);
  50.         times++;
  51.         Serial.println("Iner2"+times);
  52.          }
  53.          if(times==2)
  54.           {
  55.             stepps=0;
  56.             times=0;
  57.           }
  58.        }  
  59.        Serial.println("Outer"+times);
  60. }}
复制代码
回复

使用道具 举报

发表于 2013-4-23 23:27:36 | 显示全部楼层
找出问题了

      if (times < 2)  
      {
        stepper1.run();
        if (stepper1.isDone())
        {      
        // go back
        stepper1.rotate(400.0,stepps/2);
        Serial.println("Iner1"+times);
         }
        stepper2.run();
        if (stepper2.isDone())
        {      
        // go back
        stepper2.rotate(50.0,-stepps/2);
        times++;
        Serial.println("Iner2"+times);
         }

         if(times==2)
          {
            stepps=0;
            times=0;
          }

看黑体代码部分,函数 .run是走一小步的意思, 每次step1走一小步,然后判断走完没有,然后step2再走一小步,然后再判断step2走完没有.

如果step1走完, 就继续走stepps/2步(对time和step2都没有影响), 只有等step2走完,time才加1.
只有time加到2, 才跳出函数,大家同时不走了.

所以导致的结果是,无论step1速度是多少,要走多少步,可是两个马达运行的时间都是以step2的设置为主

现在你知道应该怎么改你的程序了吧


回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 01:04:05 | 显示全部楼层
gjfhahaha 发表于 2013-4-23 23:27
找出问题了

      if (times < 2)  

谢谢高手~明白错在哪了,可还是不知道能怎么改....

因为run需要一个循环才能一直执行,两个步进电机如果想同时动,应该是要写在同一个循环里面的吧?

那循环的跳出方式用什么呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 01:42:52 | 显示全部楼层
gjfhahaha 发表于 2013-4-23 23:27
找出问题了

      if (times < 2)  

我是这么改的,还没经过测试,不知道对不对?

  1. //1,2电机以不同速度转动相同步数

  2. #include <EasyStepper.h>
  3. #define STEP1_PIN 2
  4. #define STEP2_PIN 4
  5. #define DIR1_PIN 6
  6. #define DIR2_PIN 8
  7. #define EN1_PIN 12
  8. #define EN2_PIN 13//两个EN端悬空
  9. #define DIR1_PIN_INVERTED true
  10. #define DIR2_PIN_INVERTED true
  11. #define EN1_PIN_INVERTED true
  12. #define EN2_PIN_INVERTED true
  13. EasyStepper stepper1(STEP1_PIN, DIR1_PIN, EN1_PIN, DIR1_PIN_INVERTED, EN1_PIN_INVERTED);
  14. EasyStepper stepper2(STEP2_PIN, DIR2_PIN, EN2_PIN, DIR2_PIN_INVERTED, EN2_PIN_INVERTED);
  15. int times=0;
  16. int stepps=0;
  17. void setup()
  18. {
  19.   Serial.begin(9600);
  20.   stepper1.debugMode(false);
  21.   stepper1.startup();
  22.   stepper2.debugMode(false);
  23.   stepper2.startup();
  24. }
  25. void loop(){
  26.   if (Serial.available() > 0)
  27.   {
  28.       stepps=Serial.parseInt();
  29.       Serial.println(stepps);
  30.       stepper1.rotate(400.0,stepps);
  31.       stepper2.rotate(400.0,-stepps);
  32.   }
  33.     while(stepps!=0)
  34.     {
  35.      
  36.       if (times < 1)  
  37.       {
  38.         if (stepper1.isDone()==false)
  39.         {      
  40.             stepper1.run();
  41.         }
  42.         if (stepper2.isDone()==false)
  43.         {      
  44.             stepper2.run();
  45.         }
  46.         if(stepper1.isDone()&&stepper2.isDone())
  47.         {
  48.           times=1   
  49.           stepps=0;
  50.           times=0;
  51.          
  52.          }  
  53.       }
  54.     }
  55. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2013-4-24 07:26:00 | 显示全部楼层
直线插补,我发过个帖CNC用的GCode_Interpreter,参考里面的插补方式
回复 支持 反对

使用道具 举报

发表于 2013-4-24 16:12:28 | 显示全部楼层
JasmineL 发表于 2013-4-24 01:42
我是这么改的,还没经过测试,不知道对不对?

times 这个变量貌似没用了吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 18:52:15 | 显示全部楼层
gjfhahaha 发表于 2013-4-24 16:12
times 这个变量貌似没用了吧

是这样的,我实际用的时候,是没有while(stepp!=0)这一个循环的,因为两个电机走的步数是经过计算后得出的,不是这个测试程序这么简单,写的时候疏忽了~~现在程序已改正了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-4-24 18:58:49 | 显示全部楼层
贴上个主程序里试验成功的函数吧,竖直平面内从现有位置移动到另一位置
  1. void xyMove(float dest_x,float dest_y)
  2. {
  3.   init_a=float(sqrt(pow(init_x,2)+pow(init_y,2)));
  4.   init_b=float(sqrt(pow(D-init_x,2)+pow(init_y,2)));
  5.   dest_a=float(sqrt(pow(dest_x,2)+pow(dest_y,2)));
  6.   dest_b=float(sqrt(pow(D-dest_x,2)+pow(dest_y,2)));

  7.   da=dest_a-init_a;
  8.   db=dest_b-init_b;
  9.   //a,b电极旋转的正方向不同,去了再看,某个的da需要*-1
  10.   //记得试一试两电机同转,但符号不同的时候,是否方向相反
  11.    
  12.   step_a=fabs(da*step_per_cm+0.5);
  13.    step_b=fabs(db*step_per_cm+0.5);//四舍五入
  14.    times=0;//电极需要初始化,以保证连续运动
  15.     if(step_a>=step_b)
  16.    {
  17.        speed_a=spd;
  18.        speed_b=(step_b*1.0/step_a)*spd;
  19.    }
  20.    else
  21.    {
  22.      speed_b=spd;
  23.      speed_a=(step_a*1.0/step_b)*spd;
  24.    }
  25.      if(da<0)
  26.      step_a=step_a*(-1);
  27.    if(db<0)
  28.      step_b=step_b*(-1);
  29.      
  30.    stepper1.rotate(speed_a,-step_a);
  31.    stepper2.rotate(speed_b,step_b);
  32.    
  33.    times=0;
  34.    while (times < 1)  
  35.    {
  36.         if (stepper1.isDone()==false)
  37.         {      
  38.             stepper1.run();
  39.         }
  40.         if (stepper2.isDone()==false)
  41.         {      
  42.             stepper2.run();
  43.         }
  44.         if(stepper1.isDone()&&stepper2.isDone())
  45.         {
  46.           times=1;
  47.         }
  48.     }
  49.    
  50.    init_x=dest_x;
  51.    init_y=dest_y;

  52. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2013-4-24 23:40:04 | 显示全部楼层
xmdesign 发表于 2013-4-24 07:26
直线插补,我发过个帖CNC用的GCode_Interpreter,参考里面的插补方式

您发的那个Gcode的程序我想知道怎么用,很感兴趣。
回复 支持 反对

使用道具 举报

发表于 2013-4-25 07:18:08 | 显示全部楼层
串口(Serial.begin(19200);)键入G代码
1:G90 绝对坐标方式(G91为增量坐标方式)
2:G1 F3000 运行速度(F1~X)
3:X10 Y20 Z50  移动目标坐标
4: M代码你发现其实可以你自己定义,比如打开或者关闭某个端口等
等等 G代码
回复 支持 反对

使用道具 举报

发表于 2013-4-25 11:48:29 | 显示全部楼层
xmdesign 发表于 2013-4-25 07:18
串口(Serial.begin(19200);)键入G代码
1:G90 绝对坐标方式(G91为增量坐标方式)
2:G1 F3000 运行速度 ...

嗯,我正在改造我的小铣床,现在是做了个手动/自动走刀,控制xy两轴,z轴改动量比较大我就没改,我想实现雕刻或者铣平面的的工作,一直在找gcode的解释程序,您给的那个程序我下来看了下,觉得不错。就是不太清楚怎么写程序。
回复 支持 反对

使用道具 举报

发表于 2014-8-6 13:37:57 | 显示全部楼层
回复做个笔记,有空研究下,谢谢楼主
回复 支持 反对

使用道具 举报

发表于 2016-3-1 11:06:51 | 显示全部楼层
英文不好,打开相应链接就糊涂了。库文件下载,安装以及历程理解一直困扰。请不吝赐教;详尽些更好。
回复 支持 反对

使用道具 举报

发表于 2018-8-20 13:39:23 | 显示全部楼层
楼主可以发份源码吗!对我来说很有参考价值!([email protected]

顺便问一下arduino最多可以实现同时控制多少个步进马达??
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-2 06:01 , Processed in 0.046727 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表