zoukankan      html  css  js  c++  java
  • 【华为云技术分享】40多元成本制作基于Arduin的随动四轴机械臂,机械臂实现步骤记录、复现等功能

    【摘要】 Arduin随动四轴机械臂,机械臂实现步骤记录、复现等功能;主要原材料元器件有:电位器 * 4、9g舵机 * 4、轻触开关 * 1、Arduin UNO * 1、热熔胶、杜邦线多根(建议用质量好的杜邦线)、连接用的木棍(可以用其他代替)。

    制作这个机械臂是导师留下的作业,任务要求是夹取印章,然后在指定的地方盖章。程序要求能记录步骤,并且复现出来。

    先大概看下丑陋的成品:

    image.png

    说实话确实很丑,因为临近毕业了,事情又多,没时间搞那么好看了

    原材料

    电位器 * 4

    9g舵机 * 4

    轻触开关 * 1

    面包板 * 1

    Arduin UNO * 1

    热熔胶

    杜邦线多根(建议用质量好的杜邦线)

    连接用的木棍(可以用其他代替)

    image.png

    然后用热熔胶连接成下图的样子:

    image.png

    这样就可以做成随动机械臂了,但是后来因为用电烙铁把电位器管脚连接起来后接触不良,原因是电烙铁的温度使电位器的连接处发生变形,导致的接触不良。随后就拆掉了,也没心思搞了,最后就变成一开始的样子了。

    电路连接图如下:

    image.png

    最终的成品:

    image.png

    老师布置的任务要求是夹取印章,然后在指定的地方盖章。程序要求能记录步骤,并且复现出来。

    为了节约成本,我只用了一个按键

    按键功能:(按几次板子上的灯也相应的会闪烁几次,长按会快速闪烁4次)

    按1次:按顺序记录步骤n;

    按2次:复现(把刚刚记录的步骤重复一遍);

    按3次:暂未定义;

    长按1秒:清除记录的所有步骤。

    下面我把自己写的代码贴出来(自己研究一下吧):

      1 #include <Servo.h>                    //舵机头文件
      2 #include <stdio.h>           
      3 #include <string.h>
      4 #include <MsTimer2.h>            //定时器库的 头文件,需添加对应的头文件才可使用,文件放在尾端资源处,自行下载
      5  
      6 Servo myservo1;                                  // 创建一个伺服电机对象1
      7 Servo myservo2;                                  // 创建一个伺服电机对象2
      8 Servo myservo3;                                  // 创建一个伺服电机对象3
      9 Servo myservo4;                                  // 创建一个伺服电机对象4
     10  
     11 #define Servo_Num 4         //自定义舵机个数
     12 #define STEP 30             //自定义最大记录步数
     13 #define KEY 2               //定义多功能按键管脚
     14 #define Step_time 15        //定义步骤复现时舵机改变1度的时间,单位:ms
     15  
     16 int dianweiqi1 = 0;
     17 int dianweiqi2 = 0;
     18 int dianweiqi3 = 0;
     19 int dianweiqi4 = 0;
     20  
     21 unsigned int step_num = 1;   //定义已走步数变量
     22 unsigned int flag = 0;       //定义按键次数标志位
     23 unsigned int key_num = 0;    //按键次数
     24  
     25 unsigned char Step_Receive [ STEP + 1 ][ Servo_Num ] = {0}; //定义储存步数,初始化为0,最多存储STEP步
     26  
     27 //函数声明
     28 void Servo_Read();
     29 void Blink(int i);
     30 void slow_Step(int i);
     31  
     32  
     33 void setup()
     34 {
     35   pinMode(KEY,INPUT_PULLUP);        //初始化按键,上拉输入
     36   pinMode(LED_BUILTIN, OUTPUT);      //初始化LED灯
     37  
     38   myservo1.attach(6);                     //
     39   myservo2.attach(9);                     // 小臂舵机
     40   myservo3.attach(10);                     // 大臂舵机
     41   myservo4.attach(11);                     // 底座旋转
     42  
     43   MsTimer2::set(700, RT);       // 中断设置函数,每 700ms 进入一次中断
     44  
     45 }
     46  
     47  
     48  
     49 void loop()
     50 {
     51  
     52   dianweiqi1 = analogRead(0);                          //读取A0口模拟量
     53   dianweiqi1 = map(dianweiqi1, 0, 1023, 180, 0);       //将模拟量转换为0~180之间的数值
     54   myservo1.write( dianweiqi1 );
     55  
     56   dianweiqi2 = analogRead(1);
     57   dianweiqi2 = map(dianweiqi2, 0, 1023, 0, 180); //这样更改值会使舵机反着转
     58   myservo2.write( dianweiqi2 );
     59  
     60   dianweiqi3 = analogRead(2);
     61   dianweiqi3 = map(dianweiqi3, 0, 1023, 180, 0);
     62   myservo3.write( dianweiqi3 );
     63  
     64   dianweiqi4 = analogRead(3);
     65   dianweiqi4 = map(dianweiqi4, 0, 1023, 0, 180);
     66   myservo4.write( dianweiqi4 );
     67  
     68   Scan_KEY();                                              //按键扫描
     69   if(key_num > 0)
     70   {
     71     if( flag == 0 && key_num == 1 )   //按一次记录步骤
     72     {
     73       Blink(key_num, 400);
     74       Servo_Read();
     75       key_num = 0;
     76     }
     77  
     78     else if(flag == 0 && key_num == 2)//按两次记录复现
     79     {
     80       Blink(key_num, 400);
     81       Servo_Step_recur();
     82       key_num = 0;
     83     }
     84  
     85     else if(flag == 0 && key_num == 3)//按三次循环复现
     86     {
     87       Blink(key_num, 400);
     88       key_num = 0;
     89     }
     90  
     91     else if(flag == 0 && key_num >= 4)//长按清除记录步骤
     92     {
     93       memset( Step_Receive, 0, sizeof(Step_Receive) / 4 );
     94       step_num = 1;                   //步数记录回到第1步
     95       Blink(key_num, 200);            //LED灯闪烁4次
     96       key_num = 0;
     97     }
     98   }
     99  
    100 }
    101  
    102  
    103 void RT()   //中断函数
    104 {
    105   flag = 0;
    106   MsTimer2::stop();                                   //停止计时
    107 }
    108  
    109 void Scan_KEY()                                      //按键扫描
    110 {
    111   if( digitalRead(KEY) == 0 )         //查看按键是否按下
    112   {
    113     delay(80);                                 //延时80ms,去抖动 
    114     if( digitalRead(KEY) == 0 )       //查看按键是否按下
    115     {
    116       key_num++;
    117       flag = 1;
    118       MsTimer2::start();                //启动定时器
    119      
    120       while(digitalRead(KEY) == 0)  //松手检测,若超过700ms未松手,则判断为长按
    121       {
    122         delay(10);
    123         if( key_num == 1 && flag == 0 )
    124         {
    125           key_num = 4;
    126         }
    127       }
    128     }
    129    
    130   }
    131  
    132 }
    133  
    134 void slow_Step(int i)
    135 {
    136   int j = 0;
    137   int arr[Servo_Num + 1] = {0};
    138   int arr_temp[Servo_Num + 1] = {0};
    139  
    140   //如果是第一步,则记录现在的位置,作为对比
    141   if(i == 1)
    142   {
    143     Step_Receive[i - 1][0] = dianweiqi1;
    144     Step_Receive[i - 1][1] = dianweiqi2;
    145     Step_Receive[i - 1][2] = dianweiqi3;
    146     Step_Receive[i - 1][3] = dianweiqi4;
    147   }
    148  
    149  
    150   //与上一步对比,缓慢前进
    151   for(j = 0; j < Servo_Num; j++)
    152   {
    153     if( Step_Receive[i][j] - Step_Receive[i - 1][j] > 0 )
    154     {
    155       arr[j] = 1;
    156       arr_temp[j] = 1;
    157     }
    158    
    159     else if( Step_Receive[i][j] - Step_Receive[i - 1][j] < 0 )
    160     {
    161       arr[j] = -1;
    162       arr_temp[j] = -1;
    163     }
    164     else
    165     {
    166       arr[j] = 0;
    167       arr_temp[j] = 0;
    168     }
    169   }
    170  
    171   while( ( (Step_Receive[i - 1][0] + arr[0]) != (Step_Receive[i][0]) ) ||
    172          ( (Step_Receive[i - 1][1] + arr[1]) != (Step_Receive[i][1]) ) ||
    173          ( (Step_Receive[i - 1][2] + arr[2]) != (Step_Receive[i][2]) ) ||
    174          ( (Step_Receive[i - 1][3] + arr[3]) != (Step_Receive[i][3]) ) )    
    175   {
    176  
    177     myservo1.write( Step_Receive[i - 1][0] + arr[0] );
    178     if( (Step_Receive[i - 1][0] + arr[0]) != (Step_Receive[i][0]) ){
    179       arr[0] += arr_temp[0];
    180       }
    181    
    182     myservo2.write( Step_Receive[i - 1][1] + arr[1] );
    183     if( (Step_Receive[i - 1][1] + arr[1]) != (Step_Receive[i][1]) ){
    184       arr[1] += arr_temp[1];
    185       }
    186      
    187     myservo3.write( Step_Receive[i - 1][2] + arr[2] );
    188     if( (Step_Receive[i - 1][2] + arr[2]) != (Step_Receive[i][2]) ){
    189       arr[2] += arr_temp[2];
    190       }
    191      
    192     myservo4.write( Step_Receive[i - 1][3] + arr[3] );
    193     if( (Step_Receive[i - 1][3] + arr[3]) != (Step_Receive[i][3]) ){
    194       arr[3] += arr_temp[3];
    195       }
    196      
    197     delay(Step_time);
    198   }
    199  
    200 }
    201  
    202  
    203 void Servo_Step_recur()//舵机步骤复现
    204 {
    205   int i = 0, j = 0;
    206   for(i = 1; i < step_num; i++)
    207   {
    208     slow_Step(i);
    209 //    for(j = 0; j < 1; j++)//循环多次,让舵机接收PWM波持续一段时间
    210 //    {
    211 //      myservo1.write( Step_Receive[i][0] );
    212 //      myservo2.write( Step_Receive[i][1] );
    213 //      myservo3.write( Step_Receive[i][2] );
    214 //      myservo4.write( Step_Receive[i][3] );
    215 //    }
    216 //    delay(1000);//等待舵机到位
    217   }
    218  
    219 }
    220  
    221  
    222  
    223 void Servo_Read() //读取脉冲值
    224 {
    225   Step_Receive[step_num][0] = dianweiqi1;
    226   Step_Receive[step_num][1] = dianweiqi2;
    227   Step_Receive[step_num][2] = dianweiqi3;
    228   Step_Receive[step_num][3] = dianweiqi4;
    229   if (step_num < STEP)
    230   {
    231     step_num++;
    232   }
    233   else{
    234     Blink(15, 100);//超过最大记录步数 LED灯闪烁1.5s
    235     }
    236 }
    237  
    238 void Blink(int i, int j ){    //闪烁灯程序,i为闪烁次数,j为闪烁间隔 单位ms
    239     for(; i > 0; i--)
    240     {
    241       digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    242       delay(j);                       // wait for a second
    243       digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    244       delay(j);     
    245     }// wait for a second
    246   }

    MsTimer2.zip

    作者:Micah

  • 相关阅读:
    【转】hadoop中map和reduce的数量设置问题
    【转】MapReduce原理与设计思想
    eclipse中svn插件在线安装方式
    redis配置文件详解
    Hibernate_Validator学习
    WebService入门实例教程
    Http状态码大全(来自菜鸟教程)
    Java编程规则
    Java和C++的对比
    Java实现OOP(面向对象编程)
  • 原文地址:https://www.cnblogs.com/huaweicloud/p/12525713.html
Copyright © 2011-2022 走看看