本帖最后由 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;
}
}
前段时间在知乎上看到有用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;
}
}
评分
本帖最后由 cj52 于 2020-1-30 10:52 编辑
有问题的代码是因为那些数组后面少了下标i,这个论坛的编辑器把i识别成斜体变换了,所以有问题的代码后面都是斜体,而且i不见了,改动只需要在angle0 angele1等这些数组后面加上方括号,里面再加上i即可
有问题的代码是因为那些数组后面少了下标i,这个论坛的编辑器把i识别成斜体变换了,所以有问题的代码后面都是斜体,而且i不见了,改动只需要在angle0 angele1等这些数组后面加上方括号,里面再加上i即可
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
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
本帖最后由 cj52 于 2020-1-29 16:42 编辑
先跟你道个歉,上次我说测试没问题是因为我用的是我电脑中的代码测试,没有用这里的代码。快一年没有上这个论坛了,今天上来发现有很多朋友都说这个问题,我把这里的代码复制过去编译,发现确实有问题。不知道怎么从电脑上传到这里就漏了一些东西,就是数组名后面的下标掉了,错误的地方就变成了把数组名(也就是指针)赋给float变量,所以出错了,改动只需在数组名(angle0,angle1,angle2,angle3)后面加上下标即可
先跟你道个歉,上次我说测试没问题是因为我用的是我电脑中的代码测试,没有用这里的代码。快一年没有上这个论坛了,今天上来发现有很多朋友都说这个问题,我把这里的代码复制过去编译,发现确实有问题。不知道怎么从电脑上传到这里就漏了一些东西,就是数组名后面的下标掉了,错误的地方就变成了把数组名(也就是指针)赋给float变量,所以出错了,改动只需在数组名(angle0,angle1,angle2,angle3)后面加上下标即可
快一年没有上到这个论坛了,今天闲来无事登上来才发现这个帖子都有4000多的浏览了,有点小激动。看到很多朋友都说有编译问题,才把这里的代码复制来测试了一遍找到了问题所在,错误的具体原因和改动方法已经回复在一楼了,有需要的朋友可以看看
接线对不对? 滑动变阻器是不是没有引入AD口?因为蓝白可调电阻从最小的阻值到最大的阻值刚好转了一圈,所以随动的原理是将蓝白可调电阻作为角度传感器,把它的阻值与旋转角度对应起来,通过AD采样电阻上的电压,就知道大概转了多少角度,然后把这个角度换算成舵机的PWM值,再去控制舵机,这样就能随动了。你可以先自己写一小段代码在面包板上测试一下,用一个滑动变阻器来控制一个舵机旋转,我觉得这个挺有意思的。。可以发散到其他许多地方,比如远程控制等,你不妨也拓展拓展,做一些有意思的东西,不必拘泥于这一个机械臂。