资讯详情

资讯详情

离线语音+LoRa自研智能开关:断网也能用的本地化方案

1. 为什么是「离线语音 LoRa」一堆云智能设备给我的教训家里宽带一断智能灯就变成傻灯这句话我念叨了好几年。前两年跟风买过几个云智能开关宣传语写得天花乱坠实际用下来却处处受气晚上断网语音控制直接哑火智能音箱偶尔抽风说三遍“关灯”它才反应过来更别提有些产品用了一年后厂商直接停止维护App整个设备就成了电子垃圾。所以去年年底我下定决心自己动手做了一套「离线语音 LoRa」通断器系统把卧室、客厅、门厅的灯全部换上自研开关。这套系统最核心的思路就一句话所有开关动作都在本地完成不依赖外网、不依赖厂商服务器语音识别是离线的节点之间用 LoRa 透传通信。断网只是少看几条推送家里的灯该开开、该关关完全不受影响。如果你也受够了云智能设备的各种幺蛾子或者本身就是嵌入式、智能家居方向的折腾党这篇文章应该能帮你少走不少弯路。1.1 云智能方案的最大问题不在网络在“主权”智能家居的痛点其实不是“智能”而是“不可控”。你买回来的云智能开关真正做决策的是厂商服务器本地设备只是执行端。哪怕固件里写着支持局域网控制很多时候也绕不开 App 的账号体系和云端的鉴权逻辑。有一天厂商关停服务或者路由器上不了外网你手里的开关立刻退化成一个普通机械开关。我自己碰到过最离谱的一次是路由器半夜自动升级失败Wi-Fi 整个瘫掉第二天早上想用语音关灯智能音箱一直转圈最后只能摸黑去按面板。那次之后我想明白一个道理对于灯这种每天高频操作的东西可靠性比花哨功能重要得多。离线语音识别和 LoRa 局域网通信正好能把“能用”的底线牢牢抓在自己手里。另外还有一层隐私考虑。客厅里放一个随时听声音的智能音箱即使厂商保证数据加密心里总归不踏实。离线语音模块的识别过程全部在本地芯片上完成不会上传任何音频天然规避了语音隐私问题。对我这种比较在意这块的人离线方案是唯一能接受的方向。1.2 不是大模型的 LoRA是射频通信的 LoRa如果你搜过“LoRa”这个词一定会发现现在满屏都是大模型相关的 LoRA 微调技术什么“LoRA训练”“低秩适应”之类的。我得先泼盆冷水本文里的 LoRa 是 Long Range 的缩写是一种射频调制技术跟大模型微调没有半毛钱关系。它工作在 sub-GHz 频段国内常用 470-510MHz 的免授权频段用线性扩频的方式获得很远的通信距离同时功耗极低。要区分也很简单大模型那边写作 LoRA射频通信这边写作 LoRa一个是四个字母全大写一个是大小写混合搜索结果完全两个世界。我在选型的时候对比过 Wi-Fi、蓝牙 Mesh、ZigBee 和 LoRa。Wi-Fi 最大的问题是功耗高而且依赖路由器断网就断链蓝牙 Mesh 组网复杂穿墙能力一般ZigBee 需要额外买网关且多数方案同样绕不开云。LoRa 的优势在于三点通信距离远、低功耗、协议自由。我只需要在同一个屋子里把几个开关节点连起来LoRa 穿透两三堵墙的能力完全够用而且所有数据都在本地射频链路上跑不经过任何第三方平台。当然LoRa 不是万能的它带宽很低不适合传音频视频甚至不适合做高频数据上报。但对开关控制这种只有几个字节的指令来说简直是大材小用。后面我会专门讲它在实际穿墙中的表现有好消息也有翻车记录。2. 硬件怎么配离线语音模块、LoRa 射频、继电器之间的取舍确定“离线语音 LoRa”这个方向之后最麻烦的就是硬件选型。市面上的通断器模块大多只支持 Wi-Fi 或者 ZigBee几乎没有同时集成离线语音和 LoRa 的现成产品所以只能自己组合。我建议你把整块通断器拆成三层来看语音识别层、主控通信层、执行层。语音识别层负责听懂人话主控通信层负责解析指令并通过 LoRa 分发执行层就是继电器和电源。下面挨个说我选的方案。2.1 离线语音识别模块我走的是 SU-03T 路线离线语音模块的选择其实不算多市面上常见的有 SU-03T、CI1122、LD3320 这几类。LD3320 是比较老牌的芯片支持动态编辑命令词但模块资料和生态相对陈旧而且识别率一般。CI1122 性能不错但配置工具上手门槛稍高。我最后选了 SU-03T主要是看重它三点第一唤醒词和命令词都可以在上位机里自定义不需要写复杂音频算法第二它支持串口输出识别结果方便和 MCU 对接第三板子很小能塞进标准 86 底盒。SU-03T 的定制流程大致是这样的先确定唤醒词比如我用的是“小开小开”四个字比较不容易误唤醒然后在配置工具里添加命令词比如“打开客厅灯”“关闭客厅灯”“全屋开灯”等每个命令词可以绑定一个串口指令或 GPIO 动作配置完成后把固件烧录到模块里之后它就完全离线工作了。识别到唤醒词后模块的 MIC 开始工作把语音匹配到命令词然后按约定好的串口协议把指令发出来。有一点要提醒SU-03T 只适合做命令词识别不适合做自由对话。它不能理解“帮我把灯调暗一点”这种模糊表达你必须把“开灯”“关灯”“调亮一点”这些固定说法全部预置成命令词家庭成员用的时候也要尽量按照这些说法来。对我家来说这不算问题但对于有老人小孩的家庭命令词一定要设计得简单直观别用花里胡哨的别名。2.2 LoRa 模块先用串口透传跑通再去啃裸芯片LoRa 模块大体分三类纯射频芯片比如 SX1278、半透传模块、串口透传模块。纯射频芯片需要自己写驱动处理收发、FIFO、中断等半透传模块提供 AT 指令但底层协议还得自己写串口透传模块最简单MCU 往串口丢数据模块自动加前导码、计算 CRC、无线发出去另一边的模块收到后从串口吐出来。我第一版全部用串口透传模块省下的时间都用来调协议和排查硬件问题。对于做产品或者对功耗有极致要求的场景串口透传模块可能不够理想因为透传格式会带来额外开销也无法做跳频。但作为一套自用系统稳定性和开发速度显然更重要。我用的模块是基于 SX1278 的 470MHz 串口透传模块发射功率设置到 17dBm空中速率默认比较快后来穿墙测试不理想就把空中速率调低具体参数后面第五部分再细说。天线是 LoRa 方案里最容易被忽略的环节。模块本身带的是弹簧天线在空旷环境还凑合一旦塞进金属底盒信号直接被屏蔽掉一大半。我的做法是把天线通过延长线引出面板贴在开关面板内侧靠近塑料表面的位置而不是让它窝在底盒里。别小看这个动作同样一发指令天线引出来之后接收成功率能提高一截。2.3 通断器的执行核心磁保持继电器才是断电记忆的关键通断器说白了就是一个继电器加上控制电路。继电器选型直接影响整个系统的可靠性和体验。普通继电器内部是线圈加弹簧线圈通电后触点吸合断电后触点自动弹开。这带来一个很尴尬的问题如果家里跳闸停电再来电时继电器处于断开状态而你以为房间里的灯应该保留停电前的状态结果回家一按面板没反应还得重新开一次。磁保持继电器解决了这个问题。它内部有两组线圈一组负责“置位”一组负责“复位”动作时只需要给一个短脉冲之后靠永磁铁保持触点状态。也就是说断电之后继电器还是保持在原来的开或关状态来电后不丢状态。我第一批打样用的普通继电器测试完直接全部换成磁保持继电器这一项改动几乎没有增加成本但体验提升非常明显。选继电器时还要注意触点额定电流。家里常用的 LED 灯虽然功率不高但开关电源会有比较大的启动浪涌电流不能只看稳态功率。我选的是额定 10A 的磁保持继电器即使以后接几个大功率筒灯余量也够。如果你要控制浴霸、取暖器这种大功率负载触点容量建议至少上到 16A同时要确保 AC-DC 电源模块能够提供继电器动作瞬间的峰值电流。3. 220V 接线盒里的供电设计零火线、隔离电源与功耗计算智能开关装到墙上最难的不是程序而是给板子供电。传统机械开关盒里通常只有一个火线进线和一个灯线出线根本没有零线这就导致很多智能开关只能靠“单火线偷电”来维持工作。偷电的意思是在开关断开时让一个微小电流流过负载回到零线用这个微电流给内部电路供电。听起来很美好实际做起来坑非常多。如果你装修时在开关盒里留了零线那供电问题就简单很多。3.1 单火线取电为什么容易翻车单火线方案最大的问题在于负载适配。如果下面接的是一个几瓦的 LED 灯泡流过的微电流不足以让灯亮起来但足以让电源模块启动吗而且 LED 驱动对微小电流非常敏感开关关闭后寄生电流会在线路中形成微小回路导致灯关了还一闪一闪地微亮。你多半见过家里灯关掉后还微微发光的现象那大概率就是智能开关单火供电造成的。要解决微光常见做法是在负载两端并联一个 CBB 电容或者泄放电阻给寄生电流一个泄放通道但这样治标不治本还影响安全性。更激进的方案是直接在 86 盒里做非隔离降压比如阻容降压好处是便宜坏处是板子带电对调试和绝缘要求极高稍有不慎就会电人。我自用可以小心但我实在不推荐这种方案毕竟灯开关是家人每天都要碰的东西。所以我的结论是能走零火线就坚决走零火线。我家里的几个开关盒里刚好都有零线没费太多周折。如果你家的老房子没有零线条件允许的话建议从最近的天花板灯座引一根零线下来或者找电工重新拉线而不是硬上单火方案。3.2 功耗计算和 AC-DC 模块选型零火线供电之后我选了一个隔离型的 AC-DC 模块220V 市电转 5V 直流型号是 HLK-PM01最大输出电流 600mA。为什么不用阻容降压除了安全因素之外还有一个原因是 LoRa 发射瞬间电流很大阻容降压的纹波和带载能力根本扛不住一旦压降过大模块就有可能复位重启。功耗需要精细算一遍。离线语音模块 SU-03T 静态待机大概 30-50mA识别时瞬时可能到 100mA 左右LoRa 透传模块接收状态大约 15mA发射瞬间如果功率在 17-20dBm电流会冲到 120mA 以上主控 MCU 我用的是 ESP32-C3 的板子虽然固件里把 Wi-Fi 关掉了但底层还有些基础功耗大约 40mA磁保持继电器动作时是脉冲电流持续约 200ms、峰值 150mA不是持续负载。加在一起最坏情况下瞬时电流大概在 400-500mA 之间HLK-PM01 的 600mA 余量还算充足。功耗项典型电流说明SU-03T 离线语音模块30-100mA待机低识别时爬升LoRa 透传模块15-120mA接收低发射瞬间较高ESP32-C3 主控40mA关闭 Wi-Fi 后的基板功耗磁保持继电器脉冲峰值 150mA动作 200ms 即结束有一点要注意AC-DC 模块在工作时会有一定发热而且安装在密封的 86 底盒里散热很差。我实际测量过稳定负载 300mA 左右时模块表面温度大约在 50℃ 上下手摸上去温热但不算烫。如果你接的负载更大建议在底盒里留出空气流通空间或者在面板上开几个小散热孔别把模块用热缩管塞得密不透风。3.3 接线顺序和安全细节接线这块我不敢含糊毕竟 220V 电压不是闹着玩的。整体顺序是断掉总闸用验电笔确认火线确实没电然后剥线、压线帽、按顺序接入 AC-DC 模块和继电器。火线进线接到模块的 L 端零线接 N 端模块输出 5V 给整块板子供电继电器的一路触点串接在火线和灯线之间这样继电器断开后灯头端没有电检修也更安全。面板那边的机械开关我保留了一个但不是直接串在灯线上而是把按键接成 MCU 的输入信号。按下时 MCU 检测到电平变化翻转继电器状态同时通过 LoRa 广播。这样既保留了传统开关的手感又能让语音和按键互不干扰。按键只走 5V 信号完全避开了大电流安全性好很多。还有一个细节板子和壳体之间的绝缘。市售的智能开关外壳有阻燃和防触指设计自己做的板子一定要贴绝缘胶带或者至少把 AC-DC 模块的高压裸露焊点用热缩管包上。继电器接线柱也建议用阻燃胶布加固避免震动导致接线松脱。通电之前先用万用表量一遍 L、N 之间没有短路再上电测试这个习惯能帮你省掉很多不必要的惊吓。4. 固件里的通信协议设备地址、命令帧和断网兜底逻辑硬件装到这一步一个节点已经能单机工作了。但既然是“系统”就需要让多个节点之间互相通信。比如你在卧室门口对着开关说“关闭客厅灯”这条指令要先被本地的语音模块识别然后通过 LoRa 发到客厅的节点由客厅节点执行。这里最关键的是一套稳定的通信协议否则两个节点同时说话或者一条指令被多个节点重复执行都会出乱子。4.1 语音识别结果怎么变成开关指令SU-03T 本身是一个“识别即执行”的模块它内部可以绑定命令词和 GPIO 动作但我没有用它的 GPIO 直接控制继电器而是让它通过串口把识别结果发给主控。这样一来主控可以统一处理按键、语音、LoRa 三种输入源逻辑更清晰。具体做法是在 SU-03T 的配置工具里把每个命令词绑定成一条自定义串口数据比如“打开客厅灯”对应 0xA5 0x01 0x01“关闭客厅灯”对应 0xA5 0x01 0x00。主控收到后解析协议头 0xA5然后读取设备类型和动作。大部分离线语音模块的串口是 3.3V 电平跟 ESP32-C3 可以直接对接不需要额外转换。主控内部维护一张“设备映射表”把语音命令对应的设备名和动作转成标准中间格式。比如{type: LIGHT, id: 1, action: ON}然后再根据本地地址是否匹配来决定是直接执行还是通过 LoRa 转发。这样把语音识别和通信协议解耦以后想换另一种语音模块只需改动识别层主控逻辑完全不用重写。4.2 LoRa 报文格式和冲突避免LoRa 透传模块对我来说就是一个串口替代品MCU 往串口写什么另一边的 MCU 就能从串口读到什么。但要保证多节点组网不混乱我设计了一个非常轻量的帧格式字段长度含义帧头1 字节固定 0xA5用于同步源地址1 字节发送节点的唯一编号目的地址1 字节接收节点编号0xFF 表示广播命令1 字节0x01 开灯0x02 关灯0x03 查询等设备编号1 字节具体控制哪一路负载序列号2 字节每条指令递增用于去重CRC81 字节对前面所有字段做校验用 C 语言描述大致是这样的typedef struct { uint8_t header; // 0xA5 uint8_t src; uint8_t dst; uint8_t cmd; uint8_t dev_id; uint16_t seq; uint8_t crc; } lora_frame_t;帧设计里有几个容易踩坑的地方。第一是序列号因为我们用广播通信同一条指令可能被多个节点收到如果没有序列号就无法判断是不是重复消息。我给每一条新指令分配一个自增 seq节点收到后跟最近一次处理的 seq 做比较相同就丢弃。第二是 CRC 校验透传模块本身可能已经做了校验但我在应用层再加一层 CRC8 更稳妥防止串口误码导致执行错误。第三是目的地址过滤节点收到广播包后先看 dst是自己的地址或者 0xFF 才处理其他一律丢弃避免全屋开关被一个语音指令同时触发。LoRa 是半双工通信同一时间只能有一个节点在发否则会冲突。对于家庭这种节点数量不超过十个的场景冲突概率比较低但我在协议层做了一个简单的等待退避节点在发送前先检测串口是否持续空闲 50ms如果忙就随机等待 100-300ms 再重试。4.3 断网之后的兜底逻辑离线语音模块让“没网也能动嘴”LoRa 让“没网也能远程控制”但通信链路本身仍然可能出问题。比如 LoRa 模块因为干扰丢失数据或者某个节点被断电。所以我给系统设计了三条兜底规则。规则一是本地优先。任何时候按键和语音模块识别到指令后先控制本节点继电器再考虑是否转发。这样即使 LoRa 完全瘫痪每个开关至少是一个合格的机械开关。规则二是远程指令有限次数重试。如果 A 节点要向 B 节点发指令B 节点收到后会回一帧 ACKA 节点在 500ms 内没有收到 ACK 就再发最多重试三次。三次都失败就在日志里标记“节点 B 不可达”不影响本地功能。规则三是状态上报和查询。每个节点每隔 60 秒广播一条状态帧包含继电器状态和信号接收强度。这样我可以在调试阶段知道哪个节点信号不好及时调整天线位置。我暂时没有做完整的动态路由因为家庭场景下 LoRa 的通信距离足够覆盖不需要像多跳网络那样复杂。5. 实测翻车现场微光、穿墙差、同音词误触发问题逐个修硬件和固件都搭起来之后真正折磨人的是现场实测。我大约花了两个星期才把所有问题磨平下面几个问题我觉得挺有代表性大概率也是你会遇到的。5.1 LED 灯关了还微光第一版装好之后我欣喜地发现语音能开灯关灯了但晚上一关灯问题立刻暴露LED 灯在不该亮的时候发出一种很微弱的呼吸般的光过几秒还闪烁一下。这个现象非常典型原因就出在供电回路上。虽然我用的是零火线供电AC-DC 模块接在继电器之前但继电器只是断开了火线到负载之间的通路而负载的零线是直接接到供电零线上的。如果板子上有个别隔离不到位或者 AC-DC 模块的滤波电容存在漏电流就会在继电器断开后形成一个从火线经模块电容、再经负载回到零线的微弱闭环电流虽然只有几毫安但 LED 驱动对这种漏电流很敏感表现出来就是微光和闪烁。我的解决策略是两条腿走路。第一继电器断开时确保是把火线一侧完全隔断并且负载端的走线离 AC-DC 模块尽量远不要在 PCB 上绕成一个回路。第二在灯头两端并联一个并联电容和电阻组给漏电流一个泄放通道让微小电流不再通过 LED。最简单的方法是并在火线和零线之间加一个 100kΩ/1W 的功率电阻注意电阻功耗不要超过额定值否则会发热。5.2 LoRa 穿两道墙就不行了这个问题是我最开始没预料到的。我以为 LoRa 主打远距离穿墙应该没问题结果把节点装到客厅和卧室之间时实测发现客厅节点发指令到卧室节点成功率只有六成。后来在卧室门关着的情况下测试十次里有两三次直接收不到。我开始怀疑是不是买到了劣质模块后来查阅资料才明白LoRa 的远距离是在空旷视距下测出来的混凝土墙壁、钢筋网、金属底盒都会对 sub-GHz 信号造成明显衰减。穿一道木门没什么问题穿一道承重墙也能接受穿两道墙再加上拐角信号就大打折扣。解决思路是“降速换灵敏度”。LoRa 的接收灵敏度和带宽、扩频因子直接相关带宽越窄、扩频因子越高灵敏度越好但传输速率会下降。我把模块参数从 125kHz 带宽、SF7 改成了 125kHz、SF11发射功率保持 17dBm实测接收灵敏度大概提升了 10dBm 左右穿墙成功率明显改善代价是一条指令的空中传输时间从几十毫秒变成了两三百毫秒。对于开关灯这种场景多等两三百毫秒完全无感。参数初始值调试后效果带宽125kHz125kHz保持扩频因子SF7SF11灵敏度提升约 10dBm编码率4/54/5保持发射功率17dBm17dBm保持实测穿两墙成功率约 60%成功率接近 100%明显改善另一个重要的调整是把天线从金属底盒里引出来。我也测试过在节点附近加一个 LoRa 中继但后来发现参数调整之后已经不需要了所以暂时没有上中继。如果你家面积更大中继会是一个更稳妥的方案。5.3 同音词误触发和重复执行语音模块还有一个很现实的问题同音词误触发。我把命令词设成“打开灯”和“关闭灯”结果家人聊天时说“快关灯”或者“别打开灯”模块偶尔会错误识别成标准命令词然后真的把灯关了。这本质上是离线语音模块的本地匹配能力有限它不像云端语音助手那样能理解上下文。我最有效的办法有两个。第一把唤醒词的灵敏度从最高档调低一档模块只有在确认唤醒词之后才进入识别状态闲聊时的误唤醒大幅减少。第二命令词尽量设计成完整的、不容易被日常对话包含的短语比如把“打开灯”改成“小开开灯”虽然听起来有点蠢但因为日常聊天中很少会出现这个完整短语误触率明显下降。重复执行的问题是另一回事。我的客厅里装了两个通断器节点它们都在同一个 LoRa 信道上。有一次我说“打开客厅灯”结果客厅的两个节点都执行了其中一个节点执行了两遍。排查了一下这不是 LoRa 广播本身的问题而是我的去重逻辑不够严格两个节点都用同一个 seq 去重但不同节点各自维护自己的最近 seq导致重复包无法识别。后来我把去重字段从“最近 seq”改成“src seq 组合”作为唯一键问题才彻底解决。具体的做法就是在收到帧时查一张最近处理过的小表看看 src 和 seq 是否已存在存在就丢不存在就加入并覆盖最旧的记录。6. 这套系统还能怎么扩展以及在折腾前的几句实话做出第一版、把所有坑填平之后我开始琢磨这套系统还能怎么玩。LoRa 本身是一种很低速、低功耗、远距离的通信方式把它用在开关控制上只是最基础的用法。如果家里有院子、车库、地下室需要远程控制一些不方便布线的地方这套架构可以直接平移过去。6.1 最容易复刻的一条路如果你也想复刻我不建议一上来就照抄我的全套方案尤其是 PCB、外壳这种比较费时的部分。最低成本的验证路径是先买一块通用的 ESP32-C3 开发板、一个 SU-03T 离线语音模块、一个基于 SX1278 的串口透传模块、一个磁保持继电器模块用杜邦线搭在一起。先跑通一个节点的语音控制再用两块板子做 LoRa 点对点转发最后再考虑正式画板、设计外壳、装进 86 盒。这样每一步都有明确反馈遇到问题也好定位。固件方面不需要很复杂的操作系统一个裸机状态机就够用了。主循环里轮询按键、串口、语音模块的数据收到指令后做解析再决定执行还是转发。重点是把协议处理好尤其是 seq 去重和 CRC 校验有了这两个机制系统稳定性会有质的提升。6.2 后续值得做的几个扩展方向第一个方向是传感器上报。LoRa 的带宽虽然低但周期性上报温度、湿度、门窗状态完全够用。我计划在卫生间门口放一个低功耗传感器节点通过 LoRa 上报温湿度主机节点收到后只在本地显示不经过云服务。第二个方向是接入本地智能家居平台。因为主控用的是 ESP32-C3虽然固件里关掉了 Wi-Fi但我可以单独做一个 LoRa 网关节点把 LoRa 数据转换成 MQTT 上报到 Home Assistant这样既能保留 LoRa 的远程覆盖又能享受到自动化编排的好处。这个网关仍然运行在家庭局域网里不依赖外网。第三个方向是调光。目前的通断器只能做开和关想要调光就得把执行层从继电器换成可控硅或 MOS 管。离线语音模块已经识别出“调亮一点”这种命令剩下就是在输出端做 PWM 或相位控制这比开关更有意思但代码量也要大很多。6.3 折腾完这一套我最大的体会最后说几句掏心窝的话。这套系统做下来我最深的体会不是“自研真香”而是“通信协议和供电设计才是一切的基础”。语音模块再聪明继电器再贵供电不稳、通信去重做不好整套系统照样会抽风。很多成品智能开关之所以让人失望恰恰是因为它们在底层可靠性上偷了懒。如果你打算自己动手一定要有一根稳定的示波器或者万用表先把供电纹波、串口波形确认清楚再谈组网和协议。否则一旦系统整体跑起来你会发现问题藏在各种看似不可能的地方排查起来非常痛苦。这套「离线语音 LoRa」系统目前已经在我家稳定跑了几个月家人已经完全习惯了对开关说话来开灯关灯甚至忘了它们其实不需要网络。对我个人来说这就是折腾自研智能家居最大的回报。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →