×

打开/关闭阀门并监控远程流量的开源硬件

消耗积分:0 | 格式:zip | 大小:0.15 MB | 2023-01-31

分享资料个

描述

监测液体和气体转移很困难。

大多数用于处理传输的现代系统包括许多管道部分,每个管道都可以通过截止阀隔离或连接到系统的其他部分。

管理这些众多的连接点是一项挑战,并且经常需要技术人员手动访问阀门以执行关闭。为了避免这些手动过程,设施管理人员希望能够远程打开和关闭阀门,并能够监控整个系统中液体或气体的流速。

这就是为什么我们在Blues Wireless建立了一个基于蜂窝的项目来远程监控液体通过管道的流速,以及一个网络应用程序,设施经理可以使用它来根据需要打开和关闭阀门。

在本文中,您将看到它是如何工作的。我们将从查看如何连接必要的硬件开始,然后查看设备的固件和项目的 Web 应用程序如何工作。

让我们开始吧。

组装硬件

此构建所需的主要硬件是:

  • 一个电磁阀(可以打开和关闭)。
  • 流量计(用于测量流量)。
  • 以及一种发送和接收数据的方式(这样您就可以控制您的阀门并远程获取流量计的读数)。
注意:如果您的项目只需要测量流量(不需要电磁阀),请在 GitHub 上查看我们的流量监视器项目。

对于电磁阀,我们使用了DIGITEN 电磁阀对于流量计,我们使用了GREDIA 水流量传感器为了远程监视和控制系统,我们使用了Blues Starter Kit中可用的各种组件

Blues 入门套件包括一个蜂窝 Notecard ,这是一个蜂窝和支持 GPS/GNSS 的设备到云数据泵,预装了 500 MB 的数据和 10 年的蜂窝服务。

poYBAGPXIRCADC4nAACgxtIkaMI556.png
 

Notecard 本身是一个微型 30x35mm 系统模块,带有 M.2 连接器,允许我们通过蜂窝连接发送和接收必要的数据。

为了使 Notecard 易于集成到现有原型或项目中,Blues 入门套件还包括一个称为Notecarrier-F的主机板,其中包括一个用于 Notecard 的连接器,以及一组用于任何与 Feather 兼容的 MCU 的接头.

pYYBAGPXWDCAeAqJAAGCwln6cDQ900.png
 

Blues Starter Kit 的最后一部分是Blues Wireless Swan ,这是我们将用来运行该项目固件的 MCU。Swan 是一款采用 STM32L4 的开发板,具有 2MB 闪存和 640KB RAM。它支持 C/C++、Arduino 和 CircuitPython,并且与 Feather 兼容,因此可以很好地插入 Notecarrier-F。

要组装 Blues Starter Kit 的硬件,您可以完成Notecard 的快速入门教程,之后您将拥有一个看起来像这样的设置。

pYYBAGPXWDOAK_L1AAJQfGZRvrk267.jpg
 

使用 Blues 入门套件,您可以将数据发送到(和从)云后端,我们将使用该功能来控制我们的电磁阀,并监控流量计的读数。

入门套件准备就绪后,我们接下来使用下图所示的接线图将电磁阀和流量计连接到 Notecarrier-F。您不必完全按照我们所做的那样进行设置,但如果您这样做,请务必查看我们正在使用的设备的完整列表。

pYYBAGPXWD6AO21iAAESrnFYaqw466.png
 

无论您最终使用的硬件是什么,您都必须满足以下要求才能使该项目的固件正常工作。

  • 电磁阀的信号线必须连接到Notecarrier的F_D6引脚。固件使用此引脚打开和关闭螺线管。
  • 流量计的信号线必须连接到Notecarrier的F_D10引脚。固件使用此引脚从流量计读取流量。
  • Notecarrier 的F_D13引脚必须连接到 Notecarrier 的ATTN引脚。每当 Notecard 收到打开或关闭电磁阀的命令时,固件都会使用它来响应中断。

当一切都放在一起时,您的构建应该看起来像这样。

poYBAGPXWESAepDIAAMuhuTaJ88277.jpg
 

如果您选择使用外壳(例如我们在这些图片中使用的来自 Sixfab的外壳),您的项目可以放入一个易于安装在大多数设施中的盒子中。

pYYBAGPXWEeADDxaAAMHg99B2C0624.jpg
 

这样一来,您现在就拥有了通过 Swan 控制电磁阀和监控流量的所有连接方式。但要这样做,您必须首先设置一个用于发送和接收数据的云后端。

云设置

Notecard 的一大优点是它知道如何开箱即用地将数据发送到云后端 Notehub。Notehub是一种托管服务,旨在连接到 Notecard 设备并同步数据。

如果您正在跟进并想自己构建这个项目,则需要在 notehub.io 上设置一个免费帐户,然后创建一个新项目。

poYBAGPXWEqAY3oCAABXyXK5lpA501.png
 

创建项目后,请确保复制新项目的 ProductUID(请参见下面的屏幕截图),因为您需要该标识符才能将 Notecard 连接到新的 Notehub 项目。

poYBAGPXWEyART4CAAA6i3LYn7w901.png
 

您将在整篇文章中了解有关 Notehub 的更多信息,但现在您已经设置了后端,接下来让我们看看使阀门监视器项目正常工作的代码。

编写固件

该项目的固件负责与 Notecard、电磁阀和流量计进行通信。

GitHub 上提供了实现这一目标所需的完整源代码,但我们将在此处展示最重要的部分。我们使用Platform.io构建应用程序,使用以 Swan 为目标的 Arduino 应用程序。(这里是让所有这些在您的设备上运行的说明,其中包括添加您之前从 Notehub 复制的 ProductUID。)

管理阀门

固件必须做的最重要的事情是管理电磁阀的状态。我们的电磁阀默认是关闭的,固件必须在收到 Notecard 的命令时提供电源来打开阀门。

为此,固件首先使用其 card.attn 请求武装 Notecard 以接收中断。

// Configure ATTN to watch for changes to data.qi.
req = notecard.newRequest("card.attn");
const char *filesToWatch[] = {"data.qi"};
int numFilesToWatch = sizeof(filesToWatch) / sizeof(const char *);
J *filesArray = JCreateStringArray(filesToWatch, numFilesToWatch);
JAddItemToObject(req, "files", filesArray);
JAddStringToObject(req, "mode", "files");
notecard.sendRequest(req);
注意:关于 Notecard 的一件很酷的事情是它的 API 都是基于 JSON 的——所以要使用 Notecard,您可以发送简单的 JSON 对象,并且(如果需要)接收返回的 JSON 对象作为响应。

配备 Notecard 后,它会在收到我们称之为Note的任何时候收到中断Note 是包含开发人员提供的正文的 JSON 对象,是 Notecard 与其 Notehub 后端之间的主要通信方式。

要发送笔记,您可以使用Notehub API 的 note.add 请求,该请求将数据发送到您的 Notehub 后端,后者又立即将该数据转发到您的 Notecard 设备。

并且因为 Notecard 在收到某些 Notes 时准备好中断,固件可以响应传入的 Notes 并打开或关闭电磁阀。具体来说,固件会查找具有以下 JSON 结构的注释。

"body": {
    "state": "open" // or "close"
}

固件具有响应该中断并根据需要打开或关闭电磁阀的功能。

// Toggle the valve's state. If open, close, If closed, open.
void valveToggle()
{
    if (state.valveOpen) {
        digitalWrite(VALVE_OPEN_PIN, LOW);
    }
    else {
        digitalWrite(VALVE_OPEN_PIN, HIGH);
    }
    state.valveOpen = !state.valveOpen;
}

从流量计读取数据

固件的下一个任务是监控流量计的流量,并定期将该值报告给云端后端。

每当有 2.25 mL 的流体通过时,流量计的信号线就会发出脉冲。因此,作为第一步,我们配置一个中断处理程序,每当我们在信号线上看到从低到高的转换(“下降”)时都会触发该中断处理程序。

attachInterrupt(digitalPinToInterrupt(FLOW_RATE_METER_PIN), flowMeterISR,
    FALLING);

在该中断处理程序中,我们增加一个计数器来跟踪发生了多少脉冲。

void flowMeterISR()
{
    ++state.flowMeterPulseCount;
}

最后,我们通过跟踪自上次测量以来发生的脉冲数(默认为每 500 毫秒)来计算以 mL/min 为单位的速率。

// Calculate the flow rate in mL/min.
uint32_t calculateFlowRate(uint32_t currentMs)
{
    return 60000 * (state.flowMeterPulseCount * 2.25) /
           (currentMs - state.lastFlowRateCalcMs);
}

一旦固件有了流量值,它的最终任务就是将该数据发送到云端后端。为此,固件使用 Notecard 的 note.add 请求来格式化和发送流量和阀门状态(打开或关闭)。

J *req = notecard.newRequest("note.add");
if (req != NULL) {
    JAddStringToObject(req, "file", file);
    JAddBoolToObject(req, "sync", true);
    J *body = JCreateObject();
    if (body != NULL) {
        JAddNumberToObject(body, "flow_rate", flowRate);
        if (state.valveOpen) {
            JAddStringToObject(body, "valve_state", "open");
        }
        else {
           JAddStringToObject(body, "valve_state", "closed");
        }
        JAddItemToObject(req, "body", body);
    }
    notecard.sendRequest(req);
}

此时,如果您将固件闪存到您的设备,并开始让水流过您的系统,您将开始在 Notehub 项目的事件选项卡中看到流速读数。

起初,您的所有读数的流速都将为零,因为电磁阀开始关闭并且不允许任何液体通过。

pYYBAGPXWFSADAELAAB-qb_3x_Q097.png
 

但是,如果您使用 Notehub API发送 data.qi 注释以打开阀门,您将开始看到以毫升/分钟为单位的速率。

poYBAGPXWFaARPn9AAAmhvJvFiQ472.png
 

此时,您现在拥有能够打开和关闭电磁阀以及从流量计进行测量的固件。

这一切都有效!但是必须去 Notehub 查看你的数据,并且必须使用 Notehub API 发送命令来打开和关闭阀门,这有点麻烦。因此,为了简化这些过程,我们还为该项目构建了一个 Web 应用程序。

使用仪表板

该项目的 Web 应用程序通过为设施管理员提供一个单一位置来查看和管理其系统中的所有设备,将所有内容整合在一起。

除了能够打开和关闭阀门以及查看流量外,我们还允许设施管理员配置流量阈值,并在其设备的流量落入意外范围时触发警报。

pYYBAGPXWFmADvjFAAF4xFkKlAQ912.png
 
注意:在我们的例子中,我们在网络应用程序中显示警报,但您也可以使用 Notehub 在警报发生时发送 SMS 消息。有关详细信息,请参阅我们的Twilio SMS 指南

与此项目的所有内容一样,阀门监控 Web 应用程序是开源的,可在 GitHub 上获取,因此您可以随意逐字使用它,或对其进行自定义以满足您的需求。

Web 应用程序会在您使用系统时实时更新,因此这是测试硬件和固件是否按预期工作的好方法,因为您可以在测试硬件时看到流量显示在 Web 应用程序中。

最后的想法

总体而言,该项目为任何执行液体或气体传输的设施增加了自动化和智能化。您可以利用物联网的力量来自动化阀门控制和流量监控,而不是依赖技术人员执行手动操作。

该项目的固件和 Web 应用程序是开源的,因此请随时在 GitHub 上查看它们并根据需要进行调整。

还有一件事——这个项目是我们在 Blues 构建的一系列加速器的一部分,所以如果您感兴趣,请查看完整列表,如果您有任何问题,请访问我们的william hill官网 。


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

评论(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:'打开/关闭阀门并监控远程流量的开源硬件',//标题 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);