资讯详情

干货|手把手教你自制六足仿生机器人

3811d4b095c8855ff170f71162553406.png

:大一失败后,我决定暂时停止项目的开发,先学习嵌入式开发的基础知识,然后在将来有能力的时候独立完成六足机器人。幸运的是,当我的本科课程即将结束时,我已经掌握了足够的知识来完成困扰我很长时间的机器人项目,所以我花了几周的时间来完成这个六脚机器人,这是我自己的愿望。

一、前言

这个六足机器人是我大四做的,也是我本科生涯的最后一个个人项目。至于为什么要做六足机器人,要从高考后说起:刚考完的时候一直想做一些有趣的事情,直到有一天发现了一个叫,它记录了很多如何使用它PVC制作简单机器人教程的材料之一叫做PVC六足机昆虫的机器人彻底震惊了我。看完教程,我下定决心做一个类似的六足机器人,就从懒猫侠的前辈那里买了六足机器人套件(目前应该已经绝版了),打算按照提供的教程完成自己的六足机器人。但无奈当时的我所掌握的知识太少,什么单片机、串口通信、舵机PWM、我不懂电源管理、传感器、舵机控制板等,尤其是机械结构。所以大一的时候,我也开了个玩笑:用硬纸板做六脚机器人的四肢。舵机安装通电测试后,我看着舵机振动下的纸板六脚不断解体。。。。

二、概述

六足仿生机器人是一种具有18个关节自由度的迷你多足机器人,可实现红外遥控、超声波避障等基本功能。机器人的硬件核心是Arduino Nano,并通过串口通信与24路舵机控制板进行数据交互,间接完成对所有舵机旋转角度的精确控制,最终使机器人。当然,这个机器人项目的软件仍然是开源的,具体代码可以来自我GitHub在仓库上获得。

三、制作

六足机器人的整个生产过程主要分为机械和电子两部分。因为教程中每一步的图片都很清晰,机械并没有花费我太多的时间和精力。电子部分都是我自己设计的。虽然原理并不难,但根据机器人的机械结构选择孔板的放置位置,完成电子元件的布局和焊接确实费力,有时如果处理不好返工,但幸运的是在焊接电路规划之前,所以电路部分生产顺利。

在下一篇文章中,我将尽可能详细地解释机器人生产过程中的一些具体步骤和细节。如果您对机器人的原理和最终效果更感兴趣,您可以跳过本节中的直接阅读原理和效果章节。

3.1 机械

六足小腿

如下图所示,六足的小腿主要由两部分组成PVC材料的四肢是叠加的,关节是9G金属齿舵机只需要两个自攻螺钉PVC四肢牢牢固定在舵机上,以确保六足小腿在接触地面时有足够的力量支撑整个身体。

因为它是一个六英尺的机器人,所以同样结构的小腿应该再做五条。注:机器人的身体每侧有三条小腿,左右对称,因此在组装时注意四肢和舵机的安装位置,以确保结构对称,不能安装相反。

六足大腿

六足大腿的关节结构比之前介绍的小腿关节稍微复杂一些,因为大腿的关节包含了机器人上下运动和前后运动,所以需要两个舵机来实现。如下图所示,我们首先用螺钉将舵机固定在方形关节肢体中。

然后我们需要重复上述安装步骤,然后制作六个类似的肢体结构。但在生产过程中,也要注意机器人左右两侧三个肢体结构的对称性。

然后我们需要将六个舵机插入以前预留的肢体空槽中,确保每组两个舵机垂直于位置,即舵机圆形旋转轴的方向应在下图中一前一上。

接下来,安装六足大腿关节的固定板,并将固定板卡在下图中舵机前部的圆形旋转轴上。顾名思义,固定板是用来固定的,主要是为了防止两个舵机因足体振动而相互偏移。

最后,每组关节用两条塑料扎带进一步加固。一个穿过固定板上方,起到紧固定板的作用,另一个穿过关节侧面的小孔固定结构。

六足大腿由两条组成PVC材料的矩形连杆地看出,每个连杆的左右两侧都安装了配套的舵盘,主要用于连接六脚小腿关节和大腿关节。

六足足体

如下图所示,使用螺钉连接六对小腿和大腿肢体。虽然拧紧螺钉本身并不困难,但在哪个位置用螺钉固定舵机仍有规定:,这样做的目的是让所有的舵机都有最合适的运动范围,以防止机器人在移动时不对称地移动。至于如何让舵机回到中点,一种方法是使用现成的舵机调试板,只要移动旋钮可以调整舵机的位置;另一种是编写Arduino程序,让舵机在上电后自动中。我用的是第二种方法,感觉效果不错。

接下来,我们将在顶部的身体上安装所有的六英尺足。同样,在安装前,确保需要连接的固定舵机已回到中点,并提前规定机器人头部的哪一侧,机器人尾部的哪一端,安装时不要安装脚。

如图所示,我们首先可以找到一个稍微高一点的物体来抬高机器人的顶部,然后用绑带依次绑定每个脚的三个舵线,这不仅看起来更漂亮,而且便于以后的布置和连接,,毕竟大学在机器人基地的时候,亲身经历过机械臂移动过程中电机线被撕断的悲剧。

最后,我们只需要用扎带将锂电池固定在底部身体的尾部,然后分别引出供电线和充电线,然后按顺序将所有扎好的舵机线插入身体,用螺丝拧紧顶部和底部的两个身体(因为这部分没有拍照,所以用文字描述orz)。

3.2 电子

电源管理

下图是机器人的电源管理模块。电源管理模块主要包含电源、降压电路和控制电路等,具体的原理部分请看下面原理中的电源管理章节。

下图是电源管理模块的背面。为了保持焊接后的电路整洁美观,我尽量使用锡接线来完成各部件的电气连接,而传统的飞线用于无法接线的地方。虽然锡接线的优点很明显,但其缺点也很突出:一个是焊料的浪费,另一个容易短路,短路问题对机器人的影响很严重,我记得我不小心把电源管理模块放在六脚机器人的顶部,让我没想到的是固定身体螺钉头卡在电路背面电源正负锡接线中间,结果可以想象。

因此,在电力测试前,我们应该使用通用表对焊接电路进行短路测试,必须确保电路板上没有多余的焊料残留物,对于锡接线焊接电路板,不让其背面直接接触潜在的导电介质,可以使用铜柱板高度或热熔胶覆盖板背面,以防止短路问题。

在确保电路没有潜在的短路问题后,可以像下图所示的那样测试电路模块。测试主要测试电源降压是否达到预期值,开关开关逻辑是否正确。

控制单元

下图是机器人控制单元模块。控制单元模块主要由控制单元模块组成Arduino Nano控制板、HMC58883L电子罗盘传感器,MPU惯性测量传感器6050(图中底座未插入),HC-SR04超声声波传感器和红外接收管组成。为了方便模块出现问题时更换,我在孔板上焊接了一些母底座,这样模块就可以直接插入母底座,拆卸非常方便。另外,详细介绍电路原理可以阅读以下原理章节。

下图是控制单元模块的背面。就像上面介绍的电源管理模块一样,我仍然使用锡接线 飞线焊接元件。由于电气连接较多,焊接后应对电路进行更全面、更仔细的检查。

如下图所示,因为我的Arduino Nano控制板的USB在之前的寻光车实验中,转串口因短路问题被烧毁,所以我专门使用它Arduino最小系统板烧写Bootloader的USBtinyISP编程器下载程序。经过测试,所有模块都可以正常工作,所以下一步的工作是组装所有的机器人,然后编写和调试代码。

四、原理

4.1 硬件

以下是该仿生六足机器人的硬件系统连接图:

从上图可以看出,六足机器人的硬件系统主要由舵机控制、电源管理、核心控制、数据感知和数据通信五部分组成。接下来,详细介绍:

舵机控制

本项目六足机器人配备的舵机具体型号为YZW Y09G,由于舵机内部电机减速齿轮组采用金属材料制成,其价格高于常见的辉盛SG90塑料齿舵机比较贵,但是性能相当出色。舵机标准输入电压范围为4.8v~6.0v(电压略大于6v没问题),扭矩范围在1.3kg/cm~1.6kg/cm经过测试,18个舵机的扭矩基本上可以满足支撑机器人身体和锂电池的需要。当然,由于定位精度有限,舵机会存在控制死区问题。我的解决办法主要是通过软件补差来消除机械结构上的误差,使机器人能够尽可能准确地达到预定的目标位置。

舵机控制板,顾名思义,是一种可以用来控制多个舵机的电路板,因为传统的单片机通过编写程序输出多路PWM对于大多数机器人爱好者来说,控制信号是复杂的,所以会有专家MCU舵机控制板与相关外围电路封装一起开发。另外,舵机控制板一般都有PC端部调试软件,只要在建立串口通信的前提下拖动软件界面上的滑块,就能准确实时地控制舵机的旋转角度,并将调试动作组合在一起,形成动作组,下载到舵机控制板的芯片中进行保存通过串口对其进行调用奠定基础。本项目六足机器人使用的是懒猫侠早期开发的一款24路舵机控制板,具体使用方法见24路舵机控制板板使用说明。

电源管理应该算是机器人硬件控制系统里除了核心主控之外最重要的模块了,毕竟传感器坏了机器人还能够四处移动,但是电源部分坏了的话机器人可就只是一个静止的模型了。由于本项目六足机器人采用十八个舵机作为关节执行器,所以尽管9G舵机的耗电量相对标准舵机要小很多,但是十八个舵机加起来所需要的电流大小还是相当惊人的,因此经过一段时间的考量,我最终选择了一款参数为7.4v850mAh的锂电池组作为机器人的电源,其电能满足六足机器人的动力需求。

除了锂电池电源之外,从上面的硬件系统连接图中还可以看到有两个降压电路,其中一个降压电路使用L2596 DC-DC模块将一路电源的电压降到标准的5V,用于给Arduino Nano主控制板供电,而另一路使用的是D25XB80大功率整流桥,它拥有标称800V的最大逆向电压和25A的额定前向电流,在锂电池组充满电的情况下(标称7.4v的锂电池组充满电的电压大概在8.4v左右),连接一片D25XB80可以使电压整体降到大概6.9v,经测试给24路舵机控制板和18个舵机供电是没有问题的。

最后为了方便控制锂电池电源的输入和降压后电源的输出,我并联连接了三个开关,并在并联支路中分别加入了三个LED灯用作电源闭合或断开的显示。关于电源管理的其他内容,大家可以参考一下懒猫侠写的六足机器人动力的分析 这篇博文。

核心主控主要负责分析传感器反馈回来的数据,然后给舵机控制板发出动作指令,间接驱动舵机运行到指定角度。在本项目中我使用的核心主控为Arduino Nano,它体型较小,且拥有非常丰富的开发教程和器件驱动库,很容易上手。

数据感知模块主要包括HC-04超声波测距传感器、HMC5883L电子罗盘传感器、MPU6050惯性测量传感器和红外接收管,其中超声波测距传感器用来帮助六足机器人避开其正前方的障碍物,而红外接收管则和常见的迷你红外遥控器一同构成了整个六足机器人的遥控系统,红外接收管能够接收经过38kHz载频二次调制生成的红外信号,并将解码后的数据发送给Arduino Nano主控进行相关处理。HMC58883L和MPU6050这两个传感器主要用于六足机器人的运动感知,通过采集它们的数据并进行简单的融合处理便能得到机器人在空间中的位置关系,从而为之后修正机器人在移动过程中的路径偏差提供数据上的保障。不过由于当时开发时间有限,所以这一部分暂未涉及。

数据通信包括红外通信、串口通信和蓝牙通信三部分。其中,红外通信在上面的数据感知部分已经进行过简要的介绍了,即采用NEC的编码格式将数据进行相应的编码或解码,并通过红外线的方式完成遥控指令数据的传输;串口通信则主要用在核心主控和舵机控制板之间,根据舵机控制板所规定的数据格式,主控能够发送指令来控制一个舵机或多个舵机旋转到指定的位置;最后的蓝牙通信可以使PC端上的软件与舵机控制板之间建立起无线连接,方便六足机器人动作的调试。

4.2 软件

核心类库

该头文件定义了HexapodBionicRobot类,里面声明了机器人避障、处理红外编码信息、处理超声波距离、获取红外编码信息、获取超声波距离和移动机器人躯体等核心函数。

#ifndef HEXAPOD_BIONIC_ROBOT_H
#define HEXAPOD_BIONIC_ROBOT_H

#include <Arduino.h>
#include <IRremote.h>

#define PIN_IR      2
#define PIN_TX      3
#define PIN_RX      4
#define PIN_TRIG    5
#define PIN_ECHO    6
#define PIN_LED     13
#define DIR_INIT    1
#define DIR_STOP    1
#define DIR_FRONT   2
#define DIR_BACK    3
#define DIR_LEFT    4
#define DIR_RIGHT   5
#define MODE_REMOTE 25
#define MODE_AUTO   26
#define RADIX       10
#define RUNTIME     2400
#define TIMEOUT     30000

class HexapodBionicRobot
{
public:
    HexapodBionicRobot(IRrecv *ir_receiver, decode_results *ir_results);
    void avoidFrontObstacle(void);
    void handleInfraredInformation(void);
    void handleUltrasonicDistance(void);
    void moveRobotBody(uint8_t direction, uint8_t times);
    uint32_t getInfraredInformation(void);
    float getUltrasonicDistance(void);
private:
    int             mode_flag_;
    float           duration_;
    float           distance_;
    IRrecv         *ir_receiver_;
    decode_results *ir_results_;
};

#endif // HEXAPOD_BIONIC_ROBOT_H

该源文件实现了HexapodBionicRobot类里面所有已经声明的函数,其中getInfraredInformation()函数调用了官方的IRremote库,可以实时获取红外遥控器所发送的红外编码,而handleInfraredInformation()函数则会将获取到的红外编码与已经定义好的进行比对,若符合则跳转入相应的代码块进行处理(机器人前后左右的移动,以及遥控模式或自动模式切换等),当然程序也会通过调用avoidFrontObstacle()函数来判断是否在遥控六足机器人移动的过程中,机器人前方的障碍物距离躯体较近,若距离小于事先设定的阈值,机器人便会自动后退或停止以进行避让。

#include "hexapod_bionic_robot.h"

#define DEBUG 1

HexapodBionicRobot::HexapodBionicRobot(IRrecv *ir_recviver,
                                       decode_results *ir_results)
    : ir_receiver_(ir_recviver),
      ir_results_(ir_results)
{
    pinMode(PIN_LED, OUTPUT);
    pinMode(PIN_TRIG, OUTPUT);
    pinMode(PIN_ECHO, INPUT);

    mode_flag_ = MODE_REMOTE;

    duration_ = 0.0;
    distance_ = 0.0;
}

void HexapodBionicRobot::avoidFrontObstacle(void)
{
    float distance = getUltrasonicDistance();
    Serial.println(distance);

    if (distance == false) {
        return ;
    }
    else if (distance <= 2.5) {
        moveRobotBody(DIR_STOP, 2);
    }
    else if (distance <= 5.0) {
        moveRobotBody(DIR_BACK, 2);
    }
}

void HexapodBionicRobot::handleUltrasonicDistance(void)
{
    float distance = getUltrasonicDistance();

    if (distance == false) {
        return ;
    }
    else if (distance <= 5.0) {
        digitalWrite(PIN_LED, HIGH);
#if DEBUG
        Serial.println("Warning! Distance is too close!!!");
#endif
    }
    else {
        digitalWrite(PIN_LED, LOW);
    }
#if DEBUG
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println("cm");
#endif
    delay(100);
}

void HexapodBionicRobot::handleInfraredInformation(void)
{
    float distance = 0.0;
    uint32_t ir_results = getInfraredInformation();

    if (ir_results == false) {
        return ;
    }
    else {
#if DEBUG
        Serial.print("Infrared code: ");
        Serial.println(ir_results, HEX);
#endif
        if (ir_results == 0XFF629D) {
            mode_flag_ = MODE_REMOTE;
        }
        else if (ir_results == 0XFFE21D) {
            mode_flag_ = MODE_AUTO;
        }

        if (mode_flag_ == MODE_REMOTE) {
            digitalWrite(PIN_LED, LOW);
            if (ir_results == 0xFF02FD) {
                moveRobotBody(DIR_FRONT, 2);
                delay(RUNTIME);
            }
            else if (ir_results == 0xFF9867) {
                moveRobotBody(DIR_BACK, 2);
                delay(RUNTIME);
            }
            else if (ir_results == 0xFFE01F) {
                moveRobotBody(DIR_LEFT, 2);
                delay(RUNTIME);
            }
            else if (ir_results == 0xFF906f) {
                moveRobotBody(DIR_RIGHT, 2);
                delay(RUNTIME);
            }
            else if (ir_results == 0xFFA857) {
                moveRobotBody(DIR_STOP, 2);
                delay(RUNTIME);
            }
            avoidFrontObstacle();
        }
        else if (mode_flag_ == MODE_AUTO) {
            digitalWrite(PIN_LED, HIGH);
            while (ir_results != 0XFF629D) {
                ir_results = getInfraredInformation();
                moveRobotBody(DIR_FRONT, 2);
                delay(RUNTIME);
                avoidFrontObstacle();
            }
            mode_flag_ = MODE_REMOTE;
        }
    }
}

void HexapodBionicRobot::moveRobotBody(uint8_t direction, uint8_t times)
{
    char string_direction[5];
    char string_times[5];

    itoa(direction, string_direction, RADIX);
    itoa(times, string_times, RADIX);

    Serial.print("#");
    Serial.print(string_direction);
    Serial.print("G");
    Serial.print(string_times);
    Serial.println("C");
}

uint32_t HexapodBionicRobot::getInfraredInformation(void)
{
    if (ir_receiver_->decode(ir_results_)) {
        ir_receiver_->resume();
        return ir_results_->value;
    }
    else {
        return false;
    }
}

float HexapodBionicRobot::getUltrasonicDistance(void)
{
    duration_ = 0.0;
    distance_ = 0.0;

    digitalWrite(PIN_TRIG, LOW);
    delayMicroseconds(10);
    digitalWrite(PIN_TRIG, HIGH);
    delayMicroseconds(10);
    digitalWrite(PIN_TRIG, LOW);

    duration_ = pulseIn(PIN_ECHO, HIGH, TIMEOUT);

    if (duration_ == 0.0) {
        return false;
    }
    else {
        distance_ = duration_ * 0.017;
        return distance_;
    }
}

测试代码

该测试代码的原理非常简单,首先setup()函数会以115200的波特率初始化并打开串口,然后Arduino Nano会向串口发送#1G2C(1号动作组循环运行2次)让六足机器人站立起来,紧接着程序会使能红外接收管,让其可以接收遥控器发送的红外编码。等初始化结束后,主程序会跳转到loop()函数执行HexapodBionicRobot类对象的handleInfraredInformation()函数完成红外遥控以及超声波避障等功能。

#include <IRremote.h>
#include <hexapod_bionic_robot.h>

IRrecv         g_ir_receiver(PIN_IR);
decode_results g_ir_results;

void setup()
{
    Serial.begin(115200);
    Serial.println("#1G2C");
    g_ir_receiver.enableIRIn();
}

void loop()
{
    HexapodBionicRobot hexapod_bionic_robot(&g_ir_receiver, &g_ir_results);
    hexapod_bionic_robot.handleInfraredInformation();
}

五、成果

以下是制作完成后的成果图和测试视频:

六、总结

回想起当初,自己就是看了六足机器昆虫-你的下一个足式移动机器人这篇教程才开始迷上六足机器人的,没想到大四快毕业的时候自己能有机会完成这个属于自己的六足仿生机器人,说实话当看到六足机器人第一次从团身状态下依靠自己的力量站立起来时,我的内心是无比激动的,尽管由于舵机的力矩偏小导致机器人的足体在支撑地面时会有轻微吱吱的抖动,但是得益于十八个关节自由度,六足机器人可以做出很多机器人都无法做出的复杂动作,我想这也许就是多足机器人的魅力所在吧!

不过话说回来,对于机器人初学者来说,制作一个六足机器人的难度相较于轮式机器人还是非常大的,而且投入的时间和资金成本也比较多。如果你的动手能力和技术水平足够强,且跟我一样认为六足机器人非常酷的话,你也可以尝试去做一台属于自己的六足机器人并为它扩展更多有意思的功能(比如我加入了MPU6050和HMC5883L模块来做机器人运动感知与矫正,可惜因时间有限没能实现)。最后我总结一下能成功自制六足机器人所需要的三个关键因素:

文章作者:缪宇飏,myyerrol  转载于:https://myyerrol.io/zh-cn/2018/05/21/diy_robots_2_hexapod_bionic_robot/

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「」获取学习资料网盘链接。

标签: 热熔胶传感器固定式侧臂的电子卡连接器25a电线连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台