极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12347|回复: 1

竖直平面作图--两个步进电机的使用

[复制链接]
发表于 2014-12-9 23:07:45 | 显示全部楼层 |阅读模式
时隔一年半重回论坛,想到原来在这里遇到问题时大神们热情的相助,觉得应该回报社会一下~

这是信息产品设计的大作业,利用两个步进电机和同步带,带动画笔在竖直平面完成作图
经过测试,基本实现功能,但有些抖动,以后可能也没机会完善了,发到论坛上来纪念一下吧

PS:一年半以前的作业,最近整理资料,发现了这个,自己留着也没用,放上来供大家完善


没获奖的兔斯基
视频地址:
http://v.youku.com/v_show/id_XNTU1ODc5MDQw.html



以及获了奖的兔斯基
视频地址:
http://v.youku.com/v_show/id_XNTU1ODI4ODky.html




使用了的库函数:
http://www.geek-workshop.com/for ... thread&tid=3266
我使用了了大连好人写的库函数,链接在上面,解决了两个步进电机分别在同一时间走不同步的问题
如果想立即找到解决方案,在下面的链接的答案中找,我已放过。
http://www.geek-workshop.com/forum.php?mod=viewthread&tid=4319&page=2#pid70901


这是以前写的一个像素游戏--雷电复古版的前传~,用红外遥控器控制,16*16LED点阵实现
有意戳进:
http://www.geek-workshop.com/thread-4335-1-1.html


竖直画图装置代码贴的如下:
  1. //垂直画图装置
  2. //by:梁YJ 刘DY
  3. //点坐标移动版本

  4. //变量设定
  5. //步进电机部分
  6. #include <EasyStepper.h>
  7. #define STEP1_PIN 2
  8. #define STEP2_PIN 4
  9. #define DIR1_PIN 6
  10. #define DIR2_PIN 8
  11. #define EN1_PIN 12
  12. #define EN2_PIN 13//两个EN端悬空
  13. #define DIR1_PIN_INVERTED true
  14. #define DIR2_PIN_INVERTED true
  15. #define EN1_PIN_INVERTED true
  16. #define EN2_PIN_INVERTED true
  17. EasyStepper stepper1(STEP1_PIN, DIR1_PIN, EN1_PIN, DIR1_PIN_INVERTED, EN1_PIN_INVERTED);
  18. EasyStepper stepper2(STEP2_PIN, DIR2_PIN, EN2_PIN, DIR2_PIN_INVERTED, EN2_PIN_INVERTED);
  19. int times=0;//帮助电机动,每次开始需要初始化

  20. //坐标相关

  21. #define D 130                         //两个电机间的距离(cm)
  22. #define base_x D/2                //定位点的坐标,为等边三角形
  23. #define base_y 0.866*D       

  24. float init_a,init_b,init_x,init_y;//起始点
  25. float dest_a,dest_b,dest_x,dest_y;//目标点
  26. float da,db;//a,b的增减值
  27. int step_a=0,step_b=0;//步进电机走的步数
  28. float speed_a,speed_b;//步进电机走的速度
  29. #define step_per_cm 2000/50//每cm需要走多少步
  30. #define spd 600//步进电机最大速度

  31. //坐标的单位是cm,允许小数
  32. //得奖图片
  33. int dpaint_x[128]=
  34. { 3027,3713,2755,2660,2767,3015,3630,3725,3878,4091,
  35.   3796,3630,3666,3807,4221,4742,5238,5451,5640,5770,
  36.   5889,5841,5640,5451,5699,6019,6279,6456,6302,5865,
  37.   6078,6042,5900,5652,5285,5002,4824,4813,5439,5037,
  38.   5215,5652,5711,5640,5451,5167,5037,4765,4008,4327,
  39.   4623,5274,4931,4801,4907,4990,4919,3535,3394,3535,
  40.   3666,3547,2353,2459,2578,2471,2365,1076,934,1064,
  41.   1159,1064,402,568,709,532,627,414,709,579,461,639,
  42.   733,1206,1005,946,780,780,1171,1171,970,946,733,958,
  43.   1182,1313,1514,1514,1514,1514,1265,1584,1750,1750,
  44.   2034,1845,1703,1845,1608,1277,2081,1667,1573,1407,
  45.   1253,1655,1797,2081,2199,2909,2542,2542,2223,2814,
  46.   2660,2873,2128,2968};//x坐标值
  47.   
  48. int dpaint_y[128]=
  49. { 4193,3385,2506,2340,2245,2316,2910,3088,3266,3385,
  50.   3160,2827,2447,2079,1805,1663,1758,1853,1615,1556,
  51.   1604,1782,2007,1877,2090,1853,1722,1841,2043,2269,
  52.   2637,3041,3361,3599,3373,3183,3207,3361,3718,3742,
  53.   3599,3575,3777,4050,4098,4074,3932,4205,2174,2304,
  54.   2387,2768,380,736,1117,736,380,950,1283,1675,1283,
  55.   926,1687,2209,1710,1330,1675,1128,1437,1900,1449,
  56.   1128,570,238,487,451,582,653,665,926,808,1033,273,
  57.   273,285,439,843,439,439,843,535,867,1033,855,1057,
  58.   297,439,214,713,523,606,463,226,333,344,582,428,606,
  59.   665,772,772,677,915,998,1021,760,950,1033,404,404,
  60.   202,630,962,962,748,1057,653,653}; //y坐标值
  61.   
  62. int dpaint_bi[128]=
  63. { 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  64.    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,1,2,1,
  65.    2,1,2,0,0,0,1,2,0,0,0,1,2,0,0,0,1,2,0,0,0,1,2,0,1,
  66.    2,1,2,0,0,0,1,2,0,0,1,2,0,0,1,2,0,1,2,1,2,0,0,0,0,
  67.    1,2,0,0,0,0,0,0,1,2,1,2,0,0,1,2,0,1,2,1,2,0,0,0,0,
  68.    1,2,1 };//控制抬笔和落笔
  69.            //2代表落笔,0代表示维持现状,1代表抬笔
  70.   
  71.   //没得奖图片
  72.   int npaint_x[115]=
  73.   { 4103,4257,4801,4813,3914,3938,4801,5250,5049,5096,
  74.     5605,5593,5073,3961,3914,4056,3997,4115,4044,3027,
  75.     3204,3654,3985,3630,3382,3299,3488,3725,4008,3938,
  76.     4056,4221,4257,4446,4481,4635,4836,4765,5215,5664,
  77.     5877,5877,5427,5333,4505,4446,5380,5345,4623,4576,
  78.     4883,5120,5711,5238,5794,5309,6314,5865,6492,5640,
  79.     3571,2850,3441,497,627,473,603,544,485,662,828,828,
  80.     1088,1123,1242,1242,698,1206,650,1395,1395,2081,
  81.     2081,1395,1726,1726,2235,2353,2199,2400,2412,2412,
  82.     2684,2519,2613,2968,2779,2530,2578,2779,2188,3015,
  83.     2601,2471,2223,2590,2802,3003,3441,3441,3417,3417,
  84.     3512,3512,3429};//x坐标值
  85.   
  86. int npaint_y[115]=
  87. { 1413,1271,1651,1924,1912,1615,1627,1508,1687,1912,
  88.   1924,1687,1699,1936,2364,1948,2364,1960,2387,4157,
  89.   3504,2922,3100,2910,2589,2138,1651,1366,1223,535,
  90.   404,463,1117,1128,594,392,499,1212,1318,1604,2079,
  91.   2601,2981,2114,2126,3433,3385,3243,3266,3409,3433,
  92.   4122, 226,701,986,1390,226,630,1045,1627,2839,3504,
  93.   3171,535,653,760,891,998,1318,808,713,594,594,784,
  94.   796,1342,903,903,1330,998,713,713,998,1010,523,1330,
  95.   582,701,903,831,535,998,535,784,630,630,891,962,
  96.   713,891,1069,1069,962,1235,1318,1069,1271,1318,582,
  97.   1057,1140,1247,1247,1140,1140}; //x坐标值
  98.   
  99. int npaint_bi[115]=
  100. { 2,0,0,0,0,0,1,2,0,0,0,0,1,2,1,2,1,2,1,2,0,1,2,0,
  101.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  102.   0,0,0,1, 2,0,0,1,2,0,0,1,2,0,1,2,1,2,1,2,1,2,0,
  103.   0,0,0,1,2,0,0,1,2,0,0,0,1,2,1,2,1,2,1,2,1,2,1,2,
  104.   0,0,1,2,1,2,1,2,0,1,2,0,1,2,1,2,0,0,0,1};
  105.            //控制抬笔和落笔
  106.            //2代表落笔,0代表示维持现状,1代表抬笔


  107. //自定义函数
  108. void xyMove(float dest_x,float dest_y);

  109. //舵机部分
  110. #include <Servo.h>
  111. Servo dj;
  112. int angle_ding=30;//舵机顶出时角度,抬笔
  113. int angle_shou=180;//舵机收回时角度,落笔

  114. //前一组信号接收用
  115. int c,d;

  116. void setup()
  117. {
  118.       Serial.begin(9600);
  119.       //步进电机部分初始化
  120.       stepper1.debugMode(false);
  121.       stepper1.startup();
  122.       stepper2.debugMode(false);
  123.       stepper2.startup();
  124.       init_x=base_x;
  125.       init_y=base_y;
  126.       
  127.       //舵机部分初始化
  128.       dj.attach(9);
  129.       dj.write(angle_ding);
  130.       
  131.       //前一组信号接收端口,有三种状态
  132.       //悬空,10号HIGH,和10,11号口均为HIGH
  133.       pinMode(10,INPUT);
  134.       pinMode(11,INPUT);
  135. }
  136. void loop()
  137. {
  138.   c=digitalRead(10);
  139.   d=digitalRead(11);
  140.   Serial.println(c);
  141.   Serial.println(d);
  142.   if(c==HIGH&&d==HIGH)//判断为得奖
  143.   {
  144.       Serial.println("de");
  145.       for(int i=0;i<128;i++)
  146.         {
  147.            //将int型数组的值变为float,这样做可以减少内存的使用量
  148.            float x=dpaint_x[i]*1.0/100.0;
  149.            float y=dpaint_y[i]*1.0/100.0;
  150.            
  151.            //调用函数,并通过增加数值的改变图像零点的位置
  152.            xyMove(x+33,y+38);
  153.            
  154.            if(dpaint_bi[i]==1)//1代表抬笔
  155.            {
  156.              for(int degree=180;degree>=30;degree--)
  157.              {  
  158.                dj.write(degree);
  159.                delay(5);
  160.              }
  161.            }
  162.            else if(dpaint_bi[i]==2)//2代表落笔
  163.            {
  164.              for(int degree=30;degree<=180;degree++)
  165.              {
  166.                dj.write(degree);
  167.                delay(5);
  168.              }
  169.            }
  170.            delay(200);//延时,减少笔的抖动
  171.         }
  172.         
  173.          xyMove(base_x,base_y);//回到定位点
  174.   }
  175.   else if(c==HIGH&&d==LOW)//判断为没得奖
  176.   {
  177.       Serial.println("no");
  178.       for(int i=0;i<115;i++)
  179.       {
  180.          //将int型数组的值变为float,这样做可以减少内存的使用量
  181.          float x=npaint_x[i]*1.0/100.0;
  182.          float y=npaint_y[i]*1.0/100.0;
  183.          
  184.          //调用函数,并通过增加数值的改变图像零点的位置
  185.          xyMove(x+33,y+37);
  186.          
  187.          //舵机角度改变
  188.          if(npaint_bi[i]==1)//1代表抬笔
  189.          {
  190.            for(int degree=180;degree>=30;degree--)
  191.            {  
  192.              dj.write(degree);
  193.              delay(5);
  194.            }
  195.          }
  196.          else if(npaint_bi[i]==2)//2代表落笔
  197.          {
  198.            for(int degree=30;degree<=180;degree++)
  199.            {
  200.              dj.write(degree);
  201.              delay(5);
  202.            }
  203.          }
  204.          delay(200);//延时,减少笔的抖动
  205.       }
  206.       
  207.        xyMove(base_x,base_y);//回到定位点
  208.       
  209.   }
  210.   else//判断为没有信号输入
  211.   {
  212.     delay(20);//延时等待下一次
  213.   }
  214.   
  215.                
  216. }
  217. //函数作用为从现在的点移动到目标点(dest_x,dest_y)
  218. void xyMove(float dest_x,float dest_y)
  219. {
  220.     //a,b代表与步进a与步进b相连的同步带的长度
  221.     init_a=float(sqrt(pow(init_x,2)+pow(init_y,2)));
  222.     init_b=float(sqrt(pow(D-init_x,2)+pow(init_y,2)));
  223.     dest_a=float(sqrt(pow(dest_x,2)+pow(dest_y,2)));
  224.     dest_b=float(sqrt(pow(D-dest_x,2)+pow(dest_y,2)));
  225.    
  226.     da=dest_a-init_a;
  227.     db=dest_b-init_b;
  228. //通过计算目的长度-初始长度得到步进电机移动的步数     
  229.     step_a=fabs(da*step_per_cm)+0.5;
  230.     step_b=fabs(db*step_per_cm)+0.5;  
  231.   
  232.      //通过步数的比例得到运动速度的比例
  233.      //使得两个步进可以同时开始同时停止
  234.      if(step_a>=step_b)
  235.      {
  236.          speed_a=spd;
  237.          speed_b=(step_b*1.0/step_a)*spd;
  238.      }
  239.      else
  240.      {
  241.          speed_b=spd;
  242.          speed_a=(step_a*1.0/step_b)*spd;
  243.      }
  244.      
  245.      //步进电机运转方向设定
  246.      if(da<0)
  247.          {  step_a=step_a*(-1);}
  248.      if(db<0)
  249.          {  step_b=step_b*(-1);}
  250.      
  251.      //步进电机转速.步数设定
  252.      stepper1.rotate(speed_a,-step_a);
  253.      stepper2.rotate(speed_b,step_b);
  254.      
  255.      times=0;//需要初始化,以保证连续运动
  256.      while (times < 1)  
  257.      {
  258.           //判断设定的步数是否走完
  259.           if (stepper1.isDone()==false)
  260.           {      
  261.               stepper1.run();//走一步
  262.           }
  263.           //判断设定的步数是否走完
  264.           if (stepper2.isDone()==false)
  265.           {      
  266.               stepper2.run();
  267.           }
  268.           //都走完了,跳出死循环
  269.           if(stepper1.isDone()&&stepper2.isDone())
  270.           {
  271.             times=1;
  272.           }
  273.      }
  274.      
  275.      init_x=dest_x;
  276.      init_y=dest_y;
  277.      //移动到目的坐标后,将目的坐标存在起始点中,等待下一次移动
  278.      
  279.      
  280. }
复制代码


回复

使用道具 举报

发表于 2014-12-12 14:21:00 | 显示全部楼层
非常牛逼!
回复 支持 反对

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 13:08 , Processed in 0.048679 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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