快捷搜索:  汽车  科技

用瓶盖制作毛毛虫的过程(制作一个串联仿生毛毛虫)

用瓶盖制作毛毛虫的过程(制作一个串联仿生毛毛虫)扩展板Basra(兼容Arduino Uno)3.1 电子硬件在这个示例中,我们采用了以下硬件,请大家参考:主控板

1. 运动功能说明

该样机是一款纯关节串联的蠕虫形机器人,可以像虫子一样的上下蠕动前进,样子呈波浪状。

用瓶盖制作毛毛虫的过程(制作一个串联仿生毛毛虫)(1)

2. 结构说明

该样机由5个关节模组串联构成,结构比较单纯。

用瓶盖制作毛毛虫的过程(制作一个串联仿生毛毛虫)(2)

3. 运动功能实现

本样机只需要让5个舵机按照一定的时序,做出波浪形摆动的动作,即可实现蠕动爬行。

舵机和关节模组的控制方法请参考如何驱动模拟舵机【https://www.robotway.com/h-col-129.html】,以及舵机关节模组【https://www.robotway.com/h-col-121.html】

3.1 电子硬件

在这个示例中,我们采用了以下硬件,请大家参考:

主控板

Basra(兼容Arduino Uno)

扩展板

Bigfish2.1

电池

7.4V锂电池

3.2 编写程序

编程环境:Arduino 1.8.19

(1)实现尾部关节运动(Tail_Swing.ino),代码如下:

/*------------------------------------------------------------------------------------ 版权说明:Copyright 2022 Robottime(Beijing) Technology Co. Ltd. All Rights Reserved. Distributed under MIT license.See file LICENSE for detail or copy at https://opensource.org/licenses/MIT by 机器谱 2022-9-14 https://www.robotway.com/ ------------------------------ 实验功能: 实现机器毛毛虫尾部关节运动。 ----------------------------------------------------- 实验接线:尾部关节模组的舵机接D8。 ------------------------------------------------------------------------------------*/ #include <Servo.h> #include <MsTimer2.h> int servoPort[5]={8 3 11 7 4}; //毛毛虫的舵机连接顺序及接口号,从尾巴开始。 Servo myServo[5]; long timeCount; #define DELTATIME 10 void setup() { Serial.begin(9600); for(int i = 0; i < 5; i ) myServo[i].attach(servoPort[i]); MsTimer2::set(DELTATIME Timer); MsTimer2::start(); delay(100); } void loop() { ServoMove(0 60 120 2000); //0号舵机在2000ms内从60°转到120° } void Timer() { timeCount ; } void ServoMove(int which int start int finish long t) { static int a; static long count = 0; static int i = 0; static boolean begin = true; if(begin){ if( ( start - finish ) > 0 ) a = -1; else a = 1; count = timeCount; begin = false; } else{ if( ( timeCount - count ) < (t/DELTATIME) ){ if( ( timeCount - count ) > ( i * (t/DELTATIME) / (abs(start-finish)) ) ){ myServo[which].write( start i * a ); delay(1); i ; Serial.println(start i * a); } } else{ i = 0; begin = true; count = 0; } } }

此段程序之所以看起来那么复杂,是因为它搭建了一个程序框架,在这个框架中,大家可以通过改变参数,来决定哪个舵机运动,以及怎么运动,不需要重写整个程序。

(2)编写并烧录以下程序,它可以让毛毛虫全身的关节一起运动(Body_Swing.ino),代码如下:

/*------------------------------------------------------------------------------------ 版权说明:Copyright 2022 Robottime(Beijing) Technology Co. Ltd. All Rights Reserved. Distributed under MIT license.See file LICENSE for detail or copy at https://opensource.org/licenses/MIT by 机器谱 2022-9-14 https://www.robotway.com/ ------------------------------ 实验功能: 实现机器毛毛虫全身关节运动。 ----------------------------------------------------- 实验接线:从尾巴开始,对应舵机接口依次D8、D3、D11、D7、D4。 ------------------------------------------------------------------------------------*/ #include <Servo.h> #include <MsTimer2.h> int servoPort[5]={8 3 11 7 4}; Servo myServo[5]; long servoCount[5]; boolean begin[5] = {true true true true true}; boolean complete[5] = {false false false false false}; int direct[5] = {1 1 1 1 1}; int delta[5] = {0 0 0 0 0}; long timeCount; #define DELTATIME 10 int up = 30; //关节起始角度 int down = 120; //关节终止角度 int turnTime = 1000; //关节运动时间 String inputString = ""; // a string to hold incoming data boolean stringComplete = false; // whether the string is complete void setup() { Serial.begin(9600); for(int i = 0; i < 5; i ) myServo[i].attach(servoPort[i]); MsTimer2::set(DELTATIME Timer); MsTimer2::start(); delay(100); } void loop() { static int phase[5] = {0 0 0 0 0}; if (stringComplete) { Serial.println(inputString); up = inputString.substring(0 inputString.indexOf(' ')).toInt(); inputString = inputString.substring(inputString.indexOf(' ') 1 inputString.length()); down = inputString.substring(0 inputString.indexOf(' ')).toInt(); turnTime = inputString.substring(inputString.indexOf(' ') 1 inputString.length()).toInt(); Serial.println(up); Serial.println(down); Serial.println(turnTime); inputString = ""; stringComplete = false; } if(phase[0] == 0) if(ServoMove(0 up down turnTime)) phase[0] = 1; if(phase[0] == 1) if(ServoMove(0 down up turnTime)) phase[0] = 0; if(phase[1] == 0) if(ServoMove(1 down up turnTime)) phase[1] = 1; if(phase[1] == 1) if(ServoMove(1 up down turnTime)) phase[1] = 0; if(phase[2] == 0) if(ServoMove(2 up down turnTime)) phase[2] = 1; if(phase[2] == 1) if(ServoMove(2 down up turnTime)) phase[2] = 0; if(phase[3] == 0) if(ServoMove(3 down up turnTime)) phase[3] = 1; if(phase[3] == 1) if(ServoMove(3 up down turnTime)) phase[3] = 0; if(phase[4] == 0) if(ServoMove(4 up down turnTime)) phase[4] = 1; if(phase[4] == 1) if(ServoMove(4 down up turnTime)) phase[4] = 0; } void Timer() { timeCount ; } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); inputString = inChar; if (inChar == '\n') stringComplete = true; } } boolean ServoMove(int which int start int finish long t) { if(begin[which]){ if( ( start - finish ) > 0 ) direct[which] = -1; else direct[which] = 1; servoCount[which] = timeCount; begin[which] = false; complete[which] = false; } else{ if( ( timeCount - servoCount[which] ) < (t/DELTATIME) ){ if( ( timeCount - servoCount[which] ) > ( delta[which] * (t/DELTATIME) / (abs(start-finish)) ) ){ myServo[which].write( start delta[which] * direct[which] ); delay(1); delta[which] ; //Serial.println(start i * a); } } else{ delta[which] = 0; begin[which] = true; servoCount[which] = 0; complete[which] = true; } } return (complete[which]); }

烧录后,打开Serial Monitor,输入up down turnTime的值 可直接改变全部关节的运动参数,例如,输入50 100 2000。

用瓶盖制作毛毛虫的过程(制作一个串联仿生毛毛虫)(3)

关节的运动状态会实时发生变化。其中50代表摆动的起始角度50°,100代表摆动的终止角度100°,2000代表运动持续时间是2000毫秒。

(2) 上一例程中,机器毛毛虫相邻关节的运动相位差为180°,根据样机的运动姿态分析,各个关节的运动相位差为90°左右的时候运动效应该比较好。

将相邻关节的运动相位差调整为90°(Worm_Go.ino),代码如下:

/*------------------------------------------------------------------------------------ 版权说明:Copyright 2022 Robottime(Beijing) Technology Co. Ltd. All Rights Reserved. Distributed under MIT license.See file LICENSE for detail or copy at https://opensource.org/licenses/MIT by 机器谱 2022-9-14 https://www.robotway.com/ ------------------------------ 实验功能: 实现机器毛毛虫向前蠕动爬行。 ----------------------------------------------------- 实验接线:从尾巴开始,对应舵机接口依次D8、D3、D11、D7、D4。 ------------------------------------------------------------------------------------*/ #include <Servo.h> #include <MsTimer2.h> int servoPort[5]={8 3 11 7 4}; Servo myServo[5]; long servoCount[5]; boolean begin[5] = {true true true true true}; boolean complete[5] = {false false false false false}; int direct[5] = {1 1 1 1 1}; int delta[5] = {0 0 0 0 0}; long timeCount; #define DELTATIME 10 int up = 30; int down = 120; int turnTime = 1000; String inputString = ""; // a string to hold incoming data boolean stringComplete = false; // whether the string is complete void setup() { Serial.begin(9600); for(int i = 0; i < 5; i ) myServo[i].attach(servoPort[i]); MsTimer2::set(DELTATIME Timer); MsTimer2::start(); delay(100); } void loop() { static int phase[5] = {0 0 0 0 0}; if (stringComplete) { Serial.println(inputString); up = inputString.substring(0 inputString.indexOf(' ')).toInt(); inputString = inputString.substring(inputString.indexOf(' ') 1 inputString.length()); down = inputString.substring(0 inputString.indexOf(' ')).toInt(); turnTime = inputString.substring(inputString.indexOf(' ') 1 inputString.length()).toInt(); Serial.println(up); Serial.println(down); Serial.println(turnTime); inputString = ""; stringComplete = false; } if(phase[0] == 0) if(ServoMove(0 up down turnTime)) phase[0] = 1; if(phase[0] == 1) if(ServoMove(0 down up turnTime)) phase[0] = 0; if(servoCount[0]>0 && (timeCount - servoCount[0])>(turnTime/(4*DELTATIME))){ if(phase[1] == 0) if(ServoMove(1 up down turnTime)) phase[1] = 1; if(phase[1] == 1) if(ServoMove(1 down up turnTime)) phase[1] = 0; } if(servoCount[1]>0 && (timeCount - servoCount[1])>(turnTime/(4*DELTATIME))){ if(phase[2] == 0) if(ServoMove(2 up down turnTime)) phase[2] = 1; if(phase[2] == 1) if(ServoMove(2 down up turnTime)) phase[2] = 0; } if(servoCount[2]>0 && (timeCount - servoCount[2])>(turnTime/(4*DELTATIME))){ if(phase[3] == 0) if(ServoMove(3 up down turnTime)) phase[3] = 1; if(phase[3] == 1) if(ServoMove(3 down up turnTime)) phase[3] = 0; } if(servoCount[3]>0 && (timeCount - servoCount[3])>(turnTime/(4*DELTATIME))){ if(phase[4] == 0) if(ServoMove(4 up down turnTime)) phase[4] = 1; if(phase[4] == 1) if(ServoMove(4 down up turnTime)) phase[4] = 0; } } void Timer() { timeCount ; } void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); inputString = inChar; if (inChar == '\n') stringComplete = true; } } boolean ServoMove(int which int start int finish long t) { if(begin[which]){ if( ( start - finish ) > 0 ) direct[which] = -1; else direct[which] = 1; servoCount[which] = timeCount; begin[which] = false; complete[which] = false; } else{ if( ( timeCount - servoCount[which] ) < (t/DELTATIME) ){ if( ( timeCount - servoCount[which] ) > ( delta[which] * (t/DELTATIME) / (abs(start-finish)) ) ){ myServo[which].write( start delta[which] * direct[which] ); delay(1); delta[which] ; //Serial.println(start i * a); } } else{ delta[which] = 0; begin[which] = true; //servoCount[which] = 0; complete[which] = true; } } return (complete[which]); }

烧录后,打开Serial Monitor,输入up down turnTime的值,并实时观察运动变化。你可以通过这种方法调整机器人的运动姿态,直至对爬行效果满意为止。

4. 扩展样机

本样机没有设计左右摆动的结构,因此不能左右转向,有兴趣的朋友可以尝试为其加上左右摆动的结构,让它的运动方式更加丰富。

5. 资料下载

资料内容:

①样机3D文件

②样机例程源代码

​资料下载地址:https://www.robotway.com/h-col-149.html

猜您喜欢: