单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
上一页
1/2
下一页
查看:27053|回复:43
打印上一主题下一主题

基于Arduino的可学习机械臂制作 附代码

 [复制链接]
跳转到指定楼层
楼主
ID:318910发表于 2019-4-15 18:09|只看该作者|只看大图回帖奖励
本帖最后由 cj52 于 2019-4-19 00:06 编辑

前段时间在知乎上看到有用Arduino做机械臂的,自己也做了一个来玩玩。
基本原理很简单,就是电位器(蓝白可调电阻)来控制舵机。
制作2个机械臂,从机械臂的关节处用电位器接合,主机械臂用舵机,将电位器的电压与舵机的角度相映射就能让舵机与电位器同步运作。
学习的具体内容见代码,基本上就是记录学习过程中的几个主要动作,然后根据这些主要动作来模糊推测大动作之间的小动作。

制作出来的实物图如下:


视频效果自取链接:https://pan.baidu.com/s/1gRzXL1DkdWBaYyxTWxKEyA   提取码:g9su
                    https://pan.baidu.com/s/1ngaNVAzMBjx2wjF1jojfbw   提取码:2vh6
                    https://pan.baidu.com/s/1vqZn4FpYyzftkw7iwNzFrA   提取码:cndx
第二个视频中主机械臂出现突变是因为从机械臂的电位器接触不良。
*******************************************************************************

Arduino源程序如下:

#include< Servo.h>
Servo servo_0;  //定义4个舵机
Servo servo_1;
Servo servo_2;
Servo servo_3;
int sensorPin0 = A0;  //电位器阻值输入口
int sensorPin1 = A1;
int sensorPin2 = A2;
int sensorPin3 = A3;
int SensVal_0;
int SensVal_1;
int SensVal_2;
int SensVal_3;
boolean playmode = false;  //设置运行模式,初始化为学习
float angle0[30];// 存储底座舵机动作的数组,最多存30个
float angle1[30];//手臂舵机角度数组
float angle2[30];//手掌舵机角度数组
float angle3[30];//夹子舵机角度数组
float dif[4],temp[4];// 差分值与中间数组

int i,j,k,stepsMax,num=0,key_value,num1=0,del;
void setup() {
   // put your setup code here, to run once:
   pinMode(4, INPUT);  // 键盘输入口
   servo_0.attach(6); // 连接舵机
   servo_1.attach(9);
   servo_2.attach(10);
   servo_3.attach(11);
   Serial.begin(115200);
}
void loop()
{
   // put your main code here, to run repeatedly:
   if(playmode == false)     //学习模式
   {
   SensVal_1 = analogRead(sensorPin1); //读取电位器阻值
   //Serial.println(SensVal_1);
   SensVal_1 = map(SensVal_1, 0, 1024, 500, 2500);//将电位器阻值与舵机角度映射,实现两个机械臂的同步
  
   SensVal_0 = analogRead(sensorPin0);
   //Serial.println(SensVal_0);
   SensVal_0 = map(SensVal_0, 0, 1024, 500, 2500);
  
   SensVal_2 = analogRead(sensorPin2);
   //Serial.println(SensVal_2);
   SensVal_2 = map(SensVal_2, 0, 1024, 500, 2500);
  
   SensVal_3 = analogRead(sensorPin3);
     //Serial.println(SensVal_3);
   SensVal_3 = map(SensVal_3, 0, 1024, 500, 2500);
  
   servo_0.writeMicroseconds(SensVal_0); //控制主机械臂跟随从机械臂运行
   servo_1.writeMicroseconds(SensVal_1);
   servo_2.writeMicroseconds(SensVal_2);
   servo_3.writeMicroseconds(SensVal_3);
   }
   else       //运行模式
   {
     for(i=0;i<num;i++)
     {
       temp[0]=angle0;   //暂存当前动作角度值
      
temp[1]=angle1;
       temp[2]=angle2;
       temp[3]=angle3;
       j=i+1;           //指向下一个动作
       if(j==num) j=0;
       dif[0] = abs(angle0[j]-angle0);     //下一动作与当前动作做差分
       dif[1] = abs(angle1[j]-angle1);
       dif[2] = abs(angle2[j]-angle2);
       dif[3] = abs(angle3[j]-angle3);
      
       stepsMax = max(dif[0],dif[1]);       //找出最大差分值
       stepsMax = max(stepsMax,dif[2]);
       stepsMax = max(stepsMax,dif[3]);
       //将两个动作分为最大差分值个小动作,即用每个舵机的差分值除以最大差分值
       if (angle0[j]< angle0) dif[0] = 0-dif[0]/stepsMax; else dif[0] = dif[0]/stepsMax;
       if (angle1[j]< angle1) dif[1] = 0-dif[1]/stepsMax; else dif[1] = dif[1]/stepsMax;
       if (angle2[j]< angle2) dif[2] = 0-dif[2]/stepsMax; else dif[2] = dif[2]/stepsMax;
       if (angle3[j]< angle3) dif[3] = 0-dif[3]/stepsMax; else dif[3] = dif[3]/stepsMax;
      
       for(k=0;k<stepsMax;k++)   // 运行至下一大动作
       {
       //Serial.println("stepin");
       angle0 += dif[0];   //运行到下一小动作
       angle1 += dif[1];
       angle2 += dif[2];
       angle3 += dif[3];
      
       servo_0.writeMicroseconds(angle0);
       servo_1.writeMicroseconds(angle1);
       servo_2.writeMicroseconds(angle2);
       servo_3.writeMicroseconds(angle3);
       delay(1);
       }
       //Serial.println("stepout");
       angle0=temp[0];         //返回暂存的动作值
       angle1=temp[1];
       angle2=temp[2];
       angle3=temp[3];
     }
   }
   //Serial.println(digitalRead(4));
   Button();   //按键检测
}
void Button() //按键检测
{
   if (digitalRead(4) == true)
   {
   delay(20);           //消抖
   if (digitalRead(4) == true)
   {
       key_value = 1;
       delay(1000);
       if(digitalRead(4) == true) key_value = 2; //长按进入运行模式
   }
   }
  
   if ((key_value == 1)) // 记录舵机当前位置
   {
    
     angle0[num1]=SensVal_0;
     angle1[num1]=SensVal_1;
     angle2[num1]=SensVal_2;
     angle3[num1]=SensVal_3;
     num1++;               //指针加1
     key_value = 0;
     playmode = false;
   }
   else if (key_value == 2)
   {
     num = num1;           //取出动作的总数
     num1=0;             //为下一次学习做准备
     playmode = true;       //运行模式
     key_value = 0;
   }
}

评分

黑币 +50
收起理由
+ 50
共享资料的黑币奖励!

查看全部评分

来自 2#
ID:318910发表于 2020-1-27 18:37|只看该作者
本帖最后由 cj52 于 2020-1-30 10:52 编辑

有问题的代码是因为那些数组后面少了下标i,这个论坛的编辑器把i识别成斜体变换了,所以有问题的代码后面都是斜体,而且i不见了,改动只需要在angle0 angele1等这些数组后面加上方括号,里面再加上i即可
来自 3#
ID:318910发表于 2020-3-4 21:03|只看该作者
cj52 发表于 2020-1-27 18:37
有问题的代码是因为那些数组后面少了下标i,这个论坛的编辑器把i识别成斜体变换了,所以有问题的代码后面都是 ...

今天学会了回复图片和文件。。。所以在这里回复下面有同学要的接线图 附软件流程图和当时实验报告 哈哈哈哈

实习51hei.doc

2.16 MB, 下载次数: 59, 下载积分: 黑币 -5

实习报告

地板
ID:426684发表于 2019-4-16 20:00|只看该作者
作者自己测试过该代码吗?

float angle0[30];  编译出错?  
5#
ID:318910发表于 2019-4-18 16:04|只看该作者
探索软件 发表于 2019-4-16 20:00
作者自己测试过该代码吗?

float angle0[30];  编译出错?

测试过  刚又编译了一次 没有问题啊

评分

黑币 +50
收起理由
+ 50
回帖助人的奖励!

查看全部评分

6#
ID:521352发表于 2019-4-26 10:08|只看该作者
厉害!我对自制机器人的理解还处在MATLAB阶段。。。
7#
ID:474784发表于 2019-7-19 02:07来自手机|只看该作者
问题,同一楼编译出错
8#
ID:474784发表于 2019-7-19 02:16来自手机|只看该作者
数组不能复制
9#
ID:474784发表于 2019-7-19 02:47来自手机|只看该作者
探索软件 发表于 2019-4-16 20:00
作者自己测试过该代码吗?

float angle0[30];  编译出错?

加我好友qq   1595141562  
我刚刚改了一下代码,就好了。
10#
ID:115780发表于 2019-9-5 21:19|只看该作者
改动的哪里代码啊 ?
11#
ID:628606发表于 2019-10-23 06:18|只看该作者
彭大伟 发表于 2019-7-19 02:47
加我好友qq   1595141562  
我刚刚改了一下代码,就好了。

改到哪里了?可以把改的地方再发一次吗?谢谢。。。
12#
ID:628217发表于 2019-10-23 08:51|只看该作者
动手能力真强啊,底座感觉太单薄了,保持平衡会有问题
13#
ID:656210发表于 2019-12-4 19:42|只看该作者
作者你好请问能私聊问你些事情吗?
14#
ID:171746发表于 2019-12-15 18:23|只看该作者
Arduino:1.8.9 (Windows 7), 开发板:"Arduino/Genuino Uno"

The sketch name had to be modified.
Sketch names must start with a letter or number, followed by letters,
numbers, dashes, dots and underscores. Maximum length is 63 characters.

C:\Users\Administrator\Documents\Arduino\jiqibi_xuexi_001\jiqibi_xuexi_001.ino: In function 'void loop()':

jiqibi_xuexi_001:63:16: error: cannot convert 'float [30]' to 'float' in assignment

       temp[0]=angle0;   //暂存当前动作角度值

           ^

jiqibi_xuexi_001:64:16: error: cannot convert 'float [30]' to 'float' in assignment

       temp[1]=angle1;

           ^

jiqibi_xuexi_001:65:16: error: cannot convert 'float [30]' to 'float' in assignment

       temp[2]=angle2;

           ^

jiqibi_xuexi_001:66:16: error: cannot convert 'float [30]' to 'float' in assignment

       temp[3]=angle3;

           ^

In file included from sketch\jiqibi_xuexi_001.ino.cpp:1:0:

jiqibi_xuexi_001:69:32: error: invalid operands of types 'float' and 'float [30]' to binary 'operator-'

       dif[0] = abs(angle0[j]-angle0);     //下一动作与当前动作做差分

                       ^

D:\A
15#
ID:171746发表于 2019-12-15 18:27|只看该作者
请把改动的发一下吗?  谢谢
16#
ID:171746发表于 2019-12-15 18:42|只看该作者
weixiao_99 发表于 2019-12-4 19:42
作者你好请问能私聊问你些事情吗?

改到哪里了?可以把改的地方再发一次吗?谢谢
17#
ID:318910发表于 2020-1-27 18:45|只看该作者
weixiao_99 发表于 2019-12-4 19:42
作者你好请问能私聊问你些事情吗?

可以啊
18#
ID:318910发表于 2020-1-27 18:54|只看该作者
本帖最后由 cj52 于 2020-1-29 16:42 编辑
探索软件 发表于 2019-4-16 20:00
作者自己测试过该代码吗?

float angle0[30];  编译出错?

先跟你道个歉,上次我说测试没问题是因为我用的是我电脑中的代码测试,没有用这里的代码。快一年没有上这个论坛了,今天上来发现有很多朋友都说这个问题,我把这里的代码复制过去编译,发现确实有问题。不知道怎么从电脑上传到这里就漏了一些东西,就是数组名后面的下标掉了,错误的地方就变成了把数组名(也就是指针)赋给float变量,所以出错了,改动只需在数组名(angle0,angle1,angle2,angle3)后面加上下标即可
19#
ID:318910发表于 2020-1-27 18:58|只看该作者
快一年没有上到这个论坛了,今天闲来无事登上来才发现这个帖子都有4000多的浏览了,有点小激动。看到很多朋友都说有编译问题,才把这里的代码复制来测试了一遍找到了问题所在,错误的具体原因和改动方法已经回复在一楼了,有需要的朋友可以看看
20#
ID:318910发表于 2020-1-27 18:58|只看该作者
lucq7896 发表于 2019-12-15 18:27
请把改动的发一下吗?  谢谢

已经在一楼回复了
21#
ID:318910发表于 2020-1-27 19:01|只看该作者
彭大伟 发表于 2019-7-19 02:07
问题,同一楼编译出错

问题已经回复在一楼,谢谢
22#
ID:318910发表于 2020-1-27 19:02|只看该作者
cd5566 发表于 2019-9-5 21:19
改动的哪里代码啊 ?

已经回复在一楼,谢谢
23#
ID:318910发表于 2020-1-27 19:02|只看该作者
s7club 发表于 2019-10-23 06:18
改到哪里了?可以把改的地方再发一次吗?谢谢。。。

已经回复在一楼,谢谢
24#
ID:693988发表于 2020-2-16 18:10|只看该作者
up主你好,我把数组名都改了,下载了不能跟着电位计随动,只能长按按键的时候才能随动,能不能解答一下,谢谢
25#
ID:693988发表于 2020-2-16 18:12|只看该作者
程序编译时没问题了,只是下载到板子里不能随动,麻烦解答一下,谢谢
26#
ID:701071发表于 2020-3-2 11:52|只看该作者
热心市民王先生2 发表于 2020-2-16 18:12
程序编译时没问题了,只是下载到板子里不能随动,麻烦解答一下,谢谢

你好,请问问题解决了吗,能分享一下资料吗?
27#
ID:701071发表于 2020-3-2 14:26|只看该作者
cj52 发表于 2020-1-27 18:37
有问题的代码是因为那些数组后面少了下标i,这个论坛的编辑器把i识别成斜体变换了,所以有问题的代码后面都是 ...

接线图可以发一下吗?请问
28#
ID:701486发表于 2020-3-3 05:34|只看该作者
建议上传到优酷,方便观看

这个操作方式挺新奇的
29#
ID:318910发表于 2020-3-4 20:31|只看该作者
小张总 发表于 2020-3-2 14:26
接线图可以发一下吗?请问

可以啊 但我不知道怎么回复图片。。。
30#
ID:318910发表于 2020-3-4 21:03|只看该作者
小张总 发表于 2020-3-2 14:26
接线图可以发一下吗?请问

哈哈哈 我会回复图片了 已经回复在一楼
31#
ID:693988发表于 2020-3-17 14:43|只看该作者
小张总 发表于 2020-3-2 11:52
你好,请问问题解决了吗,能分享一下资料吗?

没有呢
32#
ID:693988发表于 2020-3-17 14:46|只看该作者
cj52 发表于 2020-1-27 19:02
已经回复在一楼,谢谢

已经按照你说的添加了下标了,编译也没有问题,但现在不按按键,舵机根本就不能随动
33#
ID:318910发表于 2020-3-18 13:35|只看该作者
热心市民王先生2 发表于 2020-3-17 14:46
已经按照你说的添加了下标了,编译也没有问题,但现在不按按键,舵机根本就不能随动

接线对不对? 滑动变阻器是不是没有引入AD口?因为蓝白可调电阻从最小的阻值到最大的阻值刚好转了一圈,所以随动的原理是将蓝白可调电阻作为角度传感器,把它的阻值与旋转角度对应起来,通过AD采样电阻上的电压,就知道大概转了多少角度,然后把这个角度换算成舵机的PWM值,再去控制舵机,这样就能随动了。你可以先自己写一小段代码在面包板上测试一下,用一个滑动变阻器来控制一个舵机旋转,我觉得这个挺有意思的。。可以发散到其他许多地方,比如远程控制等,你不妨也拓展拓展,做一些有意思的东西,不必拘泥于这一个机械臂。

评分

黑币 +90
收起理由
+ 90
回帖助人的奖励!

查看全部评分

34#
ID:693988发表于 2020-3-19 13:59|只看该作者
cj52 发表于 2020-3-18 13:35
接线对不对? 滑动变阻器是不是没有引入AD口?因为蓝白可调电阻从最小的阻值到最大的阻值刚好转了一圈, ...

好的,谢谢啦
35#
ID:717402发表于 2020-3-28 11:09|只看该作者
初来咋到,请多关照,向大师们致敬!
36#
ID:742968发表于 2020-5-2 19:19|只看该作者
热心市民王先生2 发表于 2020-2-16 18:10
up主你好,我把数组名都改了,下载了不能跟着电位计随动,只能长按按键的时候才能随动,能不能解答一下,谢 ...

按键没接对哦,要用微动按键,你可以把  Serial.println(key_value);   这句加一下。就可以知道你按键对不对了。
37#
ID:747036发表于 2020-5-8 16:42|只看该作者
好厉害,支持支持
38#
ID:739532发表于 2020-5-21 15:14|只看该作者
楼主好厉害
39#
ID:617786发表于 2020-5-27 18:53|只看该作者
大佬能加一下你QQ吗请教按键问题,为神魔串口监视器一直读出来按键值是1,一直按着才是0.

40#
ID:617786发表于 2020-5-27 19:27|只看该作者
大佬你用的按键是哪种按键,

手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网