×

自动通风物联网系统

消耗积分:2 | 格式:zip | 大小:0.37 MB | 2022-11-04

刘敏

分享资料个

描述

卧室空气的温度和湿度对于舒适的睡眠很重要。一般来说,我们开空调来调节温度,但是在睡前调节温度可能会很困难,因为开空调时可能会很冷,或者没有它会太热闷闷不乐。在我住的东京,除了仲夏的几天很热外,晚上并没有那么热,有时打开窗户让凉爽的空气进来就可以了。但是,即使开着窗户,早上可能会太冷,很难调节卧室的空气质量。需要注意的是,在日本的大部分地区,开着窗户睡觉是安全的。它是如此安全,以至于前几天有一只小猴子大惊小怪。

我们将创建一个物联网系统,根据温度计的数据自动打开和关闭房间的风扇。

由于许多元素协同工作,我们将依次解释每个元素。

它基于 Core2 教程和 esp-aws-iot 库中的示例代码,所以详细配置和构建设置请参考原文。

https://github.com/m5stack/Core2-for-AWS-IoT-EduKit/tree/master/Smart-Thermostat

https://github.com/espressif/esp-aws-iot/tree/master/examples/thing_shadow

SwitchBot仪表

这是一个通过 BLE 传输数据的温湿度计。协议已经分析过了,可以使用ESP32获取数据。

我认为它是最好的温度和湿度传感器,因为它很小,可以放在任何地方,并且可以使用 AA 电池运行一年以上。

在这种情况下,我要把它放在卧室的枕头附近。房间的温度在顶部和底部之间是不同的,在窗户和床头之间也是如此。需要反复试验才能确定在哪里测量温度。至少,如果温度计固定在控制系统旁边,我认为您无法真正进行舒适的调整。

Core2 -- 将温度数据发送到 AWS

通过 BLE 从 SwitchBot Meter 获取的温度和湿度数据被发送到 AWS IoT Core。它仅在数据发生变化时才发送数据。

Core2-main.c

Core2-switchbot_meter.cpp

这是基于恒温器教程中的代码,添加了 BLE 处理和更改 LED 颜色的命令。

我还修复了原始代码的 textarea 处理部分中的一个错误。如果我记得,我稍后会提出拉取请求。

云——根据数据确定粉丝行为

我想通过 AWS 服务以某种方式处理发送到 AWS IoT 的温度数据,并向控制风扇的设备发送一条消息,告诉它打开或关闭。

AWS 非常灵活,所以如果我现在将数据发送到 IoT Core,我可以稍后进行大量试验和错误,以确定使用哪个服务来处理数据以及如何处理。

在这种情况下,我们首先使用 Dynamo+Lambda 实现决策逻辑。之后,我们不得不切换到 IoT Core 规则中重新发布消息的方法。

DynamoDB+Lambda

我做的第一件事是将数据存储在 DynamoDB 中。

我们将以下查询放入 IoT Core 的 DynamoDBv2 规则中。

SELECT *, topic(3) as client_id, timestamp() as aws_timestamp FROM '$aws/things/+/shadow/update/accepted'

topic(3) 提取对应于thingName 的主题部分。

目标 DynamoDB 表是

分区键:client_id(字符串)

排序键:aws_timestamp(数字)

我们会这样设置。

接下来,我们将创建一个 Lambda。在这个 Lambda 中,我们将从存储在 DynamoDB 中的最新数据中读取一些数据,并根据这些数据发送命令来确定风扇行为。检索多个数据的原因是我们正在考虑使用时间序列变化或平均值作为做出决策的逻辑。

代码有点长,请参考链接。

v1-Lambda.js

当温度高于 30 摄氏度时,风扇打开。我还更改了 LED 的颜色,以便您了解它是如何工作的。

如果您定期运行此程序,例如每分钟运行一次,您应该能够根据温度控制风扇的开/关。

M5StickC -- 风扇控制器

现在我们已经有了在云端打开和关闭风扇的逻辑,下一步是创建实际运行风扇的设备。

我们本可以将这个功能塞进 Core2 中,但由于这是一个 IoT Core 项目,我们决定将它作为一个单独的东西来实现,并尝试与多个设备一起工作。

M5StickC 的 GPIO 无法输出足够的电流来运行风扇。如果要运行风扇,则需要使用继电器单元或类似的东西。

但是,这次我们将使用一种技术来单独使用 M5StickC 打开/关闭更大的电流。通过使用 I2C 操作电源 IC,我们可以打开和关闭 5V 输出。

pYYBAGNkf8uAcl_QAAEN_LQEEEo50.jpeg
 

它将 5V 引脚的输出转换为 USB 连接器并转动从 USB 获取电源的风扇。

请参阅代码链接中的文件 m5stickc_5v.cpp。

M5StickC-m5stickc_5v.cpp

注意:这种控制 5V 的技术仅适用于较新版本的 M5StickC。你需要比所谓的蓝色完美版本更新的东西。

Arduino + AWS 物联网核心

Core2 项目基于恒温器教程,所以它是一个 ESP-IDF 项目。它是使用 FreeRTOS 任务开发的,但似乎比 Arduino 更难。M5StickC 库和外围设备库可用于 Arduino,因此能够使用它们会很好。

AWS IoT 组件 ( https://github.com/espressif/esp-aws-iot ) 用于 ESP-IDF,所以我不能将它与 Arduino 一起使用。

我做了一些研究,找到了一种将 Arduino 核心库作为组件合并到 ESP-IDF 项目中并使用 Arduino 代码和库的方法。

按照此处的说明将 Arduino 内核嵌入组件中。我还在组件中安装了 AWS IoT 库。

现在,您可以在使用常用 Arduino 库的同时使用 IoT Core 组件。

M5StickC-main.cpp

代码与Core2 ESP-IDF项目的代码基本相似,但我感觉更好,因为我不使用FreeRTOS任务函数来处理每个任务。可能会有一些性能问题,但对于一个爱好项目,我认为这是一个不错的选择。

AWS IoT -- 规则重新发布

我使用 DynamoDB 和 Lambda 创建了风扇控制逻辑。但是,将所有消息存储在 DynamoDB 中并定期运行 Lambda 有点低效。我想我可以做得更好。

我设置了一个 Rule 来将消息存储在 DynamoDB 中,并且在这个 Rule 的 action 中,有一个 action 叫做 Republish。它可以接收消息、处理消息并发布处理后的消息。

查询现在看起来像这样。

SELECT 
  CASE current.state.reported.temperature > 27.5
  WHEN true THEN 1
  ELSE 0
  END
  AS state.desired.fanSpeed
FROM '$aws/things/012395fb0a29199a01/shadow/update/documents'
WHERE current.state.reported.temperature > 28.0 OR current.state.reported.temperature < 27.0

风扇在温度高于 28 摄氏度时打开,在温度低于 27 摄氏度时关闭。我们能够在如此短的查询中实现具有滞后性的逻辑。

AS state.desired.fanSpeed

来自此的 JSON 输出将如下所示。

{
    "state": {
        "desired": {
            "fanSpeed": 1
        }
    }
}

像这样设置主题的目的地。

$$aws/things/M5StickC-003/shadow/update

现在我们可以更新这个东西的影子了。

调试

AWS_PROFILE=awsiot-admin-202108 AWS_DEFAULT_REGION=ap-northeast-1 aws iot-data update-thing-shadow --endpoint-url "https://a15o79dfbws0i-ats.iot.ap-northeast-1.amazonaws.com" --thing-name "M5StickC-003" --cli-binary-format raw-in-base64-out --payload '{"state":{"desired":{"fanSpeed":1}}}' output.txt

此命令将允许您更新阴影。这对于验证系统的一部分是否正常工作很有用。

您可以使用 AWS 控制台中的测试工具,该工具允许您订阅和发布 MQTT,以查看和发送消息以进行调试。

您还可以查看 IoT Core 事物中的 Device Shadow 文档。如果某些东西不能正常工作,请使用这些来一一检查。

网页界面

通风系统连接到互联网。您可能想用智能手机控制它。

让我们使用网站构建框架 Amplify 为通风系统创建一个控制器。

首先,让我们以本教程为指导创建一个具有登录功能的网站。我使用了 Cognoto,但我认为其他登录方式也可以。

接下来,按照此 PubSub 文章中的说明配置您的站点。

这就是创建与 AWS IoT MQTT 通信的 Web 应用程序所需的全部内容。

完整的代码可以在链接中找到。放大-App.js

poYBAGNkf9GAD8LtAAUOejD1O-4082.png
Mac Chrome + 开发工具
 
pYYBAGNkf9SAJgyjAAEZ9KWgClE79.jpeg
iPhone 镀铬
 

结论

我们通过将设备与 M5Stack 的 ESP32 和 AWS 服务相结合,创建了一个用于自动通风的物联网系统。

ESP32 也可以使用 HTTP,所以可以连接普通的 WebAPI。到现在为止,我也使用过 HTTP。但是,通过这次使用基于 MQTT 的 AWS IoT,并结合 AWS 服务,我惊讶于 IoT 开发世界变得如此便利,甚至包括云端。

目前,我发现物联网设备可以简单地通过设备影子实现,并将它们连接到AWS,这使得后续结合云的开发非常容易。

通过使用 Amplify,我们能够创建一个系统,非常轻松地将 IoT 设备连接到智能手机和网络。

 


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

评论(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);