基于Arduino uno单片机的仿生螃蟹制作

       最近帮朋友制作了一个小项目——仿生螃蟹。该项目具有俩个模式,一个是自动运行模式,一个是遥控模式。经过沟通,发现项目对于遥控的要求不高,于是推荐他们整体使用了红外遥控,毕竟红外遥控成本更低,开发上也比较省事(毕竟是朋友,而且项目的难度很简单,经费方面你们懂的)。

        首先来介绍一下项目的使用的硬件。

综合项目的要求,包含传感器较少,对于数据的处理量不大,所以选择易于开发的Arduino单片机。一开始的时候,准备使用Arduino nano单片机,nano型号小巧,比较符合要求,后来发现,通过nano控制6个舵机,2个电机有点困难,于是使用了Arduino uno单片机。

       其余硬件非常普通,6个舵机,分别控制仿生螃蟹臂的各个关节运动,通过2个电机控制腿的运行,至于8个腿直接是如何连接的,俩个电机如何实现8条腿的控制,这个需要找机械方面专业人员进行解读,本文只说程序方面。6个舵机、2个电机的供电是无法使用板子进行供电,所以做了一块电源板,电源板由7V电池直接供电。电机通过L298N直接控制。

       总结一下,硬件清单如下:(1)arduino uno开发板一块(2)L298N驱动板一块(3)电源板一块(4)舵机6个(5)电机2个。

        通过上面的内容,对硬件有了一个基本了解,接下来进入我们的正题。

        首先介绍一下我的开发环境,这里使用的是VSCode安装相关插件来开发的,个人感觉,使用ArduinoIDE开发少量代码还行,代码较多的,ArduinoIDE的布局看起来确实不舒服(毕竟我是搞java的,javaide看多了,突然看ArduinoIDE有点不习惯),所以配置了vscode来使用。Vscode开发页面如图1所示,ArduinoIDE如图2所示。当然,还是看个人习惯,怎么舒服怎么来。

图1 vscode

图2 arduino ide

        首先,我们来看一下项目的结构,如图3 项目结构所示。

图3 目结构

        第一个.vscode大家无需管它,这个是使用Vscode创建项目后,插件给我们创建的俩个json文件,主要包含一些配置信息。下面才是项目的核心内容。

       fspx.ino文件是用于Arduino编译的,大家熟悉的LOOP函数就在这,为了使项目代码结构明了,耦合度底,通过hwjm、motive、yk三个文件来对红外解编码、运动控制、遥控进行操作,这样有俩点好处,(1)条理明晰(2)有问题容易更改。

 while (hwjm_ms==0)

    {

        hwjm_ms();

    }

    switch (msjm)

    {

    case 1:

        while (1)

        {

            zyms();

        }

        break;

   

    case 2:

        while (1)

        {

            ykms();

        }

            break;

    }

       以上是主程序代码,只有10几行,某个功能出现问题,只需到某个功能函数里面进行更改即可,无需到处找。

       首先,我们来看一下红外遥控。

      红外遥控是有俩个组件,分别是红外发射器与红外接受装置,红外发射器通过发送指令,红外接受装置按照相关协议进行解码,从而读取内容。通过控制系统识别相关指令,执行相关代码。如果我们拿到陌生的红外遥控的话,我们可以通过以下代码,来实现红外编码的读取。

#include "IRremote.h"

IRrecv irrecv(hw);

decode_results jg;

void setup() {

Serial.begin(9600);

irrecv.enableIRIn();

}

void loop() {

Serial.println(irrecv.decode(&jg));

}

        在本次项目中,就是通过这种模式去读取到每个按键的红外编码。

static int ydjm=0;

static int msjm=0;

       在红外编码的.h文件中,创建了俩个全局变量,这样,在其他文件中将无法创建同名变量,并且只需导入相关头文件,即可实现变量名称的更改,至于这俩个变量的使用,在后文中解释。

enum jm{

    FF30CF, FF18E7, FF7A85, FF10EF,

    FF5AA5, FF629D, FF4AB5, FFE21D,

    FFA857, FF906F, FF0C30, FFB04F,

    FF02FD, FFC23D, FFA25D, FF22DD,

    FFE01F, FF6897

}jm2;

//依次为红外遥控数字1、2、3、4、6、Mode、8、静音、vol-\vol+、RPT\U/SD、<<、>>,开关建、暂停建、EQ、0

       红外解码通过switch case实现,switch后的条件只能使用枚举或整数。上面是枚举内容,如果你的红外遥控器与图4的一样,可以直接使用,节省时间(至于为什么没有按照遥控顺序来,当然是写的过程中,发现之前设计的按键不太符合使用习惯,进行了更改).

图4 红外遥控

 

       在这里,可以将枚举更改为String类型的数组,但是,更改后只能使用if-else if-else来实现解码功能,但是在这里不推荐。

       解释一下原因。如果我们程序的分支很少,那么if-else if分支语句是优先选择。但是如果是分支较多,switch的运行速度比if分支的要快。Switch会为每一个创建一个指针空间,直接根据指针进行读取。而if分支语句只能从头读取,直到找到。既然有指针,那么其就需要占用一定的空间,所以如果分支很少,大可不必使用,浪费空间。这里举个例子:假如你朋友邀请你到他家玩,你朋友告诉你他家在5楼,如果5楼只有俩户人家,你只需要随机敲一户的门即可知道你朋友家在哪,而如果5楼有20户,显然无法直接敲开,只能找物业或管理层去查询。前者相对于if-else if ,你只有实验一次即可,效率高。但是,20户,你至少要实验一次,而且一次就是你朋友加到概率是5%,显然效率不高,如果遇到暴脾气的户主,少不了一顿批。

       在motive文件中,主要定义了各种运动模式,向左,向右(一开始是向前向后,后来想起,螃蟹只能横着走)、螃蟹臂的运动、螃蟹钳的运动。

#include "motive.h"

#include "Arduino.h"

#include "hwjm.h"


// 定义舵机对象

static Servo L0;

static Servo L1;

static Servo R0;

static Servo R1;

static Servo M0;

static Servo M1;


#define ang 5//此处数值决定各关节打开的角度,更改只需更改数字



//  各模块子函数

//  运动

void zy() {

    digitalWrite(in1, LOW);

    digitalWrite(in2, HIGH);



    digitalWrite(in3, LOW);

    digitalWrite(in4, HIGH);

   

    ydjm=0;

}

       这里提示大家,如果使用分模块开发,一定调用Arduino.h库,这样才可以使用一些arduino单片机的关键字,如digitalWrite的使用,否则会报错(不要问我怎么知道的)。

        在本部分,通过宏定义定义了一个ang,至于这个的作用,后面代码就可以明白了。

        这里首先列举一个左移的代码。左移我们控制的是螃蟹的移动,而螃蟹的移动是通过电机实现的,很多人会想到使用PWM控制,没错,如果只有左移,pwm可以完美解决,但是你没有见过只会向左走的螃蟹吧,所以还需要考虑右移。PWM无论如何更改占空比,都无法使得电机反转,只能更改转速(也就是螃蟹的移动速度),所以我们引入了L298N,通过对IN1、IN2、IN3、IN4给予不同电平而实现电流的反转,实现左右自由移动。至于结尾为什么有ydjm=0,大家可以联合上下文,猜一下。这里我们并没有对使能端进行使能,因为我们不需要调节螃蟹运动的速度。

//螃蟹左夹子,默认为舵机的获得角度为0-45度,0度为钳子完全夹住,45度全开

void xj_L1_K() {

     

    if (L1.read() > 45) {

        L1.write(45);

    }

    else {

        L1.write(L1.read()+ang);

    }

    ydjm=0;

}

        上面列举的这几行代码,大家通过注释应该已经明白它的功能了,这里主要说明俩个问题,首先是螃蟹钳子的控制。大家都吃过螃蟹,螃蟹的钳子开合是有限制的,不是任意角度的控制,所以,我在这里增加了角度控制,在这里,大家应该是看到了ang这个变量,也就是在开始时候,那个宏定义。我们可以想一下,不管是螃蟹的钳子还是螃蟹臂的运动,都是慢慢增加的,不是一下到位的,你在遥控的时候,如果只按了一下,结果直接一直张开,直到机械结构不在允许运动才停止,显然不符合我们的逻辑与实际功能。ang定义了这些机构每次运行的角度(也就是舵机转动角度),因为每一个机构都需要,但是如果需要调整,那不费老半天劲了,所以定义一个宏变量,只需更改一个数字,全局更改,如果有特殊的,只需特殊处理即可。其次,说明一下,这里为了保户舵机与机械外壳,大家可以增加一个蜂鸣器,当超过使用范围后,直接报警,提示操作者。当然,这个项目空间有限,只能放弃了。

void hwjm_ms(){

    char jm1=irrecv.decode(&jg);



    switch (jm1)

        {  

            //自由运动模式

            case FF30CF:

                msjm=1;

                break;

            //遥控模式

            case FF7A85:

                msjm=2;

                break;

        }

}

        这段代码是模式确认的一段,大家看到了我们之前代码中的全局变量了,我们通过解码,来获取相关指令,再对全局变量命名,从而在yk函数里面直接对数字进行对比,再寻找相关功能。解释一下,为什么要解码转变为数字,你想,如果你运行结束后,下次还要调用,但是在判断条件里面,都是固定的,那么我们只能实现单次遥控,只能单次运动,这不是开发了一只傻螃蟹。所以,这也可以解释,上面左移程序里面有一个赋值为0的步骤。

void loop() {



    while (hwjm_ms==0)

    {

        hwjm_ms();

    }

   



    switch (msjm)

    {

    case 1:

        while (1)

        {

            zyms();

        }

        break;

   

    case 2:

        while (1)

        {

            ykms();

        }

            break;

    }

     

}

        这段代码就是loop函数代码,看着很短,没有那么乱,但是麻雀虽小,五脏俱全。首先读取模式选择,活动模式(也就是遥控模式还是自由模式),确定模式后,除非重启或复位,否则将处于固定模式中。确定模式后,调用相关函数,解码红外编码,调用运动函数,执行动作。

        这就是这个项目的相关内容,本文仅仅对相关内容进行简单介绍与关键代码说明,具体代码,已经在gitee仓库开源(git@gitee.com:luyuan125/arduinodome.git),https://gitee.com/luyuan125/arduino-dome

        仓库地址如上,已经开源,后续有意思的项目代码将会统一上传至仓库,大家可以关注一下。

       本代码是根据项目的实际情况进行调试的,如果大家使用,需根据自己项目的情况进行参数调整与更改。做为开发小白,本文只记录一下我开发的思路,如有问题,请大佬批评指正。

(因项目外观保密性,无法公开望大家谅解)

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞龙0721

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值