×

Homematic显示时钟开源分享

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

石胜厚

分享资料个

描述

我曾经在我们的客厅里有一个便宜且不准确的时钟,带有温度显示,我想用可以自行设置时间和日期的东西替换它,就像你今天所期望的那样。它还应该显示我可用的 Homematic 智能家居数据,例如温度传感器和其他信息(例如门铃传感器)。

由于市场上没有这样的设备,我决定自己制作。

我决定在这个项目中使用 Arduino“Mkr Wifi 1010”,主要用于 WiFi 访问能力和可用资源。有一些有趣的学习,我认为对于从同一个板开始的其他人可能有用(请参阅下面的详细描述)。

我的 HM 时钟显示的特点:

  • 准确的自设置时钟(访问 NTP 互联网时间服务以设置微控制器的 RTC)
  • 从 Homematic(或类似的智能家居系统)接收并显示 2 个温度(内部和外部)
  • 在明亮的 7 段 LED 显示屏上显示时间、日期和温度
  • 7 段 LED 将在夜间变暗(可编程)
  • 额外的 8x8 双色点阵显示器显示状态符号(例如 WiFi、温度或 NTP 更新等)
  • 可以显示附加信息(例如,我添加了一个由 Homematic 门铃传感器触发的可视门铃)
  • 可以通过网页控制(使用IP地址或路由器符号名在本地WiFi中访问)
  • 有备用电池,测量电源电压和电池电量(剩余百分比)并知道它何时由 USB 供电

使用的零件:

  • Arduino MKR Wifi 1010
  • 4x Adafruit 4 位 7 段显示器,带 I2C 背包 - 亮白色
  • 1 个带 I2C 背包的 Adafruit 双色 8x8 LED 方形像素矩阵
  • 可选:带连接器 JST PHR-2 的 LiPo Akku(3、7 V;1200mAh)

说明

1. 要构建自己的 HM 显示时钟,我建议从使用 Mkr1010 和通过跳线连接的显示器的面包板上开始。(这里不包括外壳的设计——也许我稍后会添加一些东西……但随后会作为 3D 打印版本)。硬件设置非常简单 - 请参阅提供的示意图:

  • 将 Mkr1010 板安装在面包板上并通过(微型)USB 电缆连接到您的 PC
  • 准备 5 个显示模块并将它们全部连接到相同的 I2C 总线(Mkr1010 的 SCL、SDA 引脚)和电源(3.3V 和 GND)。确保正确设置每个显示器的 I2C 地址,以避免地址冲突(请参阅下面的详细信息)
  • 在“5V pin”和“A1”之间以及“A1”和“GND”之间连接2个相等的电阻,例如2.2k作为简单的分压器
  • 可选择连接锂聚合物电池(3.7V;1.2Ah typ.);确保连接器的极性正确(详情见下文)就是这样。
 
 
 
poYBAGNYqHuARi9jABF1RXTpKYU216.jpg
 
1 / 3我的时钟的早期原型版本(这里我使用了额外的 16x2 Charactor LCD)
 

2.准备你的Arduino IDE:2.1首先将目标设置为“Boards - Arduino SAMD board - Arduino MKR WiFi 1010”(也许你想先尝试一些简单的Mkr WiFi 1010板示例)

poYBAGNYqH6AYT0BAAGjDAZpa7M637.jpg
Arduino IDE 板设置
 

2.2 然后为 I2C 驱动的显示器下载并安装必要的 Adafruit-LEDBackpack 库(请参阅 Adafruit 网站上提供的良好说明:https://learn.adafruit.com/adafruit-led-backpack/downloads)

2.3 获取我的 Arduino 源代码(见下文),它包含 3 个文件:

  • HMClockDisplay.ino - 主要源代码
  • menu_inline_css7.h - HTML 菜单源代码(用于网站)
  • symbols.h - 8x8 点阵显示的一些符号

确保它们都在一个文件夹中

2.4 在源代码开头的“用户设置”部分更改您的个人设置:输入您的家庭 WiFi 网络 SSID(名称)和密码,并根据需要调整您的时区和夏令时(DST):

// 用户设置 : // WIFI 设置char ssid[] = " XXX "; // 你的 WiFi 网络名称char pass[] = " YYY "; // 您的 WiFi 密码// 时区设置int GMT = 1; // 适应您的时区(例如德国是 GMT+1 -> 设置为 1 )int DST = 0; // 调整夏令时(默认 = 0:无 DST(冬季)

注意:对于初始测试,我建议使用您的“正常”本地 WiFi 访问(没有像访客 WLAN 那样的主要限制)以避免任何问题。

2.5. 编译并上传代码到Arduino板

使用串行监视器从设备获取详细信息以进行初始测试。会有许多日志输出,有助于理解 WiFi 连接问题等任何问题。

详细说明:

1.WiFi妮娜

Mkr Wifi 1010 板基于微控制器 SAMD21,连接到来自 u-blox 的模块 NINA-W10,这是一种在 2.4GHz WiFi 范围内运行的低功耗芯片组。要访问您的本地 WiFi 网络,提供的 WiFiNINA 库提供了所有必需的功能。有大量使用 WiFiNina 的示例和现有项目。请参阅以下可用文档:https ://www.arduino.cc/en/Reference/WiFiNINA

在我的项目中,我使用 WiFi 网络访问:

  • 访问互联网时间协议 NTP 以定期设置实时时钟
  • 提供一个简单的配置网页(基本上它充当一个小服务器)
  • 从我的 Homematic 智能家居系统接收数据以显示(温度等)
pYYBAGNYqIaAcuoPAAxcCjMgc8U088.jpg
启动后搜索WiFi
 

笔记:

  • 在 Arduino IDE 中初始设置 Mkr1010 板后,您可能需要更新 Nina 固件。可以在 Arudino IDE 中检查和更新版本。这个更新过程在上面提到的 WiFiNINA 网页中有描述。
poYBAGNYqIuAcjx4AAE9q79zrmE102.jpg
Arduino IDE 中的 NINA 固件更新程序
 
  • 要从本地 WiFi 网络轻松访问设备,请将网络路由器配置为始终使用相同的 IP 地址。大多数路由器还允许您分配设备名称(因此您无需在浏览器中输入 IP 地址)。我使用了“HMDisplayClock”,它让我只需输入http://HMDisplayClock就可以在我的 WiFi 网络中的任何浏览器中访问控制页面(或者,使用 Arduino Mkr 1010 板的 IP 地址当然也可以......)
pYYBAGNYqI2AGTFjAAGQNc32ozk160.jpg
一个简单但有用的网站,用于从本地 WiFi 配置 HM 显示时钟
 
  • 如果您想对自己的 WiFi 连接设备进行编程,该设备需要始终可访问,这里有一个提示:确保定期检查您是否仍然连接。您的路由器会不时断开设备与网络的连接...因此,如果您只建立一次 WiFi(在设置例程中),几个小时后您将失去连接。就我而言,我在“handleWifiClient”子例程中每秒检查一次连接。

2. 自调时钟

Arduino 将从返回“纪元时间”的网络时间协议(NTP) 服务获取准确时间。返回的“纪元时间戳”是自 1970 年 1 月 1 日以来经过的秒数。因此有必要将时间戳转换为人类可读的日期和时间信息。此外,必须进行时区和夏令时校正。调整时区的子程序基于 Doug Domke 的优秀作品“It's about time”(感谢分享!):https ://www.hackster.io/doug-domke/self-setting-super-accurate-时钟-5f1162

为此,Doug 的例程 fixTimeZone() 提供了很大帮助,因为调整时区可能相当复杂。微控制器(SAMD21)的内置实时时钟将使用此信息定期设置(我每小时更新一次)。一旦接收到成功的 NTP 更新,矩阵显示屏上的绿色“NTP”符号会亮起几秒钟:

poYBAGNYqJSAZUueAAzuUuFrPtU426.jpg
收到成功的网络时间协议 (NTP) 更新
 

3. 展示

为了可视化所有信息,我决定使用大而明亮的 LED 显示屏。它们可以安装在烟色玻璃盖后面,并允许时钟模块的精美设计。此外,我使用双色 8x8 矩阵模块来获取临时状态信息。

pYYBAGNYqJ6AaY2QABIWUQeIQ_8137.jpg
在前面板上显示模块
 

所有显示模块均由 Adafruit 制造,文档齐全并附带软件库。显示器由 I2C 控制(都连接在同一总线上),可由 3.3V 供电。(注意 Mkr1010 是3.3V设备,所以不要与 5V 部件混合使用!)。

  • I2C 寻址:使用多个模块,需要设置每个显示模块的 I2C 地址,以避免地址冲突。每个显示器上有 3 个“地址调整焊接跳线”。确保为每个模块设置不同的地址。有关详细信息,请参阅 Adafruit 页面:https ://learn.adafruit.com/adafruit-led-backpack/changeing-i2c-address在我的情况下,我选择了以下地址(请参阅设置例程): 时间显示模块:0x70 日期显示模块:0x71 Temp1 显示模块:0x73 Temp2 显示模块:0x74 矩阵显示模块:0x72
  • 电源预算检查:所有显示器都连接到 MKR1010 板 VCC 引脚,这是一个稳定的 3.3V 输出。MKR ZERO 的规格表明它可以提供高达 600 mA 的电流。MKR WiFi 1010 也是如此,因为它使用相同的稳压器 (AP2112K-3.3)。我的测量结果显示,由 3.3V 提供的所有 4 个显示器的总电流不超过 120mA,所以应该没问题。

4.家常整合

为了可视化来自 Homematic 智能家居系统的温度值等信息,中央单元 (CCUx) 需要通过本地 WiFi 连接将传感器数据提供给时钟。为此,CCU 使用参数访问时钟网页……像这样:“ http://HMDisplayClock /?tempR=20.5”

使用您自己的时钟版本,请先尝试在浏览器中手动输入...如果一切正常,它将将正确的温度显示更新为 20.5C,如下所示:

poYBAGNYqKSAXhdZAAoLHtoHoL4108.jpg
已成功接收到温度值更新(由“T”指示几秒钟)
 

然后按照以下步骤自动将数据从 Homematic 中央控制单元 (CCUx) 发送到时钟:

4.1.在 Homematic CCU 中安装以下两个插件:

a) XML-API:提供 xml 请求功能作为可用 HM 设备(例如传感器)的接口https://github.com/homematic-community/XML-API

b) CUxD Deamon:使用脚本命令 CMD_EXEC 将数据发送到使用 WiFi 访问的时钟

pYYBAGNYqKeAGpSZAAIfm6n_AVI942.jpg
需要在 CCU 上安装 XML-API 和 CUxD 附加组件
 

要在安装 CUxD 后首次启用 CMD_EXEC 功能,请输入设置并使用 CUx 守护程序中的“Exec”功能创建一个类型为“(28) System”的新设备,然后通过您的 CCU 收件箱确认新设备并重新启动您的CCU(此步骤的说明在这里(

4.2. 要选择应在 HM 显示时钟上显示的特定家庭传感器名称(数据点),请执行以下步骤:打开 XML-API 菜单:

设置-> 控制面板-> 附加软件-> XML-API设置->状态列表

...将列出所有执行器...

找到正确的 并将确切的名称复制到文本编辑器

例如“HmIP-RF.000ED8A9909BB2:1.ACTUAL_TEMPERATURE”

poYBAGNYqKuAPM0tAAPa41JXFEA474.jpg
如何为您的家庭温度传感器找到正确的“数据点”值
 

4.3. 创建一个简单的 CCU 程序来定期发送数据。就我而言,我希望我的室内和室外温度传感器每 10 分钟自动发送到时钟。

pYYBAGNYqK6AR2ehAALTMuJZ6Y4207.jpg
使用“时间模块”简单地每 10 分钟左右触发一个脚本......
 

为此,我创建了一个时间控制序列作为 CCU 程序,如上所示。此 CCU 程序将每 10 分钟执行一次,然后调用如下脚本:

字符串 Temp1 = dom.GetObject(" BidCos-RF.OEQ0670990:1.TEMPERATURE ").Value().ToString(2); 字符串 Temp2 = dom.GetObject(" HmIP-RF.000ED8A9909BB2:1.ACTUAL_TEMPERATURE ").Value().ToString(2); 字符串 url = " http://HMDisplayClock /?tempL="#Temp1;dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("wget -q -O - "#url); 字符串 url = " http://HMDisplayClock /?tempR="#Temp2; dom.GetObject("CUxD.CUX2801001:1.CMD_EXEC").State("wget -q -O -"#url);

用您选择的数据点替换上面第 1+2 行中的传感器对象(参见步骤 4.2)

(也许对您也有用:我使用这个有用的教程来增强我自己对该主题的了解(德语)

当然可以进一步扩展上述方法。就我而言,每次我的家用门铃传感器被激活时,我也用它来显示门铃符号。

 

pYYBAGNYqLSAZecIAAUpwIXP2wM366.jpg
另一个 Homematic 可视化:激活的门铃传感器将显示一个符号
 

 

最后——为了完整起见——你当然可以使用任何其他本地服务来代替 Homematic 来提供数据,只要你能以上述 http 访问格式发送信息。

5.电池(可选)

您可以选择使用锂聚合物充电电池在断开 USB 电源后保持时钟运行。Arduino Mkr WiFi 1010 板具有内置充电器 Li-Po 充电威廉希尔官方网站 (BQ24195),允许 Arduino MKR WiFi 1010 使用电池电源或外部 5 伏电源运行,在使用外部电源运行时为 Li-Po 电池充电.

poYBAGNYqLmACvQxAAq1LzS9bRk071.jpg
断开 (USB) 电源的时钟显示剩余电池容量
 

要在应用中检测USB-Power(+Charging)电池模式,测量 Mkr1010 板的“5V”输出引脚是一种合适的方法:如果测量到 5V 引脚上的电压在 5V 左右,则连接 USB 电源,如果使用电池,则为 3.3V。从 5V 引脚到 A1 和 GND 使用 2:1 分压器 (2xR) 来监控电压电平(因为没有 5V 可以提供给 3.3V ADC 输入!)。有关详细信息,请参见示意图。

要测量电池电压本身,请使用 Mkr1010 板上通过“sensorValue = analogRead(ADC_BATTERY);”提供的输入信号。

电压(3.3-4.2V)是剩余容量的一个很好的指标。我正在评估 5 个不同的级别(请参阅源代码)。

备注:

  • 使用锂聚合物可充电单节电池,3.7V,约 1024mAh Arduino 推荐
  • 电池的连接器类型是 JST PHR-2(在 Arduino 端是 JST S2B-PH-SM4-TB)。重要提示:检查 JST PHR-2 连接器的极性!板子的 USB 连接器在您的左侧,+ 应该是左侧引脚(朝向 USB 连接器),请参见下图。一些可用的锂聚合物电池极性相反幸运的是,如果需要,很容易改变连接器的极性。
poYBAGNYqL-AJj5jAAmOxSJa3TI453.jpg
确保你的锂聚合物电池的连接器有这个极性
 
  • 关于切换电源的重要说明- 这没有很好的记录:根据 Arduino,从一个电源切换到另一个电源应该自动完成。但是:如果 MKR Wifi 1010 使用锂聚合物电池运行,然后插入 USB 充电,则电流将受到极大限制!因此,CRG LED 会在一段时间后闪烁,并且威廉希尔官方网站 板会因电量不足而断电。这是由于以下限制:由于没有实现TI BQ芯片的USB监控功能(D+和D-),因此无法判断它是哪种电源。因此,BQ24195L 将安全值 0x30 写入 reg 0x00,从而将输入功率限制为 100mA。然后充电进入 DPM 模式,电池上的充电电压下降以限制电流。默认设置。就我而言,我正在使用看门狗重置(请参阅源代码)。肯定有更优雅的方法来解决这个问题(例如重新配置 BQ24195),但对我来说这已经足够了。
pYYBAGNYqMeAK_KVAAy60vvEbjs028.jpg
重新连接USB电源后,需要RESET
 

而已。我希望你喜欢这个项目。

 


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

评论(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:'Homematic显示时钟开源分享',//标题 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);