【AI前沿】AI 助力改造非智能升降桌:智能升降、语音控制、多端联动……

2026-08-25

2026年08月24日49 分钟阅读AI 助力改造非智能升降桌:智能升降、语音控制、多端联动……主作者关注dong4j新手上路dong4j关注dong4j新手上路联合作者关注dong4j新手上路dong4j关注dong4j新手上路49 分钟阅读微信扫码分享以图片分享分享到微博点击下方按钮可复制链接分享收藏举报利益相关声明:作者与文中产品有直接的利益相关(开发者、自家产品等)注:本文在提纲整理、技术段落润色和代码摘录整理等环节使用了 AI 辅助拆板、逻辑分析仪抓包、I²C 时序、上拉电阻排查、软件 I²C 失败统计、ToF 读数和多端接入,则来自作者真机实验成稿时已核对文中键码、7-bit 地址、上拉阻值、传感器型号和开源仓库链接;笔者已核对所有文本表述,并修改不便于理解的描述文中的 Desk Gateway 是我自己维护的开源项目(MIT),没有商业赞助升降桌改造存在夹伤风险,文里的童锁和 ToF 保护不能替代原厂安全认证;紧急情况请用 STOP、原厂面板或直接断电背景早在 2019 年搬入新家之后,我就一直在迭代优化办公桌,现在应该是 V3 版本了:这个桌子从搬入新家就一直陪伴着我,它承载了太多太多——是的,就是字面上的意思:后来因为工作原因,我有点轻微腰椎间盘突出,所以决定给它换一个「躯干」,但桌板还是用的原来的(毕竟好一点的升降桌都要 3000+)。最终我选择了一款非智能的双电机版本,升降范围 64~129 cm。我确信凭借自己对硬件的热爱,可以很容易将其改装成智能控制,但可能也是因为对自己的技术过于自信,这个想法拖到最近才得以实现。一方面因为有充足的时间了,二则是因为有了 AI 的加持。升降桌的基本情况我的升降桌之前只能通过原厂控制面板操作,面板上有上升、下降和四个档位键:有时候会出现 B12 错误码,不过同时按住上下键 5 秒就能重置。我最初想增加一个旋钮,顺时针旋转升高,逆时针旋转降低,按下旋钮停止。动手前,我看了少数派的《从零开始,改造一张可以用 Siri 控制的升降桌》,也研究了开源项目Upsy Desky,它们使用的通信协议和我的升降桌不同,我需要重新分析原厂控制面板与控制盒之间的通信。除了旋钮,我还准备接入键盘、手机、Web、手表和语音控制。ESP32-S3 负责接收这些入口的指令,再按照原厂协议控制升降桌。后来我又接入了小智 AI:一块 JC3636W518C,放在桌上作为语音终端。如果你和我的控制面板一样,那大概率是可以复刻的。不过我还是建议你最好拆开面板看一下,看看控制面板的线序、网线的线序是否与我的一致。如果不一样可能就需要使用逻辑分析仪来抓包分析原始数据了。只要能通过 ESP32-S3 发送正确的指令控制升降,那多端接入就非常简单了。改造目标与方案选择原厂控制面板的使用局限如上面所说,原厂控制面板有上升、下降和四个档位键。单击档位键可以移动到保存的高度,长按会覆盖对应档位。每次操作都需要使用安装在桌边的控制面板。目前最大的问题是没有童锁功能,家里的小孩儿觉得好玩儿,经常趁我不注意按着玩儿,有一次离家之前将升降桌设置到了最高位置,正好超过了椅子的高度,不知道是不是老人的安全意识不够,把孩子抱起来按了档位 1,椅子抵住了桌面差点把桌子顶翻(这也是一个局限的点,没有障碍检测)。所以我老早就决定改造成智能升降桌,而且必须加上童锁功能。契机则是一个 zFrontier 的上的一个旋钮控制方案。从旋钮控制扩展到多终端接入玩儿客制化键盘的都知道 zFrontier,我没事就会在 ZF 上逛逛。正好看到Serendipity Dial,我觉得它的可定制化功能非常多,正好我桌面上有 2 个旋钮设备,想着是不是可以通过旋钮来控制升降桌。然后就是上面提到的《从零开始,改造一张可以用 Siri 控制的升降桌》并了解到了Upsy Desky这个开源项目,脑海中逐渐有了可落地的方案:这套架构的核心是 ESP32-S3,它当控制中枢,北向对接 App、手表、键盘、旋钮这类控制端,设备只发统一指令,不需要处理原厂协议;南向对接升降桌控制盒,由 ESP32-S3 把这些指令翻译成控制盒能识别的键码,桌子才会动。借助 ESP32-S3 内置的 Wi-Fi 和蓝牙通信,我们可以集成多种控制入口。硬件架构如下:整套方案里最关键的是如何拿到原厂控制盒认的那套指令。当前分层和硬件拓扑记在仓库的架构总览里。现有开源方案的适配限制少数派的 Siri 升降桌改造和 Upsy Desky,思路都是在控制盒与面板之间加一块控制模块,这点和我后来做的网关接近。但升降桌面板没有统一协议,品牌不同、批次不同,通信方式都可能不一样。我把这两份方案对照自己的桌子看过之后,发现都不适配。Upsy Desky 支持的控制盒和我的不是一种,我的原厂面板用 RJ45 插头只引出四根线,线序、协议和按键数据都得自己确认,然后用 ESP32-S3 模拟原厂控制面板和控制盒通信。原厂控制面板拆解与总线识别RJ45 接口与四线定义原厂面板通过 RJ45 插头与控制盒连接。拆开面板后,电路板背面有四个测试点,标记分别为GND(接地)、CLK(时钟信号)、DAT(传输数据)和3.3V(电源):TM1650 芯片与总线类型判断原厂面板使用 TM1650 驱动数码管,结合CLK和DAT两个测试点,初步判断面板与控制盒之间使用 I²C 通信。芯片型号还不能确定完整协议。只能继续通过总线抓包确认主从关系、设备地址、按键编码和高度数据。逻辑分析仪接线与采样参数调整抓包时,原厂面板保持与控制盒连接,逻辑分析仪接入GND、CLK和DAT三个测试点。分析仪不连接面板的 3.3V,也不参与供电。我最初把采样率设为 20 kHz,只能看到电平变化,无法解码完整数据。把采样率提高到 12 MHz 后,PulseView 可以稳定识别地址和数据。我分别采集了静置、按住上升、按住下降、单击档位和长按保存的数据。采集高度数据时,我让桌子从 64 cm 升到 129 cm,同时记录面板显示的高度,方便后续对照。抓包步骤见逻辑分析仪抓包。SDA 对应 DATSCL 对应 CLK然后将协议修改为 I²C 后就可以正常读取I²C 通信机制与协议解析物理上我们只有一对CLK/DAT,TM1650 用不同从机地址拆成两条通道:控制盒读0x24问现在按了哪颗键,写0x34到0x37刷数码管;PulseView 显示的是 7-bit 地址;TM1650 手册常用 8-bit 写地址,0x24就是手册里的0x48,0x34就是0x68。完整键码、时序和抓包索引在协议逆向笔记。I²C 主从关系与周期轮询通过抓包,我们可以确认:控制盒是 I²C Master,原厂面板是 Slave时钟由控制盒产生,SCL 大约 9.6 kHz面板不主动上报,只在被问到时把当前键态放上总线。另外静置时总线不是空闲的。控制盒大约每 3.7 毫秒做一轮完整问答:先往0x24写一字节DW=0x01,再读一字节DR。DW实测一直是0x01,像显示控制 / 亮度一类的寄存器,键态不在这里。键码在DR里。静置时DR是0x2E。这张图是静置总览,写0x01和读0x2E一直在交替:这一轮写和读是分开的两笔事务,中间各有一次 STOP,一次完整轮询是:S Address write 0x24 ACK Data write 0x01 ACK P 约 29 us S Address read 0x24 ACK Data read 0x2E ACK P 约 95 us 后再开下一轮读完那一字节之后,控制盒用的是 ACK 再 STOP,不是常见的 NACK 再 STOP。后面用 ESP32 去复放面板侧时序,就是卡在这一点上。这张图是单次读写放大:持续返回上升或下降键码时,桌子保持运动;改回0x2E后停止。控桌的本质是改 Slave 每次被读时交出的DR,不是往总线上塞一条「升桌命令帧」。升降、停止与档位指令解析对比静置、按住上升、按住下降的抓包:DW始终0x01,变的只有DR。操作DR说明空闲、松手0x2E必须一直回这个,不要静默不应答按住上升0x47要升多久就回多久按住下降0x4F要降多久就回多久档位 1 单击0x17前往已保存高度档位 1 长按保存0x570x17加上 bit6(0x40)档位 4 单击0x2F前往已保存高度档位 4 长按保存0x6F0x2F加上 bit6上升和下降只差 bit3(0x47 ⊕ 0x4F = 0x08)。档位短码和长按差的是 bit6,事务骨架不变。另外,档位 2 和档位 3 暂时没有抓包,因为我现在常用的只有档位 1 和档位 4,后续可以通过高度传感器来处理多档位问题。同时按住上和下大约 5 秒,原厂可以清 B12。抓包里对应DR=0x7F,有效区间大约 7.5 秒,结束后必须回到0x2E。数码管高度数据解析高度不在0x24的DR里。按住上升时DR一直是0x47,不会跟着厘米数往上爬。我最初在键通道里搜 64、102 这种字面量,找不到,还把写往0x34至0x37的帧当成电机干扰滤掉了。拆板确认 U2 是 TM1650 之后,这些地址对上了手册里的 digit 寄存器(8-bit0x68 / 0x6A / 0x6C / 0x6E)。控制盒一边读键,一边把七段段码写到数码管。面板自己没有高度 MCU,总线上的高度是显示镜像,整数厘米。逻辑位7-bit显示DIG10x34百位,两位高度时常写0x00消隐DIG20x35十位DIG30x36个位DIG40x37第四位;静止时常等于 DIG3总线写序多数是 DIG3 → DIG2 → DIG1 → DIG4,组装高度要按逻辑编号,不能按时间顺序当百、十、个。长按保存档位 1 / 4 的静置帧里,四元组精确重复,段码不变:AW:36 DW:C5 / AW:35 DW:DB / AW:34 DW:00 / AW:37 DW:C5 → 64 cm AW:36 DW:9E / AW:35 DW:5F / AW:34 DW:44 / AW:37 DW:9E → 102 cm对照 TM1650 段码表,还能还原出 82、121。静态大约每 2 到 3 秒刷一整帧;运动中更密。ESP32-S3 控制链路验证拿到了指令数据,就可以开始使用 ESP32-S3 来模拟指令实现升降桌控制了:控制盒通过 RJ45 接口和控制面板连接,如果需要使用 ESP32-S3 来下发控制指令的话,需要一个 RJ45 模块。这里我买的是独立的双口 RJ45 模块,左侧接口通过网线连接到升降桌的控制盒,进而使用 ESP32-S3 下发指令来控制升降桌,右口是连接原厂控制面板,意思是保留原厂控制面板的控制功能,不过这里需要 ESP32-S3 来透传指令。ESP32-S3 模拟原厂控制面板我把 ESP32-S3 配置成地址0x24的 I²C Slave,用它替代原厂面板响应控制盒。Web 页面按住上升时返回0x47,松手时返回0x2E;下降操作返回0x4F。控桌不是 ESP32 主动发一条「升桌帧」,而是控制盒每大约 3.7 ms 来读一次,Slave 把当前键码交出去。固件在mxtark.c里大致是这样:#define ADDR_KEY_7BIT 0x24u #define DR_IDLE 0x2Eu #define DR_UP 0x47u #define DR_DOWN 0x4Fu i2c_slave_config_t cfg = { .i2c_port = I2C_NUM_0, .scl_io_num = GPIO_NUM_4, /* CLK / .sda_io_num = GPIO_NUM_5, / DAT */ .slave_addr = ADDR_KEY_7BIT, .addr_bit_len = I2C_ADDR_BIT_LEN_7, .send_buf_depth