jjzjj

嵌入式学习记录(1)——四足蜘蛛机器人

Outの粉丝菌 2023-12-18 原文

模型文件来自于大神Spider robot开源,代码文件为原创测试用,比较无脑的重复代码,入门阶段。单片机采用arduino uno开发板,HC05蓝牙模块,SG90舵机12个,目前还没有PID算法,后期应该会加上吧。

#转载引用请标明出处,另外禁止商用

Arduino UNO开发板

        Adruino UNO是一款常见的Adruino板子,如图5.1所示,从复位按钮开始顺时针依次是TWI接口、数字输入输出接口、电源指示灯、ICSP编程接口、主控单片机ATmega328,模拟输入接口、电源接口、DC电源输入接口、稳压芯片、USB接口。

        Adruino UNO的工作电压为5V,供电范围一般是6-20V。考虑电压较低可能导致供电不足,驱动不了模块电压过高可能会使板子上面的稳压芯片过热影响板子使用寿命,所以实际的供电范围在7-12V之间。Adruino UNO的供电方式有3种,可以根据开发者的需要自己选择供电方式。第一种是外部的直流电源连接到DC电源输入接口来给UNO板子供电;第二种是通过UNO板子的USB接口,电脑通过USB线连接到UNO板子的USB接口可以用来下载程序给板子以及供电。当前两种供电方式没有采用时,可以使用第三种供电方式,即使用UNO板子上电源接口处的GND 和VIN引脚供电。但如果前两种供电方式已经采用的话,可以通过VIN给外部模块或者面包板供电。电源接口引脚中的5V引脚是通过稳压芯片或USB的5V电压,为板子上的5V芯片供电;其中的3.3V引脚是通过稳压芯片产生的3.3V电压,驱动电流最大为50mA。
        板子上的14路数字输入输出接口工作电压为5V,其中还有一些具有特定功能的引脚。本次毕业设计过程中使用到0、1、2、6以及7号数字输入输出引脚。0号引脚和1号引脚可用于串口通信,0号引脚为RX,1号引脚为TX,提供串口接收信号。这两个引脚用于连接HC-05蓝牙模块。2号引脚作为触发中断引脚,有3种触发模式,分别是上升沿、下降沿触发以及同时触发。本次毕设中2号引脚用于控制4个LED指示灯。6号和7号引脚属于正常功能的引脚。
        板子上的AO-A5接口是模拟输入接口,默认输入信号范围是0-5V。和数字输入接口类似,模拟输入接口也有几个引脚具有特定功能。


 步态规划:

四足步态采用了x型步态,操作部分代码见AutodataCmd部分,使用HC05蓝牙模块,由于舵机数量较多采用数组直接定义。启动时会进入准备状态,进行行进前需要启动Start进入预备状态。

‘x’型步态规划方式如下:

前进步态:

如图所示,在“X”型步态时,四足榛蛛机器人前进步态是A腿抬起→A腿前移(1号舵机带着A腿逆时针转动)→A腿落下→C腿抬起→C腿前移(7号舵机带着C腿顺时针转动)→C腿落下→AC两条腿复位→B腿抬起→B腿前移(4号舵机带着B腿顺时针转动)→B腿落下→D腿抬起→D腿前移(10号舵机带着D腿逆时针转动)一D腿落下一BD两条腿复位。

 后退步态:

在“X”字型步态时,如图所示,四足蜘蛛机器人后退步态是:A腿抬起→A腿向右移(1号舵机带着A腿顺时针转动)→A腿落下→C腿抬起→C腿向右移(7号舵机带着C腿逆时针转动)→C腿落下→AC两条腿复位→B腿抬起一B腿向左移(4号舵机带着B腿逆时针转动)一B腿落下一D腿抬起→D腿向左移(10号舵机带着D腿顺时针转动)→D腿落下→ED两条腿复位。

左转/右转步态规划:

在“X”型步态时,如图所示,四足蜘蛛机器人左转步态是A腿抬起→A腿向左移(1号舵机带着A腿逆时针转动)→A腿落下→C腿抬起→C腿向右移(7号舵机带着C腿逆时针转动)→C腿落下→B腿抬起→B腿向左移(4号舵机带着B腿逆时针转动)→B腿落下→D腿抬起→D腿向右移(10号舵机带着D腿逆时针转动)→一D腿落下→ABCD 四条腿复位。

图略,四足蜘蛛机器人右转步态是:A腿抬起→A腿向右移(1号舵机带着A腿顺时针转动)→A腿落下→C腿抬起→C腿向左移(7号舵机带着C腿顺时针转动)→C腿落下→B腿抬起→B腿向右移(4号舵机带着B腿顺时针转动)→B腿落下一→D腿抬起→D腿向左移(10号舵机带着D腿顺时针转动)→D腿落下一ABCD 四条腿复位。

#转载引用请标明出处,另外禁止商用

UNO代码控制代码:

#include<Servo.h>
//#include<MsTimer2.h>
#define sMaxAngle 175
#define sMinAngle 5

Servo servo[12];//定义舵机数组名称
int servo_pin[12];//定义引脚
bool mode;//模式调整

void setup() {
  Serial.begin(9600);
  Serial.println("Robot begin work");
  Initialize();
}


void loop() {
  if(Serial.available()){
    char serialCmd = Serial.read();
    if(mode == 1){
      //ArmdataCmd(serialCmd);//指令模式
    }else{
      AutodataCmd(serialCmd);//自动模式
    }
  }
}

void PreMode(char serialCmd = 's'){//进入预备模式
  for(int pre = 90;pre >= 45;pre--){
    servo[4].write(pre);
    delay(15);
    servo[6].write(pre);
    delay(15);
  }
  for(int pre = 90;pre <= 135;pre++){
    servo[5].write(pre);
    delay(15);
    servo[7].write(pre);
    delay(15);    
  }
  for(int pre_2 = 90;pre_2 <= 135;pre_2++){
    servo[9].write(pre_2);
    delay(15);
    servo[10].write(pre_2);
    delay(15);
  }
  for(int pre_2 = 90;pre_2 >= 45;pre_2--){
    servo[8].write(pre_2);
    delay(15);
    servo[11].write(pre_2);
    delay(15);    
  }
  for(int pos = 90;pos <= 135;pos++){//进入准备模式
    Serial.println(pos);
    servo[0].write(pos);
    delay(15);
    servo[2].write(pos);
    delay(15);    
  }
  for(int pos = 90;pos >= 45;pos--){
    Serial.println(pos);
    servo[1].write(pos);
    delay(15);
    servo[3].write(pos);
    delay(15);
  }
}

void AutodataCmd(char serialCmd){//自动模式给出相应操作
  if(serialCmd == 'B'||serialCmd == 'H'||serialCmd == 'R'||serialCmd == 'L'){
    Serial.println("+Warning:Robot in Auto Mode...");
    delay(100);
    while(Serial.available()>0) char wrongCommand =Serial.read();//清除串口错误信息
    return;
  }
  switch(serialCmd){
    case 's':
      Serial.println("Enter preparing Model!!!");
      PreMode();
      Serial.println("Preparation Over!!!");
      break;
    
    case 'w'://前进步态命令
      Serial.println("Robot starts to go ahead!!!");
      for(int i = 0;i <= 5;i++){
        Goahead_leg1();
        Goahead_leg3();
        aheadIni_leg13();
        Goahead_leg2();
        Goahead_leg4();
        aheadIni_leg24();
      }
      Serial.println("Ahead Command had overed!!!"); 
      break;
    case 'x'://后退步态命令
      Serial.println("Robot starts to come back!!!");
      for(int i = 0;i <= 3;i++){
        Bcak_leg1();
        Back_leg3();
        Back_Ini13();
        Back_leg2();
        Back_leg4();
        Back_Ini24();
      }
      Serial.println("Back Command had overed!!!");
      break;
    case 'a'://左转步态命令
      Serial.println("Robot starts to turn left!!!");
      Goahead_leg1();
      Back_leg3();
      Back_leg2();
      Goahead_leg4();
      Left_Ini();      
      //turnLeft();
      break;
    case 'd':
      Serial.println("Robot starts to turn right!!!");
      Bcak_leg1();
      Goahead_leg3();
      Goahead_leg2();
      Back_leg4();
      Right_Ini();
      //turnRight();
      break;
    case 'q':
      Serial.println("Robot starts to stand up!!!");
      turnUp();
      break;
    case 'o':
      Serial.println("Robot initialized");
      Initialize();
      break;
        
  }
}

void Initialize(){//机器人初始化
    for(int i = 0;i <= 11;i++){
      servo_pin[i] = i+2;
      servo[i].attach(servo_pin[i],500,2500);
      servo[i].write(90);
  }
}

void Goahead_leg1(char serialCmd = 'w'){//前进腿1  
  for(int pos = 45;pos <= 75;pos++){
    servo[8].write(pos);
    delay(15);
  }
  for(int pos = 135;pos <= 165;pos++){
    servo[0].write(pos);
    delay(15);
  }
  for(int pos = 75;pos >= 45;pos--){
    servo[8].write(pos);
    delay(15);
  }
}

void Goahead_leg3(char serialCmd = 'w'){//前进腿3
  for(int pos = 45;pos <= 75;pos++){
    servo[11].write(pos);
    delay(15);
  }
  for(int pos = 135;pos >= 105;pos--){
    servo[2].write(pos);
    delay(15);
  }
  for(int pos = 75;pos >= 45;pos--){
    servo[11].write(pos);
    delay(15);
  }
}
void aheadIni_leg13(char serialCmd = 'w'){//腿13复原
  for(int pos = 165;pos >= 135;pos--){
    servo[0].write(pos);
    delay(15);    
  }
  for(int pos = 105;pos <= 135;pos++){
    servo[2].write(pos);
    delay(15);
  }
}

void Goahead_leg2(char serialCmd = 'w'){//前进腿2
  for(int pos = 135;pos >= 105;pos--){
    servo[9].write(pos);
    delay(15);  
  }
  for(int pos = 45;pos >= 15;pos--){
    servo[1].write(pos);
    delay(15);
  }
  for(int pos = 105;pos <= 135;pos++){
    servo[9].write(pos);
    delay(15);  
  }  
}

void Goahead_leg4(char serialCmd = 'w'){//前进腿4
  for(int pos = 135;pos >= 105;pos--){
    servo[10].write(pos);
    delay(15);
  }
  for(int pos = 45;pos <= 75;pos++){
    servo[3].write(pos);
    delay(15);
  }
  for(int pos = 105;pos <= 135;pos++){
    servo[10].write(pos);
    delay(15);
  }
}

void aheadIni_leg24(char serialCmd = 'w'){//腿24复原
  for(int pos = 15;pos <= 45;pos++){
    servo[1].write(pos);
    delay(15);
  }
  for(int pos = 75;pos >= 45;pos--){
    servo[3].write(pos);
    delay(15);
  }
}

void turnUp(char serialCmd ='q'){//皮皮虾代码,谨慎使用
  for(int pos = 90;pos <=135;pos++){
    servo[4].write(pos);
    delay(15);
    servo[6].write(pos);
    delay(15);
  }
  for(int pos = 45;pos <= 90;pos++){
    servo[5].write(pos);
    delay(15);
    servo[7].write(pos);
    delay(15);    
  }
  for(int pos = 135;pos >= 90;pos--){
    servo[4].write(pos);
    delay(15);
    servo[6].write(pos);
    delay(15);    
  }
  for(int pos = 90;pos >= 45;pos--){
    servo[5].write(pos);
    delay(15);
    servo[7].write(pos);
    delay(15);    
  }
}

void Bcak_leg1(char serialCmd = 'x'){//腿1撤回
  for(int pos = 45;pos <= 90;pos++){
    servo[8].write(pos);
    delay(15);
  }
  for(int pos = 135;pos >= 105;pos--){
    servo[0].write(pos);
    delay(15);
  }
  for(int pos = 90;pos >= 45;pos--){
    servo[8].write(pos);
    delay(15);
  }  
}

void Back_leg3(char serialCmd = 'x'){//腿3撤回
  for(int pos = 45;pos <= 75;pos++){
    servo[11].write(pos);
    delay(15);
  }
  for(int pos = 135;pos <= 165;pos++){
    servo[2].write(pos);
    delay(15);
  }
  for(int pos = 75;pos >= 45;pos--){
    servo[11].write(pos);
    delay(15);
  }
}

void Back_Ini13(char serialCmd = 'x'){//撤回13复原
  for(int pos = 105;pos <= 135;pos++){
    servo[0].write(pos);
    delay(15);
  }
  for(int pos = 165;pos >= 135;pos--){
    servo[2].write(pos);
    delay(15);
  }    
}

void Back_leg2(char serialCmd = 'x'){//腿2撤回
  for(int pos = 135;pos >= 105;pos--){
    servo[9].write(pos);
    delay(15);  
  }
  for(int pos = 45;pos <= 75;pos++){
    servo[1].write(pos);
    delay(15);
  }
  for(int pos = 105;pos <= 135;pos++){
    servo[9].write(pos);
    delay(15);  
  } 
}

void Back_leg4(char serialCmd = 'x'){//腿4撤回
  for(int pos = 135;pos >= 105;pos--){
    servo[10].write(pos);
    delay(15);
  }
  for(int pos = 45;pos >= 15;pos--){
    servo[3].write(pos);
    delay(15);
  }
  for(int pos = 105;pos <= 135;pos++){
    servo[10].write(pos);
    delay(15);
  }  
}

void Back_Ini24(char serialCmd = 'x'){//撤回24复原
  for(int pos = 75;pos >= 45;pos--){
    servo[1].write(pos);
    delay(15);
  }
   for(int pos = 15;pos <= 45;pos++){
    servo[3].write(pos);
    delay(15); 
  }
}

void Left_Ini(){//x步态左转复原
  for(int pos = 165;pos >= 135;pos--){
    servo[0].write(pos);
    delay(15);
    servo[2].write(pos);
    delay(15);
  }
    for(int pos = 75;pos >= 45;pos--){
    servo[1].write(pos);
    delay(15);
    servo[3].write(pos);
    delay(15);    
  }
}

void Right_Ini(){//x步态右转复原
  for(int pos = 105;pos <= 135;pos++){
    servo[0].write(pos);
    delay(15);
    servo[2].write(pos);
    delay(15);
  }
  for(int pos = 15;pos <= 45;pos++){
    servo[1].write(pos);
    delay(15);
    servo[3].write(pos);
    delay(15);
  }    
}

有关嵌入式学习记录(1)——四足蜘蛛机器人的更多相关文章

  1. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  2. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  3. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  4. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  5. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  6. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  7. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  8. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  9. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  10. ruby-on-rails - 在 Rails 中更高效地查找或创建多条记录 - 2

    我有一个应用需要发送用户事件邀请。当用户邀请friend(用户)参加事件时,如果尚不存在将用户连接到该事件的新记录,则会创建该记录。我的模型由用户、事件和events_user组成。classEventdefinvite(user_id,*args)user_id.eachdo|u|e=EventsUser.find_or_create_by_event_id_and_user_id(self.id,u)e.save!endendend用法Event.first.invite([1,2,3])我不认为以上是完成我的任务的最有效方法。我设想了一种方法,例如Model.find_or_cr

随机推荐