WALTER - Arduino Photovore 昆虫
组件和用品
| × | 1 | ||||
| × | 3 | ||||
| × | 4 | ||||
| × | 4 | ||||
| × | 5 | ||||
| × | 1 |
必要的工具和机器
| ||||
|
应用和在线服务
|
关于这个项目
[请原谅我的英语]
我真的很喜欢 2 个伺服 arduino 昆虫 的流行设置 在YouTube上。当我看到它时,我总是记得在那个设置成为最受欢迎的很久之前 BEAM 机器人家伙做了什么。由于两个电机之间的角度更好(微核/双核助行器),这些模拟机器人狂热者在步态上做得更好 等)。
然而,在我看来,之前提到的那些看起来都比 VBug1.5 更有活力 (也称为随身听)由光束机器人创始人马克·蒂尔登(Mark Tilden)创建。它使用5个电机,因此具有更高的可操作性。
制作一个简单的 BEAM 机器人并不难,但是对于像我这样的电子新手来说,构建像 VBug1.5 这样复杂的东西可能会令人苦恼。因此,当我决定制作类似 Tilden 的 bug 的东西时,我不得不选择 arduino 平台,这是非工程师最简单的选择(或者在我的情况下,尴尬的是,一个工程师想成为的人)。
结果,我让 Walter ,一个带有 5 个伺服系统的 4 腿 arduino 机器人。你可能想知道,如果我想制作一个看起来栩栩如生的虫子机器人,那为什么我不使用 8 或 12 个伺服系统呢?嗯,我在想一些我可以做的最简单的事情,以获得我可以拥有的最大机动性。我说的是使用大量胶水而不是制作框架。
行为
与许多其他 arduino 机器人一样,Walter 可以使用 HC-SR04 超声波传感器避开障碍物。将角色添加为虫子,Walter 也是 photovore,这意味着他会被光吸引。光电二极管用于检测光。 arduino草图中生成了随机值,让Walter决定什么时候要停下来休息,也可以随机改变他的步态速度(3种速度)。
当我开始时,我打算在 Walter 的每只脚下都有轻触按钮,这样他就会有一个表面传感器。但是电池(智能手机的便携式移动电源)使伺服系统的重量增加了很多。我知道轻触按钮的重量几乎不用担心增加重量,但具有讽刺意味的是,机器人的重量不足以按下倒置的按钮。
我计划用更大的伺服系统制作 Walter 版本 2,然后将这些按钮作为表面传感器。
更多详情
代码
- WALTER.ino
WALTER.inoArduino
/*WALTER - THE 4 LEGGED PHOTOVORE 这个 Arduino 草图是我尝试构建一个名为“WALTER”的 5 伺服四足(4 腿)机器人。为了使用这个草图,您可能需要更改一些值以方便或以适应您自己的硬件设置。查找 (Ctrl + F) 这些标记以轻松搜索可能需要更改的值: - **** :这些标记意味着它们是伺服器的中心位置并且必须校准(您的机器人闲置时腿的药水)。 - *** :这些标记表示 arduino 引脚分配(传感器和伺服器连接到 arduino)。构建机器人时请参考此内容。 - ** :这些标记意味着可以根据您的喜好随意更改值(腿的步长,感知光线/障碍物时转动多少等)。如果您不知道自己在做什么,请保持原样。您可以自担风险使用此草图。在已发布的源代码中编写??重点是,如果您在使用这些代码时发生了不好的事情,我不想承担任何责任。玩得开心!Yohanes Martedi - 2015*/#include// ** **校准舵机的中心角(以微秒为单位,因为我们将使用“xx.writeMicroseconds();”命令)。从 1500.const int ANGLE_mid_Shaft =1520;const int ANGLE_mid_FLeft =1550;const int ANGLE_mid_FRight =1570;const int ANGLE_mid_BLeft =1450;const int ANGLE_mid_BRight =14p0;const int // **设置此值(以微秒为单位)以确定舵机将扫描的宽度(腿的步长)。更大的值意味着更宽的扫描角度。const int ANGLE_res =10; // **设置伺服运动分辨率(以微秒为单位)至少为最小伺服的默认死区宽度(最高分辨率)或更多(更小分辨率)。示例:SG90 伺服死区宽度为 10 微秒。int扫描速度; // 决定舵机扫描速度的变量。int扫描SPEED_Rand[3] ={4, 6, 8}; // **伺服速度(步态速度)将在 3 种模式下随机变化。设置每种模式的速度(以毫秒为单位)。较小的值意味着更快。const int ANGLE_turnMAX =ANGLE_sweep * 1.5; // **设置此值以确定机器人将转向光的最大值。更大的值意味着更大的turn.const int ANGLE_turnNARROW =ANGLE_sweep * 0.25; // **设置此值以确定机器人将在狭窄空间内避开其两侧的物体的最大值。更大的值意味着更大的turn.const int SONAR_sum =3; // 使用的声纳数量.const int PHOTO_sum =4; // 使用的光电二极管数量.int PIN_trig[SONAR_sum] ={13, 11, 8}; // ***设置连接到超声波传感器触发引脚的arduino引脚; {前,左,右}.int PIN_ec[SONAR_sum] ={12, 10, 7}; // ***设置连接到超声波传感器回声引脚的arduino引脚; {前,左,右}.int PIN_PHOTO[PHOTO_sum] ={2, 3, 1, 0}; // ***设置连接到光电二极管的arduino模拟输入引脚; {左前,右前,左后,右后}.const int distRotate =25; // **在机器人通过旋转避开障碍物之前配置机器人与障碍物之间的最小距离(以厘米为单位)。const int distRetreat =10; // **在机器人通过后退避开障碍物之前配置机器人与障碍物之间的最小距离(以厘米为单位)。const int distTurn =20; // **配置机器人与障碍物之间的最小距离(以厘米为单位),然后机器人通过转向避开障碍物。const int counter_gait_max =8; // **配置机器人将采取多少步来避开障碍物(旋转或后退时)。// **配置机器人休息和运行的时间(以毫秒为单位)。const int RUN_time =25000;const int REST_time =3000;// 声纳的 ID:int SONAR_id;const int FRONT =0;const int LEFT =1;const int RIGHT =2;// 光电二极管的 ID:const int FRONT_LEFT =0;const int FRONT_RIGHT =1;const int BACK_LEFT =2;const int BACK_RIGHT =3;// 光电二极管读数的变量:int PHOTO_Front_Left;int PHOTO_Front_Right;int PHOTO_Back_Left;int PHOTO_Back_Right;const int SONAR_TrigSig =10; // 传感器产生超声波所需的触发信号的持续时间(以 S 为单位)(产品已指定,请勿更改此值)。const unsigned long SONAR_MaxEc =50000; // 传感器给出的回波信号的最大持续时间(以 S 为单位)(已由产品指定,请勿更改此值)。const float SOUND_speed =0.034; // 空气中的声速,单位为 S/cm(sciene 已经指定,如果要更改此值,需要 avatar Aang 进行空气弯曲)。int distance[SONAR_sum]; //计算距离的结果。//舵机的D声明:Servo SERVO_shaft;Servo SERVO_front_left;Servo SERVO_front_right;Servo SERVO_back_left;Servo SERVO_back_right;//每个舵机角度的变量:int ANGLE_shaft =ANGLE_mid_Shaft_left; ANGLE_front_right =ANGLE_mid_FRight;int ANGLE_back_left =ANGLE_mid_BLeft;int ANGLE_back_right =ANGLE_mid_BRight;// 中间舵机(轴)的角度操作。const int ANGLE_max_Shaft =ANGLE_mid_Shaft + ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_minsweep ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_sweep ANGLE_sweep 的角度控制每个舵机的角度:int ANGLE_shaft_record;int ANGLE_front_left_record;int ANGLE_front_right_record;int ANGLE_back_left_record;int ANGLE_back_right_record;// 根据光检测舵机角度校正的变量:int LIGHT_left;int LIGHT_right:根据声纳舵机检测角度校正int SONAR_left;int SONAR_right;// 那些东西例如标志、计数器、记录,我总是不确定如何解释。 :(int ANGLE_prev;int flag_shaft_reverse;int flag_transition_rotate;int flag_transition_start =1;int flag_rest =0;int flag_RUN_time =0;introtate_random;int counter_gait;void setup() { // Serial.begin(9600); // 串行。 . 你知道,检查和调试.. SERVO_shaft.attach(2); // ***在arduino上设置水平(轴)舵机的信号引脚。SERVO_front_left.attach(4); // ***设置前左arduino 上舵机的信号引脚。SERVO_front_right.attach(3); // ***在arduino 上设置右前舵机的信号针。SERVO_back_left.attach(6); // ***设置左后舵机的信号针arduino.SERVO_back_right.attach(5); // ***在 arduino 上设置后右舵机的信号引脚。// 在中间角度准备好舵机。SERVO_shaft.writeMicroseconds(ANGLE_mid_Shaft); SERVO_front_left.writeMicroseconds(ANGLE_mid_FLeft); SERVO_front_right.writeMicroseconds(ANGLE_mid_FRight); SERVO_back_left.writeMicroseconds(ANGLE_mid_BLeft); SERVO_back_right.writeMicroseconds(ANGLE_mid_BRight); // 设置引脚s 用于声纳,包括 pinMode 和 value。 for(SONAR_id =0; SONAR_id distRotate) { flag_RUN_time =0; while(flag_RUN_time ==0) { FORWARD(); } } while(distance[FRONT]> distRetreat &&distance[FRONT] <=distRotate) { while(distance[LEFT]> distance[RIGHT]) { ROTATE_LEFT_AVOID();休息; } while(distance[LEFT] =ANGLE_max_Shaft) { ANGLE_prev =ANGLE_shaft; ANGLE_shaft -=ANGLE_res; } else if(ANGLE_prev> ANGLE_shaft &&ANGLE_shaft> ANGLE_min_Shaft) { ANGLE_prev =ANGLE_shaft; ANGLE_shaft -=ANGLE_res; } else if(ANGLE_shaft <=ANGLE_min_Shaft) { ANGLE_prev =ANGLE_shaft; ANGLE_shaft +=ANGLE_res; } SERVO_shaft.writeMicroseconds(ANGLE_shaft);}void SHAFT_REVERSE() { if(ANGLE_prev ANGLE_shaft) { ANGLE_prev =ANGLE_shaft - 1; }}/*================================轴运动结束 ================================*//*======================================过渡 =====================================*/void TRANSITION_GAIT() { ANGLE_front_left_record =ANGLE_front_left; ANGLE_front_right_record =ANGLE_front_right; ANGLE_back_left_record =ANGLE_back_left; ANGLE_back_right_record =ANGLE_back_right; ANGLE_shaft_record =ANGLE_shaft; int 标志 =高;整数计数器 =0;而(标志==高){轴(); LIGHT_left =0; LIGHT_right =0;计数器++; ANGLE_front_left =map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_front_left_record, ANGLE_mid_FLeft); ANGLE_front_right =map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_front_right_record, ANGLE_mid_FRight); ANGLE_back_left =map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_back_left_record, ANGLE_mid_BLeft); ANGLE_back_right =map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_back_right_record, ANGLE_mid_BRight); SERVO_shaft.writeMicroseconds(ANGLE_shaft); SERVO_front_left.writeMicroseconds(ANGLE_front_left); SERVO_front_right.writeMicroseconds(ANGLE_front_right); SERVO_back_left.writeMicroseconds(ANGLE_back_left); SERVO_back_right.writeMicroseconds(ANGLE_back_right); if(counter ==((ANGLE_sweep * 2) / ANGLE_res)) { flag =LOW;开始(); flag_transition_rotate =0; } }}void TRANSITION_START() { if(ANGLE_shaft ==ANGLE_mid_Shaft || (ANGLE_shaft> ANGLE_mid_Shaft &&ANGLE_shaft> ANGLE_prev) || (ANGLE_shaft =ANGLE_mid_Shaft &&ANGLE_prev =ANGLE_mid_Shaft &&ANGLE_prev> ANGLE_shaft) { ANGLE_front_left =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, ((ANGLE_mid_FLeft + ANGLE_valleft) - LARHT_VALLEFT) ANGLE_front_right =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, ((ANGLE_mid_FRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right)); ANGLE_back_left =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, ((ANGLE_mid_BLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left)); ANGLE_back_right =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, ((ANGLE_mid_BRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right)); } else if(ANGLE_shaft ANGLE_shaft) { ANGLE_front_left =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_FLeft + ANGLE_sweep_val) - LIGHT_left), - LIGHT_left); ANGLE_front_right =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_FRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right), ANGLE_mid_FRight); ANGLE_back_left =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_BLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left), ANGLE_mid_BLeft); ANGLE_back_right =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_BRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right), ANGLE_mid_BRight); } else if(ANGLE_shaft =ANGLE_mid_Shaft &&ANGLE_prev =ANGLE_mid_Shaft &&ANGLE_prev> ANGLE_shaft) { ANGLE_front_left =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, (ANGLE_mid_FLeft - ANGLE_sweep); ANGLE_front_right =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, (ANGLE_mid_FRight + ANGLE_sweep_val)); ANGLE_back_left =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, (ANGLE_mid_BLeft + ANGLE_sweep_val)); ANGLE_back_right =map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, (ANGLE_mid_BRight - ANGLE_sweep_val)); } else if(ANGLE_shaft ANGLE_shaft) { ANGLE_front_left =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_FLeft - ANGLE_sweep_val), ANGLE_mid_FLeft ANGLE_front_right =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_FRight + ANGLE_sweep_val), ANGLE_mid_FRight); ANGLE_back_left =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_BLeft + ANGLE_sweep_val), ANGLE_mid_BLeft); ANGLE_back_right =map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_BRight - ANGLE_sweep_val), ANGLE_mid_BRight); } else if(ANGLE_shaft 0.0) { SONAR_distance =SONAR_EcInterval * (SOUND_speed / 2.0);休息; } while(SONAR_EcInterval ==0.0) { SONAR_distance =501.0;休息; } return SONAR_distance;}/*==============================超声读数结束 ==============================*//*======================================光线检测 ====================================*/void LIGHT_COMPARE_EXECUTE() { //PHOTO_FLeft_RAW =analogRead(PIN_PHOTO[FRONT_LEFT]); //PHOTO_FRight_RAW =analogRead(PIN_PHOTO[FRONT_RIGHT]); PHOTO_Front_Left =analogRead(PIN_PHOTO[FRONT_LEFT]); PHOTO_Front_Right =analogRead(PIN_PHOTO[FRONT_RIGHT]); PHOTO_Back_Left =analogRead(PIN_PHOTO[BACK_LEFT]); PHOTO_Back_Right =analogRead(PIN_PHOTO[BACK_RIGHT]); if((PHOTO_Front_Left + PHOTO_Front_Right)>=(PHOTO_Back_Left + PHOTO_Back_Right)) { int LIGHT_Sensitivity =50; if(LIGHT_COMPARE()> LIGHT_Sensitivity) { LIGHT_left =LIGHT_COMPARE(); LIGHT_right =0; } else if(LIGHT_COMPARE() <-LIGHT_Sensitivity) { LIGHT_left =0; LIGHT_right =LIGHT_COMPARE(); } else { LIGHT_left =0; LIGHT_right =0; } } else { if(PHOTO_Back_Left> PHOTO_Back_Right) { LIGHT_right =0; LIGHT_left =ANGLE_turnMAX; } else if(PHOTO_Back_Left PHOTO_Front_Right){ LIGHT_rate =PHOTO_Front_Left; } else if(PHOTO_Front_Right> PHOTO_Front_Left) { LIGHT_rate =PHOTO_Front_Right; } else { // 选择使用一个并在下面注释另一个变量 // LIGHT_rate =PHOTO_Front_Left; LIGHT_rate =PHOTO_Front_Right; } int LIGHT_compareRAW =PHOTO_Front_Left - PHOTO_Front_Right; LIGHT_compareRAW =map(LIGHT_compareRAW, -LIGHT_rate, LIGHT_rate, -ANGLE_turnMAX, ANGLE_turnMAX);; return LIGHT_compareRAW;}/*==================================光检测结束 =================================*//*======================================行为 ========================================*/void RETREAT_AVOID() { counter_gait =0; while(counter_gait <=counter_gait_max) { RETREAT(); }}void ROTATE_LEFT_AVOID() { counter_gait =0;旋转随机 =2; while(counter_gait <=counter_gait_max) { ROTATE_LEFT(); }}void ROTATE_RIGHT_AVOID() { counter_gait =0;旋转随机 =2;而(counter_gait <=counter_gait_max) { ROTATE_RIGHT(); }}void ROTATE_RANDOM_AVOID() {rotate_random =ROTATE_RANDOM();而(旋转随机==0){ ROTATE_LEFT_AVOID(); } while(rotate_random ==1) { ROTATE_RIGHT_AVOID(); }}void SIDE_AVOID() { if(distance[LEFT] <=distTurn &&distance[RIGHT]> distTurn) { LIGHT_left =0; LIGHT_right =0; SONAR_left =0; SONAR_right =-(map(distance[LEFT], 0, distTurn, ANGLE_turnMAX, 0)); } else if(distance[RIGHT] <=distTurn &&distance[LEFT]> distTurn) { LIGHT_left =0; LIGHT_right =0; SONAR_right =0; SONAR_left =map(distance[RIGHT], 0, distTurn, ANGLE_turnMAX, 0); } else if(distance[LEFT] <=distTurn &&distance[RIGHT] <=distTurn) { LIGHT_left =0; LIGHT_right =0;如果(距离[左] <距离[右]){ SONAR_left =0; SONAR_right =-(map(distance[LEFT], 0, distTurn, ANGLE_turnNARROW, 0)); } else if(distance[RIGHT]
示意图
制造工艺