四轮全向底盘工训纪实
四轮全向底盘工训纪实1 工程训练纪实前言2 组装过程2.1 结构说明2.2 具体步骤3 调整电控3.1 伺服电机初始化3.2 步进电机控制3.2.1 抬笔与落笔3.2.2 修改绘图范围3.2.3 控制全向底盘移动1 工程训练纪实前言这是南京理工大学暑期工程训练金工实习机器人项目第二天的记录博客记录了四轮全向底盘的全过程细节在此先向这一个月中的各位老师表达感谢尤其感谢张小兵教授的教导。先叠个甲以后的学弟学妹请勿完全照抄本文本人方案仅为我个人记录吾技术浅薄仅供参考。2 组装过程2.1 结构说明四福来轮全向移动底盘采用四个全向福来轮作为执行轮这四个轮成正方形分布且每个轮在斜45°方向安装。全向福来轮由主轮和副轮组成主轮和副轮成垂直分布。驱动系统采用精度较高的42步进电机执行末端为伺服电机。通过四个步进电机运动的相互配合四个步进电机驱动将圆周转动转化为直线运动从而实现全向移动。四福来轮全向移动底盘具有结构简单、运动灵活等特点可以用于实现各种复杂的移动和定位任务。例如它可以用于机器人、自动化设备、无人驾驶车辆等领域实现精确的定位、移动和操控。2.2 具体步骤总体上难度不大拼起来很快直接上PPT。注意要先调试电机再安装。安装电机时接线头应朝向侧面不得朝向下面。接线的时候要注意线材颜色否则电机易烧毁可以给助教看看。其中笔架需要自己设计完善可以通过螺丝去固定也可以用透明胶带进行捆绑无论用什么方法笔要稳不能抖。3 调整电控3.1 伺服电机初始化在上课之前老师会提前发一个压缩包里面有各种各样的工具软件还有半成品代码这里就要用到arduino和controller。先将以下命名为servo_bigfish.ino的代码通过arduino烧录进开发板中。/* * Bigfish扩展板舵机口; 4, 7, 11, 3, 8, 12, 14, 15, 16, 17, 18, 19 * 使用软件调节舵机时请拖拽对应序号的控制块 */#includeServo.h#defineANGLE_VALUE_MIN0#defineANGLE_VALUE_MAX180#definePWM_VALUE_MIN500#definePWM_VALUE_MAX2500#defineSERVO_NUM12Servo myServo[SERVO_NUM];intdata_array[2]{0,0};//servo_pin: data_array[0], servo_value: data_array[1];intservo_port[SERVO_NUM]{4,7,11,3,8,12,14,15,16,17,18,19};intservo_value[SERVO_NUM]{};String data;boolean dataCompletefalse;voidsetup(){Serial.begin(9600);}voidloop(){while(Serial.available()){intB_flag,P_flag,T_flag;dataSerial.readStringUntil(\n);data.trim();for(inti0;idata.length();i){//Serial.println(data[i]);switch(data[i]){case#:B_flagi;break;caseP:{String pin;P_flagi;for(intiB_flag1;iP_flag;i){pindata[i];}data_array[0]pin.toInt();}break;caseT:{String angle;T_flagi;for(intiP_flag1;iT_flag;i){angledata[i];}data_array[1]angle.toInt();servo_value[pin2index(data_array[0])]data_array[1];}break;default:break;}}/* Serial.println(B_flag); Serial.println(P_flag); Serial.println(T_flag); for(int i0;i2;i) { Serial.println(data_array[i]); } */dataCompletetrue;}if(dataComplete){for(inti0;iSERVO_NUM;i){ServoGo(i,servo_value[i]);/*********************************串口查看输出***********************************/// Serial.print(servo_value[i]);// Serial.print( );}// Serial.println();/********************************************************************/dataCompletefalse;}}voidServoStart(intwhich){if(!myServo[which].attached()(servo_value[which]!0))myServo[which].attach(servo_port[which]);elsereturn;pinMode(servo_port[which],OUTPUT);}voidServoStop(intwhich){myServo[which].detach();digitalWrite(servo_port[which],LOW);}voidServoGo(intwhich,intwhere){ServoStart(which);if(whereANGLE_VALUE_MINwhereANGLE_VALUE_MAX){myServo[which].write(where);}elseif(wherePWM_VALUE_MINwherePWM_VALUE_MAX){myServo[which].writeMicroseconds(where);}}intpin2index(int_pin){intindex;switch(_pin){case4:index0;break;case7:index1;break;case11:index2;break;case3:index3;break;case8:index4;break;case12:index5;break;case14:index6;break;case15:index7;break;case16:index8;break;case17:index9;break;case18:index10;break;case19:index11;break;}returnindex;}代码烧录后进入controller选择端口号及波特率进行连接在对应模块中拖动控制条使电机转动最终置于90°的位置伺服电机初始化调整成功。3.2 步进电机控制步进电机控制这一段是整体最有趣的地方看起来有些难但仅需有一些C语言程序设计基础即可完成无需理解全部的代码只需要看懂位移如何控制的就行。下面是一个现成的画六边形的代码仅供参考。#includeServo.h/* * en定义步进电机使能引脚 * servo_pin定义舵机引脚 * stepper_count定义步进电机数量 * stepperPulse_delay定义步进电机脉冲生成间隔 * LINE_BUFFER_LENGTH定义串口接收数据长度 */#defineen8#defineservo_pin11#definestepper_count4#definestepperPulse_delay850#defineLINE_BUFFER_LENGTH512/* * positive_x定义正向 X 轴 * positive_y定义正向 Y 轴 * negative_x定义负向 X 轴 * negative_y定义负向 Y 轴 */#definepositive_x0#definepositive_y1#definenegative_x2#definenegative_y3/* * stepperDir_pin定义步进电机方向引脚数组 * stepperStp_pin定义步进电机步进引脚数组 * dir: x: 5, y: 6, z: 7, a: 13 * stp: x: 2, y: 3, z: 4, a: 12 */intstepperDir_pin[4]{5,6,7,13};intstepperStp_pin[4]{2,3,4,12};Servo myServo;constintstepsPerRevolution3200;//定义步进电机每圈转动的步数此处为16细分每圈 3200 步intpenZup145;//定义舵机抬起角度intpenZdown180;//定义舵机放下角度floatLEADsqrt(2)*58*PI;//定义步进电机转动 1 圈小车前进的距离单位 mmfloatl60;//定义六边形边长//定义六边形顶点坐标数组floatcoords[7][2]{-l*1/2,-sqrt(3)/2*l,l*1/2,-sqrt(3)/2*l,l,0,l*1/2,sqrt(3)/2*l,-l*1/2,sqrt(3)/2*l,-l,0,-l*1/2,-sqrt(3)/2*l};floatXmin-60;//定义绘图范围floatXmax60;floatYmin-60;floatYmax60;floatXpos0;floatYpos0;voidsetup(){Serial.begin(9600);//开启串口通信波特率为 9600myServo.attach(servo_pin);myServo.write(penZup);for(inti0;istepper_count;i){pinMode(stepperDir_pin[i],OUTPUT);pinMode(stepperStp_pin[i],OUTPUT);}pinMode(en,OUTPUT);digitalWrite(en,LOW);delay(1000);}voidloop(){draw_sexangle();while(1){};}//六边形绘制函数voiddraw_sexangle(){drawLine(coords[0][0],coords[0][1]);delay(200);for(inti0;isizeof(coords)/sizeof(coords[0]);i){penDown();delay(200);drawLine(coords[i][0],coords[i][1]);penUp();}}//直线插补函数参数为点坐标值voiddrawLine(floatx1,floaty1){intdx,dy,n,k,i,f,stepInc;if(x1Xmax){x1Xmax;}if(x1Xmin){x1Xmin;}if(y1Ymax){y1Ymax;}if(y1Ymin){y1Ymin;}x1(int)(x1/LEAD*stepsPerRevolution);y1(int)(y1/LEAD*stepsPerRevolution);floatx0Xpos;floaty0Ypos;dxabs(x1-x0);dyabs(y1-y0);nabs(dxdy);if(x1x0){ky1y0?1:4;}else{ky1y0?2:3;}for(i0,f0;in;i1){if(f0){switch(k){case1:stepper_move(positive_x,1);ff-dy;//Serial.println(x);break;case2:stepper_move(negative_x,1);ff-dy;//Serial.println(-x);break;case3:stepper_move(negative_x,1);ff-dy;//Serial.println(-x);break;case4:stepper_move(positive_x,1);ff-dy;//Serial.println(x);break;default:break;}}else{switch(k){case1:stepper_move(positive_y,1);ffdx;//Serial.println(y);break;case2:stepper_move(positive_y,1);ffdx;//Serial.println(y);break;case3:stepper_move(negative_y,1);ffdx;//Serial.println(-y);break;case4:stepper_move(negative_y,1);ffdx;//Serial.println(-y);break;default:break;}}}Xposx1;Yposy1;}//小车行进方向控制函数voidstepper_dir(intpositiveDir_x,intpositiveDir_y,intnegativeDir_x,intnegativeDir_y){intdir_value[]{positiveDir_x,positiveDir_y,negativeDir_x,negativeDir_y};for(inti0;istepper_count;i){//Serial.print(dir_value[i]);//Serial.print(,);digitalWrite(stepperDir_pin[i],dir_value[i]);}//Serial.println();for(intj0;jstepper_count;j){digitalWrite(stepperStp_pin[j],HIGH);}delayMicroseconds(stepperPulse_delay);for(intj0;jstepper_count;j){digitalWrite(stepperStp_pin[j],LOW);}delayMicroseconds(stepperPulse_delay);}//步进电机转动函数参数 dir_xy步进电机转动方向steps步进电机转动步数voidstepper_move(intdir_xy,intsteps){for(inti0;iabs(steps);i){switch(dir_xy){case0:stepper_dir(1,1,0,0);break;case1:stepper_dir(1,0,1,0);break;case2:stepper_dir(0,0,1,1);break;case3:stepper_dir(0,1,0,1);break;default:break;}}}//舵机抬笔函数voidpenUp(){myServo.write(penZup);}//舵机落笔函数voidpenDown(){myServo.write(penZdown);}3.2.1 抬笔与落笔角度需要自己用controller一次一次去尝试而且由于安装不同penZup可能不一定是抬笔penZdown也可能不一定是落笔。intpenZup145;//定义舵机抬起角度intpenZdown180;//定义舵机放下角度3.2.2 修改绘图范围建议增大绘图范围超范围就会在那里描边。floatXmin-60;//定义绘图范围floatXmax60;floatYmin-60;floatYmax60;3.2.3 控制全向底盘移动下面截取了画六边形的移动控制方法以此为例。floatLEADsqrt(2)*58*PI;//定义步进电机转动 1 圈小车前进的距离单位 mmfloatlen60;//定义六边形边长//定义六边形顶点坐标数组floatcoords[7][2]{-len*1/2,-sqrt(3)/2*len,len*1/2,-sqrt(3)/2*len,len,0,len*1/2,sqrt(3)/2*len,-len*1/2,sqrt(3)/2*len,-len,0,-l*1/2,-sqrt(3)/2*len};在float coords二维数组中存储了每次移动的目标点位的坐标在修改时可以将len作为一单位长度这样方便修改。如果要控制全向底盘写字的话不一定要按照正常的笔画进行运动。

相关新闻

WuKongIM pkg/ 三层架构重构实战:从 15 个散落包到 Controller / Group(Slot) / Channel 分层实施指南

WuKongIM pkg/ 三层架构重构实战:从 15 个散落包到 Controller / Group(Slot) / Channel 分层实施指南

即时通讯后端 【免费下载链接】WuKongIM More than just IM 不只是即时通讯(IM) 项目地址: https://gitcode.com/gh_mirrors/wu/WuKongIM 点击查看 免费下载 本文以 WuKongIM 仓库内的 docs/superpowers/plans/2026-04-10-pkg-restructure-implementation.md 实施计…

2026/10/16 1:36:41 阅读更多 →
Olares One 已知问题排查指南:初始设置卡在 9% 与 Windows 下 Thunderbolt 5 显示为 USB4

Olares One 已知问题排查指南:初始设置卡在 9% 与 Windows 下 Thunderbolt 5 显示为 USB4

云原生后端运维 【免费下载链接】Terminus Open-Source Personal Cloud OS for Always-On Agents 项目地址: https://gitcode.com/gh_mirrors/terminus2/Terminus 点击查看 免费下载 Olares One 在初始设置与双启动场景中可能遇到两个典型问题:初始激活…

2026/10/16 1:36:41 阅读更多 →
WuKongIM 聊天生命周期 Soak 第四阶段:Coordinator 协调编排与 Verdict 判定体系实现解析

WuKongIM 聊天生命周期 Soak 第四阶段:Coordinator 协调编排与 Verdict 判定体系实现解析

即时通讯后端 【免费下载链接】WuKongIM More than just IM 不只是即时通讯(IM) 项目地址: https://gitcode.com/gh_mirrors/wu/WuKongIM 点击查看 免费下载 导读 本文围绕 2026-08-04-chat-lifecycle-soak-04-coordinator-verdict.md 展开,详解 WuKon…

2026/10/16 1:36:41 阅读更多 →

最新新闻

Java字符串转数字的正确方法

Java字符串转数字的正确方法

java中把字符串转成 的方法更新时间为二零二三年七月七日零九点四十分零三秒, 作者是。在Java环境里头, 大家可以利用某个类里面的那个叫作静态的方法, 把一段写着数字的字符串变成对应那种类型的数, 这篇文章会配上一些具体的代码例子, 来把这个事情从字符串弄成具体数值的过程…

2026/10/16 3:12:01 阅读更多 →
3ds Max角色动画骨骼绑定全流程:模型准备、蒙皮权重与避坑指南

3ds Max角色动画骨骼绑定全流程:模型准备、蒙皮权重与避坑指南

简介:面向3ds Max角色动画学习者的教学PPT课件,聚焦角色动画设计与骨骼绑定核心流程。课件系统讲解了创建骨骼结构、Bones内置系统与Character Studio工具的结合使用,重点区分直接连接与蒙皮连接两种支配模型的方式;围绕软性骨骼蒙…

2026/10/16 3:12:01 阅读更多 →
先查供电、天线和传感器 CRC:方案测试怎么跟硬件同事对话

先查供电、天线和传感器 CRC:方案测试怎么跟硬件同事对话

副标题:松天线、拔传感器、波特率设错,各记一层;先给数据再让人改版 专栏:《嵌入式学生的方案测试课》第 15 篇(软硬件联测) 前置:第 1 篇环境表;第 5 篇四层;第 9 篇没有…

2026/10/16 3:12:01 阅读更多 →
混沌拓扑学(HDT)灰度思想与布劳威尔直觉主义、选择序列与展形——排中律失效后的数学重构

混沌拓扑学(HDT)灰度思想与布劳威尔直觉主义、选择序列与展形——排中律失效后的数学重构

前言 在经典数学体系中,排中律被视为不可撼动的逻辑公理:对于任意命题 PPP,必然满足 P∨PP \lor \neg PP∨P。 通俗表述为:任何命题非真即假,不存在第三种状态,不存在未确定状态,不存在中间灰度…

2026/10/16 3:12:01 阅读更多 →
浪潮AS5300/AS5500双控存储安装调试指南:从级联到映射

浪潮AS5300/AS5500双控存储安装调试指南:从级联到映射

简介:浪潮存储AS5300/AS5500安装调试指导文档,面向企业级存储实施、运维及售前售后工程师,解决新设备上架、初始化配置、业务上线和故障定位过程中的操作盲区。内容按七个环节组织:先给出设备规格与扩展柜SS5000J-16/SS5000J-24物…

2026/10/16 3:12:01 阅读更多 →
小白程序员必看:AI大模型落地实战指南,从入门到精通

小白程序员必看:AI大模型落地实战指南,从入门到精通

本文深入探讨AI大模型应用落地过程中的关键环节,强调企业需求明确、模型流程整合及持续优化的重要性。文章指出,AI应用需从模糊需求明确化,到模型接入可用流程,再到真实使用中的持续改进。通过分析FDE工程师的核心能力&#xff0c…

2026/10/16 3:11:01 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →