玩过很长一段时间单片机,一直想接触Arduino系列板子,这次如愿以偿。用去年自己3D打印机打的机器人外壳,Arduino UNO R3+舵机控制板,做的一个四足机器人。
不得不承认Arduino确是个好东西,开发速度极快,极易上手。从开始动手到完成,只持续了3天不到,测试。调代码。封装。
整个过程里一开始就感觉会头疼的就是机器人的步态,因为之前也没接触过。实际操作起来比想象中容易的多。现在的机器人支持前进、后退、左转、右转、起立、坐下。五种步态。通过摇杆控制。
废话不多说,贴一下代码。
代码经过粗略的封装,舵机控制板有个库文件需要下载调用,别的都是手打的代码
主要封装了单足控制函数action.参数说明:foot:第N只足,Up:足举起的高度,Dis:足向前转动的角度幅度,walk:取0或1,0代表原地运动,1代表走动。主要是为了区别出起立坐下这两个原地运动。
再把action函数封装进前进、后退、左转、右转四个函数中,参数仅有t,用于设定动作间的延时,以控制整体的运动速度。
void action(int foot,int Up,int Dis,int walk=0){
switch (foot){
case 0 : hor = 0 ; ver = 4 ; verBegin=340;
break ;
case 1 : hor = 1 ; ver = 5 ; Up=-Up;verBegin=400;
Dis=-Dis;
break ;
case 2 : hor = 2 ; ver = 6 ; verBegin=340;
Dis=-Dis;
break ;
case 3 : hor = 3 ; ver = 7 ; Up=-Up;verBegin=400;
break ;
}
pwm.setPWM(ver, 0, verBegin + Up);
pwm.setPWM(hor, 0, SERVOBEGIN_0 + Dis);
delay(150);
if(walk){
pwm.setPWM(ver, 0, verBegin);
}
}
#include
#include
// 使用默认I2C地址 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // this is the 'maximum' 脉冲宽度 count (out of 4096)
//定义begin状态,即机器人准备爬行状态的舵机初始值,修改初始定义值调节四足平衡,消除机械误差
//注释后为无机械误差的理想值
#define SERVOBEGIN_0 375 //左前横臂 375
#define SERVOBEGIN_1 375 //右前横臂 375
#define SERVOBEGIN_2 375 //右后横臂 375
#define SERVOBEGIN_3 375 //左后横臂 375
#define SERVOBEGIN_4 340 //左前纵臂 340
#define SERVOBEGIN_5 400 //右前纵臂 400
#define SERVOBEGIN_6 340 //右后纵臂 340
#define SERVOBEGIN_7 400 //左后纵臂 400
#define SERVOBEGIN_8 375 //尾巴起点 375
#define UP 60 //纵向幅度
#define Distance 80 //前进幅度
int i =0;
boolean q;
void setup() {
Serial.begin(9600);
//Serial.println("16 channel Servo test!");
pwm.begin();
pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
}
/*参数说明
* A0为Y轴,A1为X轴
* 从 0 ~ 1023 分别代表 左~右,上~下。中间值为512。
* 舵机信号范围150-600
* 纵向脚的摆动幅度设置:机械上最大值为90度,实际操作设置为70度
* 170为上止点,170+175=345,345下止点(实际用340)
* 旁边臂为对称2号和4号,起始点570,下止点570-175=395(实际用400)
* 150-600代表180度行程,(450/180)*70=175
* 横向脚摆动设置:以375为中间点,机械上摆动幅度为180度,
* 前后摆动幅度为各40度,375+-100为前后,(275,475)
* 0-3为横向舵机,4-7为纵向舵机
*动作部分:
*0,1,2,3 代表前后左右,4代表起立或坐下
*/
/*
* 转动方向前,Dis为正
*/
int ver;//纵向舵机
int verBegin;
int hor;//横向舵机
void action(int foot,int Up,int Dis,int walk=0){
switch (foot){
case 0 : hor = 0 ; ver = 4 ; verBegin=340;
break ;
case 1 : hor = 1 ; ver = 5 ; Up=-Up;verBegin=400;
Dis=-Dis;
break ;
case 2 : hor = 2 ; ver = 6 ; verBegin=340;
Dis=-Dis;
break ;
case 3 : hor = 3 ; ver = 7 ; Up=-Up;verBegin=400;
break ;
}
pwm.setPWM(ver, 0, verBegin + Up);
pwm.setPWM(hor, 0, SERVOBEGIN_0 + Dis);
delay(150);
if(walk){
pwm.setPWM(ver, 0, verBegin);
}
}
void sit(){
//下蹲
//横臂锁定调中
pwm.setPWM(0, 0, SERVOBEGIN_0);
pwm.setPWM(1, 0, SERVOBEGIN_1);
pwm.setPWM(2, 0, SERVOBEGIN_2);
pwm.setPWM(3, 0, SERVOBEGIN_3);
//下蹲
pwm.setPWM(4, 0, SERVOBEGIN_4 - 170);//1,2号纵臂
pwm.setPWM(5, 0, SERVOBEGIN_5 + 170);
pwm.setPWM(6, 0, SERVOBEGIN_6 - 170);//3,4号纵臂
pwm.setPWM(7, 0, SERVOBEGIN_7 + 170);
}
void stand(){ //站立
//横向调中
pwm.setPWM(0, 0, SERVOBEGIN_0);
pwm.setPWM(1, 0, SERVOBEGIN_1);
pwm.setPWM(2, 0, SERVOBEGIN_2);
pwm.setPWM(3, 0, SERVOBEGIN_3);
//站立
pwm.setPWM(4, 0, SERVOBEGIN_4);
pwm.setPWM(5, 0, SERVOBEGIN_5);
pwm.setPWM(6, 0, SERVOBEGIN_6);
pwm.setPWM(7, 0, SERVOBEGIN_7);
}
void prewalk0(){
pwm.setPWM(1, 0, SERVOBEGIN_0+80);
pwm.setPWM(0, 0, SERVOBEGIN_0-80);
}
void move0(int t){
action(1,-70,0,1);
delay(t/4);
action(3,-70,80,1);
delay(t/2);
pwm.setPWM(1, 0, SERVOBEGIN_0+80);
delay(t/8);
pwm.setPWM(3, 0, SERVOBEGIN_0);
delay(t/8);
action(0,-70,0,1);
delay(t/4);
action(2,-70,80,1);
delay(t/2);
pwm.setPWM(0, 0, SERVOBEGIN_0-80);
delay(t/8);
pwm.setPWM(2, 0, SERVOBEGIN_0);
delay(t/8);
}
void prewalk1(){
pwm.setPWM(2, 0, SERVOBEGIN_0-80);
pwm.setPWM(3, 0, SERVOBEGIN_0+80);
}
void move1(int t){
action(3,-70,0,1);
delay(t/4);
action(1,-70,-80,1);
delay(t/2);
pwm.setPWM(3, 0, SERVOBEGIN_0+80);
delay(t/8);
pwm.setPWM(1, 0, SERVOBEGIN_0);
delay(t/8);
action(2,-70,0,1);
delay(t/4);
action(0,-70,-80,1);
delay(t/2);
pwm.setPWM(2, 0, SERVOBEGIN_0-80);
delay(t/8);
pwm.setPWM(0, 0, SERVOBEGIN_0);
delay(t/8);
}
void turnLeft(int t){
action(1,-70,-80,1);
delay(t/2);
action(3,-70,80,1);
delay(t/2);
action(0,-70,80,1);
delay(t/2);
action(2,-70,-80,1);
delay(t/2);
pwm.setPWM(1, 0, SERVOBEGIN_0);
pwm.setPWM(3, 0, SERVOBEGIN_0);
pwm.setPWM(0, 0, SERVOBEGIN_0);
pwm.setPWM(2, 0, SERVOBEGIN_0);
delay(t*1.5);
}
void turnRight(int t){
action(0,-70,-80,1);
delay(t/2);
action(2,-70,80,1);
delay(t/2);
action(1,-70,80,1);
delay(t/2);
action(3,-70,-80,1);
delay(t/2);
pwm.setPWM(0, 0, SERVOBEGIN_0);
pwm.setPWM(2, 0, SERVOBEGIN_0);
pwm.setPWM(1, 0, SERVOBEGIN_0);
pwm.setPWM(3, 0, SERVOBEGIN_0);
delay(t*1.5);
}
void loop() {
// Drive each servo one at a time
//Serial.println(servonum);
//纵臂摆动,横臂锁定
q=true;
int p=0;
int act=5;
while(1){
if(analogRead(A1)<100){act=0;}
if(analogRead(A1)>900){act=1;}
if(analogRead(A0)>900){act=2;}
if(analogRead(A0)<100){act=3;}
if (!digitalRead(7)){ //站坐切换
delay(20);
if(!digitalRead(7)){
act=4;
}
}
switch (act){
case 0 :
if(p){ stand() ; prewalk0() ; delay( 150 ) ; p=0;}
else move0( 150 ) ;
act=5;
break;
case 1 :
if(p){ stand() ; prewalk1() ; delay( 150 ) ; p=0;}
else move1( 150 ) ;
act=5;
break;
case 2 :
if(p){ stand() ; delay( 150 ) ; p=0;}
else turnLeft( 350 ) ;delay(150);
act=5;
break;
case 3 :
if(p){ stand() ; delay( 150 ) ; p=0;}
else turnRight( 350 ) ;delay(150);
act=5;
break;
case 4 :q=!q;act=5;
break;
default:
delay(100);
if(q){ stand() ; p = 1 ; }
else{ sit(); p = 1 ; }
break;
}
}
}
**如代码所见,四足的前进步态,(左前为1,右前为2,右后为3,左后为4)1,延时,3,小延时,1、3回正且迈出2,延时,4,小延时,2、4回正且迈出1…如此循环。后退步态无异。
左转步态也相似,主要都是一组交叉足先移动,再移动另一组交叉足。
期间试过四五种起始步态,有四足平行,“共”字的起始步态,晃动得很严重,猜测是因为机身较轻,且足底不平(贴了橡皮擦的切片增加摩擦力),还有就是“X”型起始步态,也不理想,最后还是确认了前两足“一”字,后两足八字。其实就是前两足用“工”,后两足用“X”。稳定性表现得最好。
当然还可以有更好的步态,机械结构上也有待改进。本人在此就暂时不深究了。**
1、3D打印的机器人外壳一套
2、Arduino UNO一块,Arduino摇杆模块一枚
3、16路PMW控制板一块
4、12V2A电源一枚
5、7805稳压芯片2枚,2枚散热片(用来并联,因为8个舵机同时工作+主板大约1.5A+的电流),或者别的2A输出的5V稳压芯片
6、小散热风扇,用来冷却7805的散热片
7、9g舵机8个
8、螺丝螺母:
M3*16螺丝4枚,M3防滑螺母4枚
M4*16螺丝4,
M4*25螺丝4,
M4*20螺丝4,M4防滑螺母4,M4螺母8
M3、M4尼龙垫片若干
这个机器人现阶段是为了调试运动性能,算合格了,后面会加入语音识别模块、语言播放模块、传感机械手、wifi模块、打造成一个只能语音控制的机器人。比如直接对话查机票价格、天气等等,以及一些特殊提醒。当然实用性不重要,够酷够炫才是关键。