×

InqSpeedRacer用于HotWheels基于网络的电子测速仪

消耗积分:0 | 格式:zip | 大小:0.06 MB | 2022-10-27

386660

分享资料个

描述

InqSpeedRacer是用于 HotWheels® 的基于网络的电子测速仪。该项目是为学习运动物理主题的 8 年级科学课创建的。它也是创建InqPortal服务器的演示者,该服务器不仅服务于多个客户端,而且客户端可以连接到多个服务器。这可以很容易地用作家庭自动化的模板。创建多种InqPortal “服务器”,使用传感器、继电器和/或执行器来感知和控制环境。可以创建客户端仪表板以连接到所有服务器并监视和控制所有服务器。作为基于浏览器的应用程序的客户端可以在 Windows、Chromebook、Android、Linux 和 Apple 设备上运行。

硬件模块设计

这是一个相对较快的刻录项目。我们想为学生制作六个,并且我们想为后代保留一个……说实话……以防我们不得不支持修复错误。我们不得不订购零件。由于电子产品不是我们天生的强项之一,所以用“ Arduino photo diode ”这个短语搜索了大约三十分钟” 想出一个可行的威廉希尔官方网站 。30 分钟后,我们为 10 个 ESP8266 WeMos 板、电阻红外 LED 和红外光电二极管订购了足够的零件。最后一个我不确定有多少帖子发誓他们是光电晶体管,另一半说是二极管。我决定让我的狗再打一场。我所知道的是它们与 LED 的尺寸相同(5 毫米),并且它们有两根电线,威廉希尔官方网站 显示使用两根电线工作。我们试图在硬件方面牢记 KISS 原则。大约三天后他们出现了,我们把它放在面包板上,原型软件在大约三十分钟后运行。这是我们每个单位使用的零件。

  • 1 WeMos ESP8266 D1 Mini – 我更喜欢这些尺寸和防弹 USB 和 3.3v 稳压器。它们甚至可以由最古老、最便宜的 USB 微型交流适配器供电。即使是 250 mW 的功率也足够了。实际上,如果我们必须购买交流适配器,它的成本将超过InqSpeedRacer的其余部分
  • 2 个红外 LED——我想我烧掉了其中的一些以获得正确的限流电阻,因为卖家没有提供或提供任何信息。
  • 2 个红外光电二极管 – 同上燃烧
  • 3 个电阻器 – (1) 100 Ω 和 (2) 180 Ω

总支出——每台 InqSpeedRacerServer 不到 4 美元

poYBAGNYsQuAUtcPAB5Bbt3saJ4396.jpg
InqSpeedRacer 部分组装在 3D 打印外壳内
 

3D打印房屋

pYYBAGNYsQ6AFjMOAAFZZIkxUe0870.png
InqSpeedRacer 服务器的 3D 打印机模型
 

原型是用透明的 ABS 制作的,但它倾向于打印半透明的,你看不到里面的零件。但它的内置蓝色 LED 闪烁,拍出了令人惊叹的画面!其他设计特点包括

  • 低调
  • 有支架可以滑入轨道底部,以防止它被撞到。
  • 重量轻(< 19 克)– 足够轻,即使在没有支撑的下坡上,它也可以安装,不会显着改变轨道曲率。
pYYBAGNYsRaAHJJkAAs5SHsTLkg711.jpg
 

使用 InqPortal 的服务器软件

服务器端软件使用可在 Arduino IDE 库管理器中轻松找到的InqPortal库。该服务器的设计目的是让开发人员不必弄乱任何 WiFi、WebServer 逻辑。他们可以专注于手头的工作——速度陷阱。以下是有关服务器的一些详细信息。

  • 完全注释、完全基于 WiFi 网络的服务器 Sketch 的行数只有 140 行。 其中只有十行与 Web 服务器有关。剩下的就是监控光电晶体管,执行时序计算和注释。
  • 一辆车通过并向客户端报告速度后,它会自动重置并准备下一辆车通过。
  • 与其他InqPortal示例不同,这个示例实际上在 loop() 方法中做了一些事情。它利用了完全运行时的环路频率约为 100kHz。我用它来检查光束是否被汽车挡住。我最初做了一个中断版本,但代码复杂性并没有真正变得更好。这给出了 1/100, 000 秒的时间分辨率。这比我们向客户报告的毫秒分辨率要好得多。

这是代码,但请节省您的时间... InqSpeedRacer是您将InqPortal库下载到您的 Arduino IDE 后包含的示例之一。这里只是为了让您了解配置基于InqPortal的项目是多么容易。

#include 
// Works with InqPortal v5
// Can use NULL if you want to configure via InqPortal Admin 
// or hard code your router SSID and Password.
#define YOUR_SSID           NULL
#define YOUR_PW             NULL
#define DEFALUT_SSID        "InqSR"
#define VERSION             "3.0.0"
#define LED                 D4
#define PHOTO1              D1
#define PHOTO2              D2
#define LOG_LEVEL           1
#define CHK_FOR_RUN         50      // Check for a valid run (ms)
#define CHK_FOR_FAULT       1000    // Check to see if there is a fault (ms)
InqPortal svr;
// Published variables
float speed = 0;
u32 finish = 0;
// Working Variables (not published)
u32 tPhoto1Blocked, tPhoto1Unblocked, tPhoto2Blocked, tPhoto2Unblocked;
bool blockage = false; // To detect a continuous blockage and flash LED slowly.
void setup() 
{
   // Set up Interval callbacks
   svr.onInterval(checkForRun, CHK_FOR_RUN);
   svr.onInterval(checkForFault, PAUSE);
   // Publish runtime and persisted variables
   svr.publishRO("V", VERSION, sizeof(VERSION), "InqSpeedRacer Version");
   svr.publishRO("S", &speed, "Speed (m/s)");
   svr.publishRO("F", &finish, "Finish (ms)");
   svr.publishRO("T", NULL, "Server time (ms)", 
       []()->u32 { return millis(); });
   svr.autoSend(0);
   // Start the InqPortal server.
   svr.begin(DEFALUT_SSID, NULL, YOUR_SSID, YOUR_PW); 
   pinMode(LED, OUTPUT);
   pinMode(PHOTO1, INPUT_PULLUP);
   pinMode(PHOTO2, INPUT_PULLUP);  
   clear();
}
#define isBlocked(p) digitalRead(p)
#define LED_TOGGLE digitalWrite(LED, !digitalRead(LED))
#define LED_OFF digitalWrite(LED, true)
void loop() 
{
   // Sensor 1
   if (!tPhoto1Blocked)
   {
       if (isBlocked(PHOTO1))
       {
           tPhoto1Blocked = micros();
           set();
       }
   }
   else if (!tPhoto1Unblocked)
   {
       if (!isBlocked(PHOTO1))
           tPhoto1Unblocked = micros();
   }
   // Sensor 2
   if (!tPhoto2Blocked)
   {
       if (isBlocked(PHOTO2))
       {
           tPhoto2Blocked = micros();
           set();
       }
   }
   else if (!tPhoto2Unblocked)
   {
       if (!isBlocked(PHOTO2))
           tPhoto2Unblocked = micros();
   }
}
void set()
{
   svr.onInterval(checkForFault, CHK_FOR_FAULT);
   blockage = true;
   if (!finish)
       finish = millis();
   LED_OFF;
}
void clear()
{
   tPhoto1Blocked  = 0;
   tPhoto1Unblocked = 0;
   tPhoto2Blocked  = 0;
   tPhoto2Unblocked = 0;
   finish = 0;
   svr.onInterval(checkForFault, PAUSE);
   blockage = false;
}
void checkForRun(void*)
{
   if (!blockage)
       LED_TOGGLE;
   if (tPhoto1Blocked && tPhoto1Unblocked && 
       tPhoto2Blocked && tPhoto2Unblocked)
   {
       // WARNING - Don't mess with this.  Needed to handle wrapping
       // of the u32 coming from the micros()!!
       s32 t = (abs((s32)(tPhoto1Blocked - tPhoto2Blocked)) + 
                abs((s32)(tPhoto2Unblocked - tPhoto1Unblocked))) / 2;
       // This does the speed calculation based on the distance
       // between the two sensors of 19.7 mm and time in micro seconds.
       speed = 19700.0 / (float)t;   // m/s
       // Sends it out the the clients.
       svr.send("lflu", "S", speed, "F", finish);
       clear();
   }
}
void checkForFault(void*)
{
   // We added this in case we have false trigger.  After duration  
   // of CHK_FOR_FAULT (ms), it will clear out the times.
   // This checks if its still blocked... then we know something
   // is in the way.  We blink slowly.
   blockage = isBlocked(PHOTO1) | isBlocked(PHOTO2);     // Still blocked?
   if (blockage)
       LED_TOGGLE;
   else
   {
       svr.LOG(LOG_LEVEL, "Fault detected and cleared\n");
       clear();  
   }
}

使用 JavaScript 和 InqPortal 的客户端软件

客户端有两个应用程序(网页),JavaScript 编码实际上比服务器端编码长,分别为 105 和 240 行。第一页简单地报告了所有汽车速度的运行记录。它显示实际速度和假设 HotWheels 为 1:64 比例的比例速度。它还做了一些物理操作,并使用 KE = PE 估计掉落汽车的原始高度。单位可以从 mph 更改为 kph 和任何比例因子。

从开发人员的角度和家庭自动化的角度来看,第二页在技术上更有趣。InqPortal有能力编写一个可以与多个InqPortal服务器对话的客户端。服务器不必是同一个项目。家庭自动化的优势很简单……您可以拥有一个仪表板,连接所有各种设备,并从一个客户端检索和控制所有内容……而且由于它是基于浏览器的,它可以在 Windows、Android、苹果和 Linux。在此示例中,我们将其设置为连接到多个InqSpeedRacer服务器充当终点线......就像松木德比。代码有点复杂,不是因为多服务器访问,而是因为客户端必须标准化所有服务器时钟,以便它可以比较汽车穿过各个服务器“终点线”的时间。

poYBAGNYsR2AVeYrAAFvgdpXXBk961.png
多服务器连接充当终点线裁判
 

开始...

... 构建您自己的InqSpeedRacer ,您首先需要在您的 Arduino IDE 库管理器中下载InqPortal库。它将包含示例中所有必要的服务器和客户端文件的完整副本。有关该项目的更多详细信息,请访问InqSpeedRacer 有关InqPortal库的更多详细信息,您可以查看我的其他 Project Hub 项目使用 3 行代码制作 WebServer! 完整的交叉参考手册和教程可以在InqOnThat.com/InqPortal/上找到


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

评论(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:'InqSpeedRacer用于HotWheels基于网络的电子测速仪',//标题 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);