×

Arduino滑冰机器人

消耗积分:0 | 格式:zip | 大小:1.20 MB | 2022-12-05

哈哈哈

分享资料个

描述

介绍

这个项目是我参加 2018 年 Arduino / Distrelec Automattion 竞赛的参赛作品。它基于我今年早些时候设计并作为一个想法发布的滑冰机器人。我需要做的“唯一”事情就是开发一个可以通过 Blynk 控制的版本,然后在有良好的用户界面后添加更多功能。当然事情从来没有那么容易,我在下面写了一些关于这个项目的东西。

目标是拥有更多功能,比如自主模式,但我需要在 9 月初专注于拥有一个工作机器人和尽可能整洁的东西,以适应比赛截止日期。我决定在我的 Blynk 应用程序中添加带有伺服和超声波传感器以及简单用户界面的功能。自主移动是我接下来要做的事情。无论如何,我确信我的机器人在很多方面都是独一无二的,并且可能展示了一种将行走与轮式推进相结合的方式。

背后的概念

机器人通常可以分为两类,轮式或步行式。轮式机器人设计简单(基本上是遥控汽车)且移动速度快。有腿机器人更像是一项工程挑战,因为它们需要复杂的编程才能移动四肢,挑战本身就是我个人开发 KITtyBot 的原因之一。有腿式的优点是可以翻越障碍物和上下楼梯。这对于建筑物内的救援任务至关重要。但是在平坦的地面上,步行机器人比带轮子的机器人慢。当然,这些概念可以通过多种方式组合,以便从两个世界中获得最佳效果。带有高级悬架的轮式机器人可以越过障碍物,最终“悬架”可以更像“腿”,允许行走或攀爬。

我的项目评估了一个带有被动轮子的机器人,即它们缺乏推进力。取而代之的是一个伺服系统,可以让车轮倾斜,基本上就像汽车的前轮一样。移动是通过滑冰(或者可能像划独木舟)来完成的,即利用可能性来调整轮子的角度并使用腿部运动向前推动。至少与普通步行相比,这允许进行相当快速且节能的运动。与具有“腿悬架”的传统轮式机器人相比的优势在于不需要电机驱动轮子。机器人可以随时恢复行走。

大部分设计与我在项目中心发布的机器人 KITtyBot 相似。它使用相同的反向运动学来移动脚,如果它确实行走,它使用我为 KITtyBot 开发的相同步行步态。新的部分是脚上增加的“旱冰鞋”。轮子的接触点位于脚尖在 KITtyBot 上的位置。

构建机器人

根据提供的文件打印零件。在开始之前,请花一些时间查看图片并弄清楚如何组装零件。

应首先组装髋关节。我通过添加更多 3D 打印部件从 KITtyBot 开发了设计。为此,我还必须重新设计身体,新的髋关节需要多出几毫米的空间。如果您碰巧有 KITtyBot 的零件在身边,或者想将其中一个改装成这个机器人,您可以这样做。组装好所有部件后,外形尺寸将相同

请注意,有两个版本称为 fl/rr(左前/右后)和 fr/rl(右前/左后)。制作四个髋关节需要每类各两套。确保您对零件进行了分类。除了这四个引脚之外,还需要一个新的身体。保留了原版 KITtyBot 的腿和保险杠。

下图显示了关节的组装。下图中的分步说明显示了如何进行 fl/rr 接头。一旦你用完了一半的零件,另一个关节应该是直的。:)

 
 
 
 
poYBAGOIKqaALi5NAAAsaFTqjv8204.jpg
 
1 / 6首先将销钉安装到内部部件中
 

接下来是脚关节。这还包括两个 3D 打印部件和两个伺服系统。有四个部分,每个部分称为先脚和后脚。它们没有分为 fr/rl 和 fl/rr 版本,因为它们会随着伺服系统的安装方式而改变。下面的图片描述了安装顺序。

 
 
 
 
poYBAGOIKqqALQmXAAA3EyNiLn8815.jpg
 
1 / 3通过简单地连接零件的大平面区域来制作四个接头。使用 CA 胶水我们的双面胶带
 

这样做之后,腿就可以完成了。在继续之前,最好确保所有 12 个舵机都居中。最好的方法是组装电子设备,见下文,连接所有伺服系统并加载代码。当 Arduino 启动时,所有伺服系统将居中(命令信号 90 度)。

上肢、大腿和安装轮子的部分(称为脚)具有与伺服喇叭配合的凹槽,伺服喇叭通常与舵机一起交付。将喇叭粘到凹槽中。确保使用适用于连接 3D 打印材料和制成喇叭的尼龙塑料的胶水。我用的胶枪很好用,一些更好的 CA 胶也可以。

完整的腿组件应如下图所示。首先将两个伺服组件连接到大腿部分。大腿与垂直方向成 30 度角。这将在车轮伺服中心与下臀部 alpha 伺服中心对齐时实现。使其尽可能靠近,并在组装好所有内容后微调代码中的中心位置(见下文)。

然后可以将脚部组装到它的伺服器上。车轮由 3D 打印的轮辋制成,带有一个 O 形圈作为“轮胎”。轮子用 M3 螺丝和螺母安装到脚上。在脚和轮之间使用两个垫圈,以使其尽可能平稳地滚动。

 
 
 
 
pYYBAGOIKq6AabbNAAA9PmDZ1Tc748.jpg
 
1 / 4组装好的前/后腿
 

然后可以将腿与身体组装在一起。保险杠的凹槽中应粘有伺服喇叭。最好的方法是将伺服驱动器安装到保险杠上,尽可能接近所需的角度,见下文,并用螺丝固定。然后可以将带有两条腿的完整保险杠安装到车身上,并用伺服螺钉固定保险杠。注意:伺服系统随附的所有螺钉都需要将伺服系统组装到髋关节和脚关节上。你可能有一些额外的安装螺丝,至少有备用伺服系统是个好建议,因为它们很容易坏掉。

下图显示了组装好的机器人。电子面包板应安装在机器人顶部。用尼龙搭扣将电池固定在“腹部”下方。可以取下来充电,也可以换上新充电的,还可以通过左右移动电池来调整重心。

 
pYYBAGOIKrOAbm6CAADQFEj_rzE160.jpg
组装好的机器人
 

添加超声波传感器和伺服

该项目的目标是借助安装在伺服系统上的超声波传感器 HC-SR04 实现自主导航。好吧,3D 打印部件方面的硬件已经准备就绪,功能本身已经与电子设备一起进行了测试。我只是简单地添加这些项目,因为它们在比赛截止日期时是这样的,你可以选择组装它们并稍微玩一下,或者编写自主导航和发布的代码。:)

前保险杠应更换为美国保险杠,传感器支架应组装在第 17 个舵机的顶部。伺服本身安装在前保险杠中。做这一切时,重心会向前移动。将机器人顶部的面包板移到后面是个好主意。

 
 
 
 
poYBAGOIK8SAMB8rAAwRynrsmmQ471.jpg
 
1 / 2为机器人添加美国传感器
 

连接电子设备

连接组件非常简单。然而,有些事情值得一提。在继续之前,我觉得有必要写一些关于 LiPo 电池的东西(我也在我之前的项目 KITtyBot 中写过免责声明)。

我使用完全没有保护的锂聚合物电池。这可能是有风险的,主要的危险是放电太快或太深。只要不是意外短路,第一个危险就可以避免。普通 R/C 电池的放电率为 25 C,在这种情况下允许 12 A。两个 UBEC 将防止它在任何情况下各自高于 2 至 3 A。如果电池电压降至 6 V,UBEC 无法为舵机和 MKR 提供电压,这恰好是低电压的限制,因此可以防止第二个危险。为了增加监控,Blynk 应用程序中安装了一个电压指示器。KITYBot 有一个主动电压监控,可以让机器人休息,但不需要它,因为机器人会在电压过高之前自行停止工作。

最后我必须强调,电池应使用专用充电器充电,并按常规小心处理,切勿在无人看管的情况下充电。电池应从机器人上拆下(使用尼龙搭扣安装)并在防火袋内充电,或至少与易燃材料保持安全距离,以便火势得以遏制且不会蔓延。还要安全地存放电池。

如果您不熟悉锂聚合物电池,请咨询当地的 R/C 业余爱好商店并购买电池以及合适的充电器,可能还有用于充电和储存的防火袋/容器。这些物品通常带有警告标志。阅读它们并运用您自己的良好判断力。:)

将两个 UBEC 连接到电池引线。还有另外两根电线直接从电池侧馈电。在我的例子中,这些“两根电线”是一根报废的伺服电缆,信号线(黄色或白色)已被移除。它整齐地安装在面包板上的公-公接头上。然后它变得类似于 UBEC 的电源输出线。

 
pYYBAGOIK8qAI_MYAAumOCu5zJM247.jpg
我将电池连接器连接到两个 UBEC 和电池电源线的方式。
 

如原理图所示,一个电源 UBEC 1 为伺服控制器供电。另一个 UBEC2 连接到面包板上的“上电源轨”,为 MKR 供电。如果需要,此轨稍后可用于为更多 5 V 设备供电,请参见下文。电池电源(在我的例子中是剥离的伺服电缆)连接到较低的电源轨。A1 引脚由此通过两个电阻馈电以测量电池电量。通过这两个电阻器,电池功率按比例降低,因此 10.6 V 转换为 3.3 V,从而为 8.4 V 的最大电池电压提供了相当大的余量。

当我第一次连接电子设备时,我遇到了抖动伺服系统的严重问题。这是一个已知现象,伺服控制器准备添加一个电容器来平衡电压振荡。我看到了“经验法则”,每个伺服使用大约 100 uF 的容量,在我的例子中加起来达到 1600 uF。我在我的东西中发现了一个 2200 uF 的电容器并焊接到卡上,一切正常。所提供的 3 A 对于所有这些数量的伺服系统来说有点低(如果所有 16 个伺服系统同时停止,最坏的情况是大约 8 到 10 A),但是随着电容器的增加,功耗的峰值可能是平了。

如果您想添加美国传感器和伺服器,还有另一个示意图显示要添加的内容。伺服和超声波传感器都在 5 V 下工作最佳。从面包板的 5 V 导轨供电。这些组件本身通过从 MKR1000 获取 3.3 V 信号来工作。但要注意一件事。来自 US 传感器的返回信号“回声”将为 5V。为了保护 MKR1000,分压器必须使用 2.2 和 1.0 K 电阻(或任何其他电阻比约为 1 比 2 的电阻对)。

Blynk 应用程序

这个项目真正的新颖之处在于使用 Blynk 以便在我的 iPhone 上拥有用户界面并能够通过 wifi 控制它。Blynk 的使用引起了对如何编写代码的重新思考。Blynk 的基本规则是:

  • 没有延误
  • 避免在 loop() 中有代码
  • 使用时间(而不是做上面的两个禁忌)

这样做的原因(我认为)是需要经常调用 blynk.run() 。如果不是,一切都会变糟。我计划重用和开发的 KITtyBot 代码肯定打破了第二条规则,因为它有几秒钟的冗长函数调用。我可以通过偶尔在代码中加入一个 blynk.run() 命令来让它工作,但是当阅读william hill官网 时,很明显核心专家说“使用计时”然后是“它不是 har根本”。我把这当作一个挑战并决定重写以适应“Blynk方式”

所以 Arduino 每 100 毫秒调用一次函数。执行此操作时,它要么读取按钮状态以接收新命令,要么继续执行 100 毫秒前的操作。滑板或步行步态由几个连续的动作组成,其中一些可以在 100 毫秒的间隔内执行,一些需要分成更小的部分,同步动作通常需要 500 毫秒。这一点,连同电源问题,在比赛截止日期前花了相当长的时间来解决。

操纵杆控制正常滑行。机器人是非常可控的,它可以前进和后退,也可以做非常急的转弯。我还添加了一个开关来将模式更改为一种叫做“舞蹈”的东西,在这种模式中,操纵杆改为控制身体在两个方向上的运动。添加更多内容是为了显示通过添加 Blynk 小部件和几行代码并使用我为 KITtyBot 开发的功能可以轻松添加新功能。正常行走和转弯的方式与 KITtyBot 上的相同,只需按下四个按钮之一,并在您想让它移动时一直按住它们(我必须做的“唯一”事情就是重新考虑 Blynk)。

电池指示器只需添加一个连接到 A1 的垂直电平即可。限制是 580 到 810。这个,10.6 V 是模拟引脚上的最大值 1023,电平测量值在 6.0 到 8.4 V 之间(电池应在该限制内运行)。小部件每秒更新一次。

如果添加了 US 传感器,则距离测量由标记值小部件完成。还添加了一个滑块来移动平移伺服。后者的值限制在 20 到 160 之间,以便在伺服系统 0 到 180 度的操作范围内发出命令(为端点提供 20 度的余量)。

下图显示了我如何在 iPhone 上组织小部件。我在 Arduino 代码的开头添加了关于如何定义每个小部件的注释。

 
pYYBAGOIK8yAKE4rAAB9mMEbPxQ814.png
我在 Blink 应用程序中的小部件。
 

校准舵机

这张来自 KITtyBot 的图片展示了如何定义不同的几何参数。相应的变量可以在 Arduino 代码中找到。

 
poYBAGNOTZGAAYlTAAAbvr1eYQE667.png
不同几何参数的变量
 

在使用机器人之前,应微调中心位置。这是通过在代码中编辑数组 servodeg0 来完成的:

const int servonum = 16; // The amount of servos
const float servodeg0[servonum] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};

这些值的顺序为 alfa、beta gamma 和前/左、后/左、前/右、后/右。所以右前方的beta是数组中的第八个位置或者servodeg0[7](数组的编号从0开始)。最后四个是脚舵机,顺序为 f/l、r/l、f/rr/r。

还有一个称为 servodir 的数组,用于定义舵机的旋转方向。

const int servodir[servonum] = {  +1, +1, -1, -1, -1, +1, -1, -1, -1, +1, +1, +1, -1, -1, -1, -1};

我使用的舵机沿逆时针方向从 0 度移动到 180 度。我在某处读到有舵机朝另一个方向移动。在这种情况下,阵列 servodir 必须一直改变它们的符号。

启动 Arduino 并检查所有舵机的角度。采取措施,看看一切看起来都是笔直和对称的。

然后在客厅地板上溜冰。:)


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'Arduino滑冰机器人',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);