喝水方案升级之路

Posted by boydfd on 2024-11-10 15:00:00 +0800

You may find interesting:


大语言模型中一个调皮的EOS token


大语言模型中一个调皮的EOS token

ChatGPT对文章的摘要

这篇博客讲述了作者在家庭日常用水管理方面的改进经历。由于家里用水量增多,作者不断优化解决方案,从最初用农夫山泉桶装水,到购买反渗透净水机,再到通过智能化手段简化补水流程。过程中,作者不断提高设备自动化程度,最终实现了全自动化补水,并且详尽描述了每个优化步骤和使用的技术(如Node-RED、homeassistant、小米设备等)。此外,作者还介绍了如何利用压力传感器和智能控制来实现更精确的水量控制,并用语音命令来实现自动接水功能。同时,还记录了优化过程中的一些挑战及解决方案。

背景

自从家里多了个娃之后,家里的水消耗量成倍增加。所以我就增加了一个固定任务,给恒温饮水机灌水,饮水机的容量是4.5L(为啥不是5L,因为买的饮水机有个很坑的点,最后剩下的一点水是没法接的),而我们家现在,算上宝宝一共有4口人,而一个成年人一天饮用水的量在1.5L到2L左右,这就意味着,我一天很有可能要换2次水(为啥不是必须,因为大家都很容易忘记喝水,我不是特指谁,包括在座的各位)。

一开始,我家用的是5L的农夫山泉桶装水,这个水最难受的就是一桶水没法一次倒完,会剩下0.5L,这就很难受了。每次倒水都需要抬臂两次倒水(需要先把上次的水倒进去),实在不够高效。

于是,我后面就换成了4L的水,这优化带来了很长一段时间的舒适感,就好像之前每次要执行两步的操作,写了个脚本只需执行一个命令一样舒畅。

事情的转机发生在了今天4月份,在一个直播间半价抢到了一个ro膜反渗透净水机。

这次的升级是价格,按照4桶x5l的水30块钱左右的售价,一年大概需要2200左右的水费。 而这台机器我才花了1500,算下来,已经回本1200左右了,所以用净水机确实是个很实惠的方案。

这下问题变成了,怎么将净水机里的水倒到恒温饮水机上了。这就不得不提我家这个饮水机的一个优点了,他是可分离的,也就是盛水的水箱是可以直接卸下来的。

小番外

当初买这个也是因为身处南方,最令人苦恼的就是蟑螂了,而蟑螂非常喜欢待在电器里面,我家在去年3月份的时候就发生过蟑螂入侵的情况,大量的小蟑螂混迹在电饭煲和恒温饮水机里。大家可以想象一下,喝完了水,然后要换水的时候,发现两只小蟑螂躺在水箱里的绝望感。尤其是在清理完,并换了一个位置后,蟑螂发生了迁移(其实就是待在了机器里面),再一次打开盖子,发现又喝了一段时间蟑螂的洗澡水的深深的绝望。 所以后面就换成了这种分离式的,并且一开始就把机器放在阳台旁边,每天有充足的阳光照射,顺带一提,电饭煲也换新,并放在了阳台旁。(换了之后再也没发现蟑螂了,南方的朋友可以参考这个思路)。

方案升级之路

方案一

既然饮水机是可分离的,我就可以只提着这个水箱去接水,并且净水机是可以设置出水量的,所以流程就变成了,

  1. 拿水箱去水槽
  2. 放20s左右的水,等tds降低
  3. 按下按钮
  4. 过几分钟后回来把水箱放回去。

想必大家在这肯定能感受到过几分钟再xxx的这种难受,平时工作中如果某个完整的任务中间出现了,等xxx程序跑完再执行另外一个命令,那我们一定要写个脚本一步到位,省去了中间反复人肉检查的过程。

补充一下,第一杯水tds高的原因(来自GPT):

  1. 滞留水的积累:在停止使用期间,净水器中的残留水可能会停留在滤芯和膜中,这些滞留水会与滤芯和反渗透膜中的溶解物质持续接触,导致其TDS值升高。当你重新开始使用净水器时,这些滞留的高TDS水首先被冲出,因此第一杯水的TDS值会较高。

  2. 系统冲洗不足:重新使用时,如果没有进行充分的冲洗,一些微小污染物和沉积物可能会积累在系统的各个部分。当水重新流过这些部分时,TDS值会上升。因此,重新使用净水器前通常需要进行冲洗。

方案一架构

alt text

方案评估

  • 经济性:10分
  • 减少工作量程度:1分
  • 上手简单程度:10分

方案二

那就给升个级,净水器的出水管路可以给加个3通,一路给龙头,一路给饮水机,然后加上一个电磁阀,就可以控制水的通断了。最后加上一个米家的智能插座,就能通过米家进行补充水了,这样优化顺带解决了每次接水还需要提着一桶5kg的水走好几步路,最后还得准确地把水箱放上去的问题。

这样流程就优化成了

  1. 放20s左右的水,等tds降低
  2. 喊小爱帮忙补充水(设置一个定时,每次补充1分钟的水)

方案二架构

alt text

方案评估

2水管+电磁阀+智能插座+ 24V电源 = 10 + 15 + 30 + 10 = 65元

  • 经济性:7分
  • 减少工作量程度:7分
  • 上手简单程度:8分 (需要给电磁阀接线)

方案三

再看看还有啥优化的?对,你没猜错,又是一个等待。虽然只有20s,但是我就是不想等呀。解决思路其实也很简单,再加个电磁阀和三通,它的目的是把水放走。

这样流程就优化成了

  1. 定期确认水剩多少,比较少了就喊小爱补充水 1.1 小爱先打开排水电磁阀 1.2 持续检测出水的tds值 1.3 如果tds低于10,就关闭排水,开始给饮水机补充水

哈哈,这下只有一步了。

方案三架构

alt text

方案评估

方案二 + 电磁阀 + 智能插座 + 三通 + 2分管 + 24V电源 = 65 + 15 + 30 + 5 + 10 + 10 = 135元 (如果要监控TDS值,需要再入手一个小米中枢网关,使用极客版功能,这个就比较贵了,先不算在里面了)

  • 经济性:6分
  • 减少工作量程度:8分
  • 上手简单程度:8分

方案四

再看看还有啥可以优化的?(什么!还能优化?),现在就剩下人需要定期确定一下水还剩多少了,那有没有办法让传感器帮忙确认呢。肯定是有的,市面上检测水位的传感器很多,问了下GPT,有了以下的备选方案:

  1. 超声波传感器:通过发射超声波并接收反射波来测量距离,从而计算出水位高度。优点是非接触式测量,不会污染水质;缺点是测量精度受水面波动影响较大。(对于我家这个饮水机来说,传感器有点大,不太适合直接放在水箱里,它比较适合大型容器中)。
  2. 浮球开关:最简单的水位检测方案,通过浮球随水位升降来触发开关。优点是结构简单、成本低;缺点是只能检测固定的水位点,而且有机械磨损,(这个肯定也不适合,一是浮球占用了水箱的空间,二是它只能测一个固定水位点,我需要判断什么时候需要补水,什么时候停止补充水。)
  3. 电容式传感器:利用水和空气的介电常数不同来检测水位。优点是精度高、响应快;缺点是价格相对较贵,且需要定期校准。(这个也不适合,要求是非金属水箱。)
  4. 压力传感器(注:也就是秤):通过测量水的压力来计算水位。优点是结构简单、精度高;缺点是需要安装在容器底部,可能会有漏水风险。(最终我选择了这个方案,因为它是非接触式的,并且精度高,价格也合适,同时它还有另外一个用途,后面会提到哈。)

最终的流程就优化成了:

  1. 压力传感器实时监测水位
  2. 当水位低于预设值时,自动触发补水流程 2.1 打开排水电磁阀 2.2 持续检测出水的tds值 2.3 如果tds低于10,就关闭排水,开始给饮水机补充水 2.4 检测到压力大于预设值,就关闭补水电磁阀

终于完全实现了全自动化,再也不用操心补水的问题了。

方案四架构

alt text

方案评估

方案三 + esp32 + 半成品高精度秤 = 135 + 20 + 90 = 245元

  • 经济性:5分
  • 减少工作量程度:10分 (完全躺平)
  • 上手简单程度:3分 (需要开发esp32程序)

细说最终方案的软件实现

智能家居其实就3部分:

  1. 感知
  2. 大脑
  3. 执行

让我们分别来看一下这个系统在这3个方面的实现:

感知

压力感知

压力的感知来自压力传感器,通过esp32的io管脚连接后就可以在esp32程序中进行处理。这部分数据我们想让它放哪就放哪,我这边选择把数据写入到了MQTT中,MQTT(Message Queuing Telemetry Transport)是一种轻量级的基于发布/订阅模式的消息传输协议。很多智能家居平台都支持MQTT协议,所以后面处理起来会非常方便。

出水口tds传感器

净水器是接入米家的,所以tds的数据需要从米家读取。

第一个问题就来了,怎么能把我的数据和米家的数据放到一起,然后用一段逻辑进行处理呢?

方案有两个:

  1. 可以通过巴法云把我的数据写到米家,然后看在米家是否有地方可以进行逻辑处理: 目前米家能实现比较复杂的逻辑的地方是米家中枢网关提供的米家极客版,但是,即使是极客版,可定制的逻辑还是有限,所以我没有选择这个方案。
  2. 把米家的数据拉过来,然后我在某个地方统一进行处理,这个自然就是homeassistant了,无比强大的智能家居平台(我把我家的美的设备、海尔设备、米家设备统统都接进去了。)

大脑

大脑其实就是决定在获取到XXX数据后,需要执行什么操作。homeassistant本身提供了一些自动化的功能,但是这个功能比米家极客版还要弱,所以我最终的选择是Node-RED,Node-RED是一个可视化编程工具,可以非常方便的进行逻辑处理,还支持一堆插件,有些逻辑很复杂还能通过写js来处理,所以很方便。

执行

其实所有需要执行的东西都是米家的智能插座,所以肯定是要通过某种方式来调用米家的api的,而homeassistant也帮忙解决了这个问题,通过homeassistant的米家插件,就可以非常方便的调用米家的api。

最终的架构

alt text

再进一步

你以为到这就结束了?不,我还有个痛点,就是买的这个饮水机它没有定量出水的功能,所以接水的时候,还是要在旁边一直按着接,再等到水接满了,再放开,这个设计真的很反人类。所以我就想着,我这不是有了重量检测么,那我要接多少水,靠重量不就搞定了?所以我就更进了一步,让它支持语音控制来进行定量出水。

任务拆解

用感知、大脑、执行的思路来分析一下这个任务:

感知

  1. 语音命令
  2. 出水量(可以用压力感知来替代)

大脑

  1. 语音识别ASR
  2. 语音理解NLU
  3. 出水量控制(可以用代码逻辑来实现)

执行

  1. 按下饮水机的出水按钮
  2. 回复用户信息

方案选型

语音命令

之前我写过一个关于自制小爱音箱的文章,后续其实是我还是在用小爱音箱,因为自制的音箱的成本还是挺高的,家里要用好多个音箱,最终还是投奔了小爱音箱。那这次就尝试一下通过小爱音箱来控制饮水机的出水吧。

小爱音信本身解决了语音命令的感知,大脑的ASR,很不错。那怎么能获取到小爱识别后的文本信息呢?我这边用了一个库,叫做xiaogpt,它本身是在ChatGPT刚开始爆火的时候,作者用来给小爱音箱接入ChatGPT的,被我拿来用于这次的改造了。它的原理其实就是不断轮训小爱音箱的历史对话记录,并通过一个“唤醒词”来判断是否需要进行特殊处理,我这边设置的“唤醒词”是“请”。也就是我对小爱同学说的话,只要是“请”开头的,它就会识别到,并且调用我的自定义逻辑。这个方案有一个缺点,就是小爱同学自身也会对你进行回复,也就是如果你说“请帮我接100ml的水”,小爱同学会先回复你“作为xxx,我没法帮你接水….“,这里的处理是会先停掉小爱同学的回复,但是没法完全停掉,还是会有延迟,因为本身历史对话记录也不是实时获取的。但是这都不是事,对于我们使用来说,已经足够了。

出水量

这个沿用之前的方案。

语音识别ASR

这个使用小爱音箱的ASR能力。

语音理解NLU

NLU其实就是理解用户说的话,确认用户的意图(接水)以及实体(出水量),执行对应的逻辑。

这部分没啥好说的,做了好几个项目了,用的都是Thought Agent的方案,效果也经过验证,虽然说有些大材小用了,我这边就只有一个简单的意图,但是后续扩展起来就会很方便了。

之前做项目的时候,用的都是OpenAI的模型,效果肯定刚刚的,但是我自己用的话,考虑到延迟和成本,还是决定试用一下国产模型。比较了一圈下来,发现零一万物的yi-lighting完美契合了我的需求。不知道它什么时候悄悄地给我充值了100块钱,然后每100wtoken才1块钱,如果单给这个接水的场景使用,足够我用好几年了。

要实现这个场景的NLU,用Thought Agent就只需要这么简单配置一下就行,剩下的(意图识别、实体提取、对话管理)框架都帮忙实现了,很是方便。 alt text

对普通的规则匹配来说,用大模型来做这个场景最主要的就是容错性很好,比如我说100ml/1L/1升/1毫升(具体单位是中文还是英文,得看小米的ASR模块),它都能听懂,并且给出正确的意图和实体(我代码中定义的是毫升,所以大模型最终会给我返回毫升,不管用户说的是什么)。

出水量控制

这个通过Node RED的代码节点来进行控制,就是一些代码的事,还是比较简单的。

alt text

按下饮水机的出水按钮

这个就又值得一说了,我这个饮水机的出水通过一个触控区域来进行控制,所以得需要找个能模拟手指触碰的东西来进行控制。上网搜索手指机器人就能找到这个东西,手指机器人分两类,一类是专门按电容屏幕的,一类是按机械按钮的,我这次需要的是电容屏的方案。我是比较早为了给我家的烘干机使用才买的,但是这玩意儿的适配性没有那么好,所以没有适配烘干机的触摸板,这次正好用上了。它是通过蓝牙接入米家的(这又是一个坑)。

回复用户信息

这个通过小爱音箱的TTS能力就能实现。

方案架构

alt text

方案不足

  1. 因为触屏开关是通过蓝牙接入米家的,而需要和纯蓝牙设备进行通讯需要小米的网关,我家有一个小米路由器BE6500 pro自带的中枢网关,按理来说是可以直接本地控制这个设备的,但无奈中枢网关不在homeassistant的支持之列,所以只能通过米家来控制,这样就多了一层大大的网络延迟,导致Node-RED觉得要停止的时候,虽然发送了指令,但是到真正的停止接水还是有一定的延迟,导致最终的误差在80ml左右。所以我这边人为减少了80ml的出水量。但是80ml只是平均值,网络延迟的方差还是挺大的,这并不是一个精准的方案。
  2. 我家的饮水机有童锁,所以每次接水我需要把童锁打开,而童锁本身5s后会自动关闭,但是我让小爱操作到最终Node-RED执行操作常常大于5s,这里的延迟有两个主要部分,一个是读取小爱同学的历史消息的延迟,在2 3s的样子,另一个是Thought Agent的决策延迟,这个在 3 4s的样子,所以我还得在听到小爱同学回复后,再按童锁,这里又是一个人为的等待!!!

暂时还没解决这两个不足的问题,思路的话大概就是

  1. 触屏开关我是完全可以自己定制的,不用之前那个购买的方案。
  2. 童锁也可以通过触屏开关来解决,不过这个童锁属于和我那烘干机差不多的触摸方式,所以需要搭配机械式手指机器人+触摸的方式来实现,这个是我后续的探索方案。(为了实现折腾自由,趁着双十一加国补,已经入手了一台3D打印机,机械式手指机器人这种玩意儿也是可以安排了。用这台3D打印机,特地为我的esp32还安排了一个严丝合缝的房子)

alt text

来一个最终效果演示视频吧:

自动补充水的视频链接

自动接水的视频链接

总结

你以为到这就完了么?不,当我把这些东西都搞定之后,在老婆面前演示了一番,老婆说了一句,有一个管线机不是就够了么?

哈哈,生命在于折腾。