实物展示

1、选材用料

2、设计原理

2、代码展示

#include <PS2X_lib.h>
#include<AFMotor.h>
#define PS2_DAT        13  //14    //对应的串口初始化,arduino板上的引脚分别连接PS2上对应的标识引脚
#define PS2_CMD        11  //15     //引脚可按自己连接更改
#define PS2_SEL        10  //16
#define PS2_CLK        12  //17AF_DCMotor motor1(1);//对四个电机的连接建立
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
AF_DCMotor motor4(4);#define pressures   true
#define rumble      truePS2X ps2x; // create PS2 Controller Classint error = 0;//以防出错的检测
byte type = 0;
byte vibrate = 0;void (* resetFunc) (void) = 0;
/*检测连接是否建立,在无显示屏,无法print情况下无用*/
void setup(){Serial.begin(115200);//串口通讯波特率的建立motor1.setSpeed(200); //四个电机速度的设置(200可按实际需要速度更改)motor2.setSpeed(200); motor3.setSpeed(200); motor4.setSpeed(200); delay(500);  //added delay to give wireless ps2 module some time to startup, before configuring iterror = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);if(error == 0){Serial.print("Found Controller, configured successful ");Serial.print("pressures = ");if (pressures)Serial.println("true ");elseSerial.println("false");Serial.print("rumble = ");if (rumble)Serial.println("true)");elseSerial.println("false");Serial.println("Try out all the buttons, X will vibrate the controller, faster as you press harder;");Serial.println("holding L1 or R1 will print out the analog stick values.");Serial.println("Note: Go to www.billporter.info for updates and to report bugs.");}  else if(error == 1)Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");else if(error == 2)Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");else if(error == 3)Serial.println("Controller refusing to enter Pressures mode, may not support it. ");type = ps2x.readType(); switch(type) {case 0:Serial.println("Unknown Controller type found ");break;case 1:Serial.println("DualShock Controller found ");break;case 2:Serial.println("GuitarHero Controller found ");break;case 3:Serial.println("Wireless Sony DualShock Controller found ");break;}}/*前后左右函数*/
void STOP(){motor1.run(RELEASE); motor2.run(RELEASE); motor3.run(RELEASE); motor4.run(RELEASE);
}//停止函数void RUN(){motor1.run(FORWARD); motor2.run(FORWARD); motor3.run(FORWARD); motor4.run(FORWARD);
}//可调速的前进函数void LEFT(){motor1.run(FORWARD); motor2.run(BACKWARD); motor3.run(BACKWARD); motor4.run(FORWARD);
}//可调速的左转函数void RIGHT(){motor1.run(BACKWARD); motor2.run(FORWARD); motor3.run(FORWARD); motor4.run(BACKWARD);
}//可调速的右转函数void BACK(){motor1.run(BACKWARD); motor2.run(BACKWARD); motor3.run(BACKWARD); motor4.run(BACKWARD);
}//可调速的后退函数void zishun(){motor1.run(FORWARD); motor2.run(BACKWARD); motor3.run(FORWARD); motor4.run(BACKWARD);
}//顺时针自转void zini(){motor1.run(BACKWARD); motor2.run(FORWARD); motor3.run(BACKWARD); motor4.run(FORWARD);
}//逆时针自转/*直接引用示例库,在按下某一按键后,会print 提示,
在提示后加入需要运行的代码,即可实现需要效果,也
可删去多余部分,在此小编直接引用*/
void loop() {if(error == 1){ //skip loop if no controller foundresetFunc();}if(type == 2){ //Guitar Hero Controllerps2x.read_gamepad();          //read controller if(ps2x.ButtonPressed(GREEN_FRET))Serial.println("Green Fret Pressed");if(ps2x.ButtonPressed(RED_FRET))Serial.println("Red Fret Pressed");if(ps2x.ButtonPressed(YELLOW_FRET))Serial.println("Yellow Fret Pressed");if(ps2x.ButtonPressed(BLUE_FRET))Serial.println("Blue Fret Pressed");if(ps2x.ButtonPressed(ORANGE_FRET))Serial.println("Orange Fret Pressed"); if(ps2x.ButtonPressed(STAR_POWER))Serial.println("Star Power Command");if(ps2x.Button(UP_STRUM))          //will be TRUE as long as button is pressedSerial.println("Up Strum");if(ps2x.Button(DOWN_STRUM))Serial.println("DOWN Strum");if(ps2x.Button(PSB_START))         //will be TRUE as long as button is pressedSerial.println("Start is being held");if(ps2x.Button(PSB_SELECT))Serial.println("Select is being held");if(ps2x.Button(ORANGE_FRET)) {     // print stick value IF TRUESerial.print("Wammy Bar Position:");Serial.println(ps2x.Analog(WHAMMY_BAR), DEC); } }else { //DualShock Controllerps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speedif(ps2x.Button(PSB_START))         //will be TRUE as long as button is pressedSerial.println("Start is being held");if(ps2x.Button(PSB_SELECT))Serial.println("Select is being held");      if(ps2x.Button(PSB_PAD_UP)) {      //will be TRUE as long as button is pressedSerial.print("Up held this hard: ");RUN();//按压PSB_PAD_UP键后执行RUN()函数Serial.println(ps2x.Analog(PSAB_PAD_UP), DEC);}if(ps2x.Button(PSB_PAD_RIGHT)){Serial.print("Right held this hard: ");RIGHT();//按压PSB_PAD_RIGHT键后执行 RIGHT()函数右转Serial.println(ps2x.Analog(PSAB_PAD_RIGHT), DEC);}if(ps2x.Button(PSB_PAD_LEFT)){Serial.print("LEFT held this hard: ");LEFT();//按压PSB_PAD_LEFTT键后执行LEFT()函数左转Serial.println(ps2x.Analog(PSAB_PAD_LEFT), DEC);}if(ps2x.Button(PSB_PAD_DOWN)){Serial.print("DOWN held this hard: ");BACK();//按压PSB_PAD_DOWN键后执行 BACK()函数后退Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);}   if(ps2x.Button(PSB_R3)){Serial.print("DOWN held this hard: ");zishun();//按压PSB_R3键后执行zishun()函数顺时针自转Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);}   if(ps2x.Button(PSB_L3)){Serial.print("DOWN held this hard: ");zini();//按压PSB_L3键后执行 zini()函数逆时针自转Serial.println(ps2x.Analog(PSAB_PAD_DOWN), DEC);}   /*以下函数在实作中没有用到*/vibrate = ps2x.Analog(PSAB_CROSS);  //this will set the large motor vibrate speed based on how hard you press the blue (X) buttonif (ps2x.NewButtonState()) {        //will be TRUE if any button changes state (on to off, or off to on)if(ps2x.Button(PSB_L3))Serial.println("L3 pressed");if(ps2x.Button(PSB_R3))Serial.println("R3 pressed");if(ps2x.Button(PSB_L2))Serial.println("L2 pressed");if(ps2x.Button(PSB_R2))Serial.println("R2 pressed");if(ps2x.Button(PSB_TRIANGLE))Serial.println("Triangle pressed");   STOP();      }if(ps2x.ButtonPressed(PSB_CIRCLE))               //will be TRUE if button was JUST pressedSerial.println("Circle just pressed");if(ps2x.NewButtonState(PSB_CROSS))               //will be TRUE if button was JUST pressed OR releasedSerial.println("X just changed");if(ps2x.ButtonReleased(PSB_SQUARE))              //will be TRUE if button was JUST releasedSerial.println("Square just released");     if(ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) { //print stick values if either is TRUESerial.print("Stick Values:");Serial.print(ps2x.Analog(PSS_LY), DEC); //Left stick, Y axis. Other options: LX, RY, RX  Serial.print(",");Serial.print(ps2x.Analog(PSS_LX), DEC); Serial.print(",");Serial.print(ps2x.Analog(PSS_RY), DEC); Serial.print(",");Serial.println(ps2x.Analog(PSS_RX), DEC); }     }delay(50);
}

3、结构原理

3.1建模

通过建模模拟车体基本构架,便于结构设计、无实物展示展示和组装;

 

  1.                            (b)

3.1  小车sw模型

   小车简介:小车将采用钢质小车地盘作为车身;以直流减速电机提供动力;麦克纳姆轮作为车轮;采取可装卸推球凹槽。

  

  1. (b)

图3.2 小球推槽结构

小球推槽结构简介:采用螺母结构固定于车身,竞速赛道时取下提高速度和可操控性,凹槽采取两段圆弧结构,大圆弧加宽凹槽宽度,使小车在遥控行驶的过程中更易捕获小球,凹槽中的小圆弧用于在推动小球时限制小球的较大范围运动,使在推小球到指定区域外时,小车减速,小球依靠惯性运动进入区域时,对小球的运动角度把握的更精准。

3.2 麦克纳姆轮原理

3.2.1 物理原理

3.2.1.1两种轮

对于四轮小车来说,一套麦克纳姆轮至少应含有两种不同的轮子,民间叫法有很多,百度上将他们称为:“麦克纳姆轮左和麦克纳姆轮右”,下面简称左轮和右轮;

左轮:正转可以向左前方运动,反转向右后方的轮(注意是运动方向,与给地面摩擦力的方向相反)

右轮:正转向右前方运动,反转向左后方的轮

当主轮转动时会带动周边轮的转动,而周边轮与主轮的转动成一定角度,所以可以产生一个斜向的力。因此多个麦轮组合使用、分别控制就可以使小车在主轮方向不变的情况下实现全向移动了(如果一时没想清楚就请继续看下面对各个运动状态的分析)。

对于左右轮旋转会产生什么方向的力是关键,你可以尝试着进行受力分析,这里就没必要讲解了,只需要大脑里稍微想象应该一下就明白了(或者直接记上面的结论也是一样的)

核心就是利用安装的对称性抵消不需要的力,叠加目标速度方向的力。

3.2.1.2一种可行的安装方式

对于四轮小车来说;一般来说的安装方式是:

图为一辆麦轮小车的俯视图,其中左前方和右后方的轮为左轮,其余两个为右轮

3.2.2 控制原理

3.2.2.1 前进/后退

以上述方式安装的麦轮同时正转时,前部两个轮与后方两个轮的侧方的力都可以抵消,只剩下向前方的力。小车就可以向前运动

图为,向前时横向移动的力。

后退反转即可,分析同理。

3.2.2.2 左右平移

原理是将小车同一侧的两个麦轮以相反的方向旋转,这样沿前后方的力就会抵消,而横向的力有恰好是同一方向。

例如向左移动就所有右轮全反转,左轮全正转。

3.2.2.3 自旋

原理就是一侧的轮子向后,另一侧的轮子向前;这样对于同一侧的两个轮子来说,横向的力还是可以抵消

如左侧两个轮子正转,右侧两个轮子反转就可以使小车顺势针旋转,反之则逆时针。

以上这几种运动方式需要注意的是,四个轮子虽然转的方向不同,但是转速需要严格相同,不然运动就不再准确。

3.3 控制逻辑

通过一套完备的代码,保证小车运行的速度和灵活性,通过手柄按键,控制实现前后左右、原地掉头,45°斜向的移动。

图3.3.1 PS2手柄按键示意图

图3.3.2连接示意图

(a)初始化设置

  1. 部分行进函数

图3.3.3 部分代码展示

代码简介:对arduino于PS2手柄连接Pin口进行初始话设置;如用L298n,则对控制L298n的IO口进行设置,将前后左右、原地掉头,45°斜向的移动封装为函数,当接收到PS2手柄的通讯信息时,按照不同按键的信息进行调用,实现移动。

3.4 组装

根据建模结果,由钢制车架(亚克力板)、直流电机、小轮胎、电池盒、电池等搭建小车,连接arduino板与推动足球的3D打印支架

图3.3.4 目前完成部分图

基于arduino及PS2的麦克纳姆轮遥控小车相关推荐

  1. 【控制】麦克纳姆轮 Mecanum 小车模型分析

    文章目录 简介 单个麦轮受力分析 单个麦轮速度分析 正运动学 逆运动学 附 Ref: 简介 移动机器人的运动学模型决定了如何将车轮速度映射到机器人的本体速度,而动力学模型则决定着如何将车轮扭矩映射到机 ...

  2. arduino麦轮转弯程序_麦克纳姆轮智能小车接线方案

    折腾了好几天,实在搞不定了,决定上来社区求助. 现在的硬件情况是这样的: - HM-GM37-3429霍尔传感器大载重电机,每个电机六条线,其中电机输入两个,霍尔编码器电源两个,编码器AB相两个 - ...

  3. 树莓派小车,从基础上手到完整工程(二)——麦克纳姆轮

    搭一个树莓派小车 树莓派小车 麦克纳姆轮 树莓派小车 麦克纳姆轮 po一张原理图,安装的时候注意轮子方向. 我把电机控制部分的代码大致封装了一下,后续可以自行添加其他功能. motor.py impo ...

  4. 麦克纳姆轮小车在gazebo中的实现

    搞毕设看的是赵虚左老师的视频,在视频中赵老师只介绍了两轮差速小车和阿克曼底盘的小车的控制器插件,麦克纳姆轮的小车并没有介绍到,在这里给大家分享一下麦轮小车的简单实现. <robot name=& ...

  5. 基于Arduino通过并联L298N实现四驱麦克纳姆轮巡迹小车

    1 前言 本人也是零基础进行Arduino学习的初学者,做小车期间遇到过很多困难,在此写下整个小车的制作流程以及遇到的问题与解决方案,希望对后来者有所帮助.在制作期间参考了许多文章得到了大佬的指点,以 ...

  6. arduino 4WD 麦克纳姆轮小车支持Mixly/Scratch

    加粗样式 完整资料教程下载链接: 前往界面 1.简介: 提及编程,很多人都会觉得是一件令人非常头疼的事情. 然而,基于arduino的麦克纳姆轮小车套件可以让您发现编程不再那么难.这款可编程套件,提高 ...

  7. 基于 RT-Thread的麦克纳姆轮小车循迹运动控制算法开发和研究

    学校:浙江工业大学 队伍名称:浙工大鸿泉全向 SOLO 队参赛队员:杨一帆.袁启恒.何志涛 带队教师:陈国定.褚衍清 简 介: 本文详细介绍了全向行进组智能车的制作方案.该方案以南京沁恒公司的 CH3 ...

  8. python firmata协议利用arduino操控麦克纳姆轮小车(附完整代码)

    python firmata协议利用arduino操控麦克纳姆轮小车 前言 一.python中pyfirmata的环境 材料 二.使用步骤 1.小车的安装方式 我在这采用的是X型安装方式 总结 前言 ...

  9. 四轮 控制算法 麦轮_基于麦克纳姆轮的全向移动自主机器人

    龙源期刊网 http://www.qikan.com.cn 基于麦克纳姆轮的全向移动自主机器人 作者:莫然 张进 高淑芝 来源:<山东工业技术> 2017 年第 08 期 摘 要:设计了一 ...

最新文章

  1. C++中的volatile关键字
  2. java AST 表达式_java 编译时注解-AST 抽象语法树简介
  3. Hibernate学习5—Hibernate操作对象
  4. 【C 语言】文件操作 ( 配置文件读写 | 写出或更新配置文件 | 逐行遍历文件文本数据 | 获取文件中的文本行 | 查询文本行数据 | 追加文件数据 | 使用占位符方式拼接字符串 )
  5. Java文件非法字符
  6. python基础教程 第3版 epub_铃声多多安卓版下载
  7. windows和centos进行文件上传和下载
  8. php 控制304,php静态文件返回304技巧分享
  9. C语言试题五十六之计算并输出给定整数n的所有因子(不包括1与自身)之和。规定n的值不大于1000。
  10. I/O复用的 select poll和epoll的简单实现
  11. storyboard搭建项目_swift项目第五天:swift中storyBoard Reference搭建主界面
  12. Spring Data JPA 实例查询
  13. 4.安卓基础之Activity跳转动画
  14. VUE3 Router路由
  15. PS 如何使用钢笔工具
  16. HTML5基础学习(6):个人简历制作
  17. 接口文档要写在概要设计里吗_概要设计报告怎么写
  18. 设置背景颜色html,css怎么设置背景颜色?
  19. 易语言解析ip138.com的查询接口
  20. 掌握Haproxy原理并搭建

热门文章

  1. 675. 为高尔夫比赛砍树
  2. Liferay 学习教程-ServiceBuilder的基本使用
  3. 使用Docker安装的Nginx代理前端vue项目
  4. 蔡徐坤教你用OpenCV实现素描效果
  5. 微信小程序无法访问豆瓣API, 豆瓣图书小程序示例
  6. NumPy的实用函数整理之sliding_window_view
  7. 明星项目ALGO沦为散户收割机:5天跌去60%,私募却获48倍回报
  8. C# IO流读写文件操作
  9. Linux 操作系统原理 — 进程管理 — 进程调度
  10. 思杰pvs服务器压力无法最大化,XXX学校桌面虚拟化方案资料.docx