×

ESP8266空气质量指数显示

消耗积分:2 | 格式:zip | 大小:0.10 MB | 2023-01-04

王尚岱

分享资料个

描述

冬天我在中国的一个大城市,不幸的是,这是造成空气污染的良方。我几乎每次出门都会检查 AQI(空气质量指数),这样我就知道我是否需要戴 N95 口罩。AQI 并没有可靠地显示在我手机的天气应用程序中,而且每次都在线查找它很乏味。我的室友建议我建造一些东西来持续显示 AQI,这样我们所要做的就是看它。

因此,我介绍了 AQI 显示。NodeMCU ESP8266 开发板连接到 wifi,并根据一天中的时间每 20 分钟或每小时查询一次 AQI API。我认为它不需要在我睡着的晚上更新那么频繁。它通过查询 NIST 时间服务器知道现在是什么时间。在查询之间,ESP8266 深度睡眠(关闭 Wifi、CPU,除实时时钟之外的所有东西)以节省能源。

------------------------------------自己制作的步骤-------- ------------------------------

1) 通过 Arduino IDE 与 NodeMCU ESP8266 开发板对话:

这些说明包括一个闪烁程序,可确保您能够闪烁 ESP。

2) 空气质量指数 API:

此页面解释了公开的各种 API。我们想使用 JSON 格式的。

这是 JSON API 的特定文档:

API 请求是通过访问以下 URL 发出的,

接下来,在 aqicn.org 上搜索您所在的城市。进入城市网页后,如果您需要更多本地化数据,可以单击地图上城市内的特定站点,将您带到站点页面。例如,北京城市页面为http://aqicn.org/city/beijing/

我们想找到城市或车站的 4 位数索引,但网页本身似乎没有显示。因此,一旦您位于适当的页面,请查看该页面的 HTML 源代码并搜索“idx”。至少一个搜索结果应该在一个 JSON 块中,该块将 idx 列为一个 4 位数字。如北京城市指数为1451,美国驻北京大使馆站指数为3303。

现在您可以通过网络浏览器进行测试 API 调用。如上构造 URL(不要忘记索引前的“@”)并访问它。您应该会收到一个 JSON 响应,其中包含 AQI 等许多内容。

在我的测试中,API 通常会向 ESP 返回非 200(即以某种方式失败)的 HTTP 响应,因此我的代码将发送请求,直到请求成功或达到最大错误数。您可以在文件顶部附近的常量部分更改最大错误数和其他常量。

3)接线

请参阅下面的 Fritzing。

4)修改刷写代码:

修改标记为“CHANGE ME!”的三行 在代码中(参见下面链接的 github 存储库)以反映您的 Wifi 凭据和 AQI 站和令牌。然后通过 Arduino IDE 使用此代码闪存开发板。如果您还没有 Adafruit SSD1306 和 Adafruit GFX 库

----------------------------------------代码注释---- ----------------------------------

1) 解析 API 的 JSON 响应:

2) 现在几点了?

为了尽量减少不必要的 API 请求数量并节省电量,我希望 AQI 显示在我睡着的晚上不那么频繁地更新。

简而言之,预期行的形式为:JJJJJ YR-MO-DA HH:MM:SS TT LH msADV UTC(NIST) OTM。请注意,此格式与上述教程所说的不同。

例如:58537 19-02-23 08:15:31 00 0 0 420.9 UTC(NIST) *

3)启用深度睡眠:

深度睡眠很酷,因为它会关闭除实时时钟以外的所有功能以节省电量,然后在设定的时间后醒来。这个时间以微秒为单位指定,并存储为 32 位整数,因此 ESP 可以深度睡眠的最长时间约为 71 分钟。

在指定时间段休眠后,ESP 通过将 GPIO16(NodeMCU 开发板上的引脚 D0)驱动为低电平来唤醒自己。因此,确保引脚 D0 连接到电路板上的 RST 引脚(参见下面的 Fritzing)。

要进入深度睡眠,请使用这行代码:ESP.deepSleep(time_to_sleep_in_us);

4)控制显示:

我买的 OLED 兼容 Adafruit 的 SSD1306 驱动程序,所以我只包含了 Adafruit_SSD1306 库并修改了他们的示例代码。

在 OLED 屏幕上显示内容的代码非常复杂。制作一个通用函数或一组可以自动适应屏幕并显示任意文本的函数会很好。

或者,我们可以尝试其他类型的显示器,例如 LED 矩阵或某种投影。

最后,了解该项目使用 2 节 AA 电池或其他非墙上电源可以运行多长时间会很有用。到目前为止,我只用过它,因为手机移动电源在我连接到它们后不久就会自动关闭。我猜这是因为它没有吸收足够的电量,所以移动电源假设没有插入任何东西。


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

评论(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.lene-v.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:'ESP8266空气质量指数显示',//标题 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.lene-v.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);