- 工业制造
- 嵌入式
【免费下载链接】linuxcnc
LinuxCNC controls CNC machines. It can drive milling machines, lathes, 3d printers, laser cutters, plasma cutters, robot arms, hexapods, and more.
XHC WHB04B-6 是成都鑫和诚科技生产的一款无线 MPG 手轮(无线手脉),本文基于 LinuxCNC 仓库中的 xhc-whb04b-6 组件文档 及其源码,系统讲解该组件的两种运行模式、USB 协议逆向成果、全部命令行选项、按键码表与 HAL 引脚接线方法。读完本文,你将能够独立完成 WHB04B-6 手轮的驱动加载、连通性调试、按钮/旋钮/手轮事件的 HAL 接线,并理解其显示数据的编码原理,从而把这块手轮接入自己的 LinuxCNC 机床。
组件简介:共享内存 HAL 模式与免共享内存的模拟模式
xhc-whb04b-6是一个用户态 HAL 组件,负责接收 WHB04B-6 设备的事件并通过 HAL 引脚暴露给 HAL 系统。其核心设计在 xhc-whb04b6.h 中由XhcWhb04b6Component类实现,内部组合了三个关键子系统:
Usb(见 usb.h):基于 libusb 完成设备的枚举、claim、异步收发与睡眠/空闲检测;Hal(见 hal.h):创建并维护全部 HAL 引脚,HalMemory结构体按In/Out分组保存每个引脚的内存指针;Pendant(见 pendant.h):负责按钮、旋钮与手轮计数器的业务逻辑。
组件的两种运行模式如下:
- 生产模式(HAL 模式):接口数据放在共享内存中,其他 HAL 组件(如
halui、axis)可以直接读写。使用-H参数启动。 - 模拟模式(仿真模式):不需要共享内存,所有引脚退化为堆内存中的普通变量(见
hal.h中newSimulatedHalPin的实现逻辑),适合在无实时环境时检查设备连通性与调试协议。
从源码看,模拟模式的判定通过setSimulationMode()控制,而 HAL 内存分配路径(hal_pin_new_bool等)只在非模拟模式使用。组件还实现了isPendantSleeping/isPendantConnected两个状态引脚,用于反映手轮的休眠与连接状态。
编译依赖
组件源码中保留了一行关键提示(main.cc 与 README 均有记录):
sudo apt-get install libprotobuf-dev protobuf-compiler注意:构建脚本 Submakefile 还要求 GCC >= 4.7 且系统具备 libusb-1.0(HAVE_LIBUSB10),组件由hal.cc、usb.cc、pendant-types.cc、pendant.cc、xhc-whb04b6.cc、main.cc六个源文件链接成../bin/xhc-whb04b-6。
面板布局:16 个按钮与 Fn 修饰键
设备提供 16 个按钮,其中一个 "Fn" 按钮用作按键修饰键。任何按钮与 Fn 组合按下都会产生替代事件——Macro-n(n 为宏编号),即使按钮上并未印有 Macro-n 字样。组件将宏从 Macro-10 一直扩展到 Macro-16。完整布局如下:
| 列1 | 列2 | 列3 | 列4 | 列5 |
|---|---|---|---|---|
| RESET (Macro-11) | Stop (Macro-12) | Start/Pause (Macro-13) | <On/Off Sw.> | |
| Feed+ (Macro-1) | Feed- (Macro-2) | Spindle+ (Macro-3) | Spindle- (Macro-4) | |
| M-HOME (Macro-5) | Safe-Z (Macro-6) | W-HOME (Macro-7) | S-ON/OFF (Macro-8) | Fn |
| Probe-Z (Macro-9) | ||||
<Axis Rotary Button> | Macro-10 (Macro-14) | <Feed Rotary Button> | ||
| CON (Macro-15) | Step (Macro-16) | |||
<Jog Dial> |
⚠️ 注意:该设备的按键命名与用户手册翻译得不太理想。MPG 按钮将设备置入连续(continuous)模式,而Step/Continuous 按钮将设备置入步进(step)模式。连续模式下,n 次手轮(jog dial)事件被翻译为"以速度 x 移动关节 n 次";步进模式下则翻译为"以预设速度移动关节 n 步"。
该布局在仓库中以 PlantUML 源文本形式保存于 buttons-layout-diagram.txt,组件源码中对应的事件分发在 pendant.cc。
命令行选项:从连通性调试到生产运行
运行xhc-whb04b-6 -h可查看完整帮助。以下是 README 记录并经 main.cc 中getopt解析确认的全部选项:
| 选项 | 说明 |
|---|---|
-h | 打印用法摘要与常用命令 |
-H | 以 HAL 模式(而非交互模式)运行。HAL 模式下设备命令将暴露到 HAL 共享内存;交互模式适合测试设备连通性与调试 |
-t | 带超时等待 USB 设备,超时则退出;不带-t时超时隐式为无限(源码中固定为 3 秒) |
-u, -U | 显示从设备接收的数据;-U同时打印接收与发送的数据。输出以 "usb" 前缀标识 |
-p | 显示 HAL 引脚及 HAL 相关消息。输出以 "hal" 前缀标识 |
-e | 显示捕获到的事件,如按钮按下/释放、手轮、轴旋钮、进给旋钮事件。输出以 "event" 前缀标识 |
-a | 启用全部日志设施,等价于逐个指定 |
-c | 启用校验和输出,用于调试校验和生成函数。不要依赖此特性,生成器实现完成后将被移除 |
-s | 主轴(Spindle)模式下的 Lead:Lead + 手轮改变主轴倍率,每 tick 增/减主轴倍率 |
-f | 进给(Feed)模式下的 MPG:MPG + 手轮改变进给倍率,每 tick 增/减进给倍率 |
-B | 大步进模式:为进给选择器追加 5mm 和 10mm 档位 |
-n | 强制静默,除错误外不打印任何输出,同时抑制 "init" 前缀消息 |
-P | 以十六进制指定设备 ProductId(缺省 0xeb93),见main.cc中case 'P' |
常用示例
xhc-whb04b-6 -ue 打印收到的 USB 数据传输与生成的按键按下/释放事件。 xhc-whb04b-6 -p 打印 HAL 引脚名称及分发到 HAL 内存的事件。 xhc-whb04b-6 -Hn 以 HAL 模式启动并抑制输出(除错误外)。 xhc-whb04b-6 -HsfB HAL 模式 + 主轴倍率 + 进给倍率 + 大步进 5/10mm。USB 协议逆向:接收与传输数据结构
由于厂商(成都鑫和诚科技有限公司)拒绝公开任何协议信息,组件作者只能对协议进行逆向工程。他们曾联系厂商索取 PHB04 的源代码,但所得代码质量堪忧,最终仍以自行分析为主。以下是 README 记录的全部逆向发现。
接收数据(设备 → 主机)
设备上报的 HID 报告共 8 字节,report ID 恒为0x04:
| 字节# | 位宽 | 数据 | 取值 | 待澄清 |
|---|---|---|---|---|
| 0x00 | [0:7] | report ID | 常量 0x04 | |
| 0x01 | [0:7] | random(随机字节) | ||
| 0x02 | [0:7] | 按钮 1 键码 | 0x00-0x10 | |
| 0x03 | [0:7] | 按钮 2 键码 | 0x00-0x10 | |
| 0x04 | [0:7] | 进给旋钮键码 | 0x0d-0x10, 0x1a-0x1c | |
| 0x05 | [0:7] | 轴旋钮键码,若轴处于 OFF 状态则显示无法更新 | 0x11-0x16, 0x06 | * |
| 0x06 | [0:7] | 手轮增量 delta | int8_t | |
| 0x07 | [0:7] | 校验和 | * |
该结构在 usb.h 的UsbInPackage中一字不差地实现(header、randomByte、buttonKeyCode1/2、rotaryButtonFeedKeyCode、rotaryButtonAxisKeyCode、stepCount、crc),并用__attribute__((packed))保证字节对齐与协议一致,接收端通过UsbInPackageBuffer联合体在字段视图与原始字节缓冲之间转换。
校验和研究
逆向得到的校验和规律如下:
- 手轮事件、旋钮事件或按钮释放事件:
checksum == random & seed - 按钮按下事件:
//! 仅当 seed 为 0xfe、0xff 时可靠,否则不可靠,等式应有缺失部分。 //! 不确定是 crc 还是手工算法。 checksum == random - (keyCode ^ (~seed & random))
README 明确标注:按下事件的公式只对部分 seed 生效,说明存在未解析的等式成分;无法确认是 CRC 还是手写算法。-c选项的校验和输出正是为此调试而保留的临时特性。
传输数据(主机 → 设备)
USB vendor ID = 0x10ce USB product ID = 0xeb93传输数据打包为 7 字节数据,外加恒定的前导字节0x06作为 report ID(源码中UsbOutPackageBlockFields::reportId)。除 report ID 外的数据字段如下:
| 字节# | 位宽 | 数据 | 取值 | 待澄清 |
|---|---|---|---|---|
| 0x00 | [0:15] | 头部,不清楚能否发送不同头部(命令) | 常量 0xfdfe | * |
| 0x02 | [0:7] | seed | * | |
| 0x03 | [0:1] | 显示指示标志:步进模式 | 0x00 "CONT xx%",0x01 "STEP: xx",0x02 "MPG xx%",0x03 "xxx%",0x04 未知。设置步进模式则为连续模式。注意:即使旋钮处于无效步进位置(如 100%)也会被解释为步进模式,此时显示误导性的 "STEP: 1.0",作者认为这是固件 bug | |
| 0x03 | [2:5] | 显示指示标志:未知 | * | |
| 0x03 | [6:6] | 显示指示标志:reset | 复位时指示所选 X 轴的星号渲染错误,且同一区域可见闪烁,作者认为这是固件 bug | |
| 0x03 | [7:7] | 显示指示标志:机床坐标 | 置位显示工件坐标,否则显示机床坐标 | |
| 0x04 | [0:15] | 显示行 1 轴坐标:整数值 | ||
| 0x06 | [0:14] | 显示行 1 轴坐标:小数值 | 15 位宽但设备只截取 4 位数字,作者认为这是固件 bug | |
| 0x06 | [15:15] | 显示行 1 轴坐标:符号 | ||
| 0x08 | [0:15] | 显示行 2 轴坐标:整数值 | ||
| 0x10 | [0:14] | 显示行 2 轴坐标:小数值 | 与轴 1 相同 | |
| 0x10 | [15:15] | 显示行 2 轴坐标:符号 | ||
| 0x12 | [0:15] | 显示行 3 轴坐标:整数值 | ||
| 0x14 | [0:14] | 显示行 3 轴坐标:小数值 | ||
| 0x14 | [15:15] | 显示行 3 轴坐标:符号 | 与轴 1 相同 | |
| 0x16 | [0:15] | 进给率 | ||
| 0x18 | [0:15] | 主轴转速 | ||
| 0x20 | [0:x] | 不清楚设备是否会解析后续字节 | * | |
| 0xn | [0:x] | 最大长度同样不清楚 | * |
该布局同样完整复刻在 usb.h 中:UsbOutPackageData以header、seed、displayModeFlags、三个UsbOutPackageAxisCoordinate(每轴由integerValue、15 位fractionValue与 1 位coordinateSign组成)、feedRate、spindleFeedRate的顺序打包,显示模式位字段见DisplayIndicatorBitFields(2 位stepMode、4 位未知、1 位isReset、1 位isRelativeCoordinate)。
显示指示的步进模式编码
pendant-types.h 中的HandwheelStepmodes::Mode枚举给出了显示模式的语义:
CON = 0x00:按进给旋钮位置显示 "CON: 2%/5%/10%/30%/60%/100%"STEP = 0x01:按旋钮位置显示 "STP: 0.001/0.01/0.1/1.0";在 60%、100% 或 Lead 位置仍显示 "STP: 1.0"(固件 bug)MPG = 0x02:显示 "MPG: 2%/5%/10%/30%/60%/100%"PERCENT = 0x03:直接显示 "2%/5%/10%/30%/60%/100%"
组件内部通过HandWheelCounters(同一头文件)为 X/Y/Z/A/B/C 各轴与 Lead 维护独立计数器,setActiveCounter()决定当前手轮增量累加到哪条计数上。
已做与未做的工作
已做的调查:
- 在网上搜索到部分相关但非完全匹配的信息(一个 planet-cnc 论坛帖子与一个 LinuxCNC wiki 上关于 XHC-HB04 无线 MPG 手轮的页面);
- 礼貌联系厂商索取接口控制文档或等价信息,未获成功。
未做的调查:
- 未在 Windows 虚拟机中安装驱动与 Mach3,用 Wireshark、usbmon 等工具嗅探 USB 协议。
已知问题
- 设备上电后并不(总是)主动发送数据以披露当前旋钮状态;
- 若旋钮状态在断电期间发生变化,则极有可能发送,但并非总是如此。
- 轴旋钮处于 "OFF" 状态时,设备不会刷新显示上的坐标。
键码详解:按钮、进给旋钮与轴旋钮
按钮键码(Key Code 0x00–0x10)
| 按钮名 | 键码 | 按钮文字 | 按钮替代文字 |
|---|---|---|---|
| reset | 0x01 | RESET | Macro-11 |
| stop | 0x02 | STOP | Macro-12 |
| start | 0x03 | Start | Macro-13 |
| feed_plus | 0x04 | Feed+ | Macro-1 |
| feed_minus | 0x05 | Feed- | Macro-2 |
| spindle_plus | 0x06 | Spindle+ | Macro-3 |
| spindle_minus | 0x07 | Spindle- | Macro-4 |
| machine_home | 0x08 | M-HOME | Macro-5 |
| safe_z | 0x09 | Safe-Z | Macro-6 |
| workpiece_home | 0x0a | W-HOME | Macro-7 |
| spindle_on_off | 0x0b | S-ON/OFF | Macro-8 |
| function | 0x0c | Fn | Fn |
| probe_z | 0x0d | Probe-Z | Macro-9 |
| macro10 | 0x10 | Macro-10 | Macro-14 |
| manual_pulse_generator | 0x0e | Continuous | Macro-15 |
| step_continuous | 0x0f | STEP | Macro-16 |
<无按键> | 0x00 | <NA> | <NA> |
进给旋钮键码
| 进给旋钮档位名 | 键码 | 按钮文字 | 按钮替代文字 |
|---|---|---|---|
| speed_0_001 | 0x0d | 0.001 | 2% |
| speed_0_01 | 0x0e | 0.01 | 5% |
| speed_0_1 | 0x0f | 0.1 | 10% |
| speed_1 | 0x10 | 1 | 30% |
| percent_60 | 0x1a | <NA> | 60% |
| percent_100 | 0x1b | 100% | |
| lead | 0x1c | Lead | <NA> |
<无按键> | 0x00 | <NA> | <NA> |
轴旋钮键码
| 轴旋钮档位名 | 键码 | 按钮文字 | 按钮替代文字 |
|---|---|---|---|
| off | 0x06 | OFF | <NA> |
| x | 0x11 | X | <NA> |
| y | 0x12 | Y | <NA> |
| z | 0x13 | Z | <NA> |
| a | 0x14 | A | <NA> |
| b | 0x15 | B | <NA> |
| c | 0x16 | C | <NA> |
<无按键> | 0x00 | <NA> | <NA> |
HAL 引脚命名与示例接线
HAL 引脚名称由按钮上印刷的文字派生,组件前缀为whb(见hal.h中mComponentPrefix)。用以下命令可列出全部引脚:
xhc-whb04b-6 -p从 example-configuration.hal 可以看到完整的接线模式:whb.halui.*、whb.axis.*、whb.button.*三类引脚与标准halui.*、axis.*信号一一net相连。典型片段如下:
# 加载手轮组件(HAL 模式 + 主轴倍率 + 进给倍率 + 大步进 5/10mm) loadusr -W xhc-whb04b-6 -HsfB # 电源开关信号 net machine.is-on halui.machine.is-on whb.halui.machine.is-on net pdnt.machine.on whb.halui.machine.on halui.machine.on net pdnt.machine.off whb.halui.machine.off halui.machine.off # 程序控制信号 net pdnt.program.run whb.halui.program.run halui.program.run net pdnt.program.stop whb.halui.program.stop halui.program.stop net pdnt.program.pause whb.halui.program.pause halui.program.pause net pdnt.program.resume whb.halui.program.resume halui.program.resume # 各轴手轮进给信号 net pdnt.axis.x.jog-scale whb.axis.x.jog-scale axis.x.jog-scale net pdnt.axis.x.jog-counts whb.axis.x.jog-counts axis.x.jog-counts net pdnt.axis.x.jog-enable whb.axis.x.jog-enable axis.x.jog-enable net pdnt.axis.x.jog-vel-mode whb.axis.x.jog-vel-mode axis.x.jog-vel-mode宏按钮可映射到 halui 的 MDI 命令引脚:
net pdnt.macro-1 whb.button.macro-1 halui.mdi-command-01 net pdnt.macro-2 whb.button.macro-2 halui.mdi-command-02 net pdnt.macro-5 whb.button.macro-5 halui.mdi-command-05 # ... 依此类推直到 macro-16部分宏被硬编码为固定功能(见hal.h注释):Macro-3/4 用于主轴升/降速,Macro-8 切换主轴方向,Macro-10 切换 DRO 相对/绝对显示,Macro-15/16 用于冷却液(flood)与喷雾(mist)开关。主轴相关接线示例:
net pdnt.spindle.is-on whb.halui.spindle.is-on spindle.0.on net pdnt.spindle.start whb.halui.spindle.start halui.spindle.0.start net pdnt.spindle.stop whb.halui.spindle.stop halui.spindle.0.stop net pdnt.spindle.increase whb.halui.spindle.increase halui.spindle.0.increase net pdnt.spindle-speed-abs whb.halui.spindle-speed-cmd spindle.0.speed-out-abs轴坐标回读用于刷新手轮 LCD 显示:
net pdnt.axis.x.pos-feedback halui.axis.x.pos-feedback whb.halui.axis.x.pos-feedback net pdnt.axis.x.pos-relative halui.axis.x.pos-relative whb.halui.axis.x.pos-relativeINI 侧可增加[HALUI]段的宏命令定义(example-configuration.hal顶部注释提供了 16 个MDI_COMMAND=(debug,macroN)模板),并在[HAL]段加载上述 HAL 文件。
实战运行:连通性调试与 HAL 模式
交互模式调试 USB 与按键事件
$ ../bin/xhc-whb04b-6 -ue init setting machine configuration to scale=80 max_velocity=800 init starting in simulation mode init usb context ... ok init not waiting for device XHC-WHB04B-6 vendorId=0x10ce productId=0xeb93, will continue in 0s .... ok init XHC-WHB04B-6 device found init detaching active kernel driver ... already detached init claiming interface ... ok init enabling reception ... ok in 0x04 ba 00 00 0e 11 00 ba delta 14 => | 04 | ba | | | 0.01( 5%) | X( ) | 0 | ba event axis inactive ( ) event axis active X ( ) event feed inactive ( ) event feed active 0.01( 5%) event data interpreted, display data ready in 0x04 82 01 00 0e 12 00 81 delta 14 => | 04 | 82 | reset | | 0.01( 5%) | Y( ) | 0 | 81 reset event pressed event data interpreted, display data ready in 0x04 9d 00 00 0e 12 01 9c delta 14 => | 04 | 9d | | | 0.01( 5%) | Y( ) | 1 | 9c event jog dial 1 ^Ctermination requested upon signal number 2 ... connection lost, cleaning up可以看到每帧 8 字节的原始报文(report ID0x04、随机字节、按钮键码、进给旋钮键码0x0e=0.01/5%、轴旋钮键码0x11=X 或0x12=Y、手轮 delta、校验和),以及由组件解释出的 axis/feed 激活、reset 按下/释放、jog dial 事件。程序按 Ctrl-C 会通过信号处理器(main.cc中的registerSignalHandler注册 SIGINT/SIGTERM)走 "termination requested → cleaning up" 的优雅退出路径。
HAL 模式(halrun)加载
$ halrun msgd:0 stopped rtapi:0 stopped halcmd: loadusr ../bin/xhc-whb04b-6 -Hup halcmd: init setting machine configuration to scale=80 max_velocity=800 hal initialize HAL component in HAL mode xhc-whb04b-6 ... ok hal initialize shared HAL memory for component id 80 ... ok hal bit out xhc-whb04b-6.out.button.reset [...] //! < 省略若干行 init usb context ... ok init XHC-WHB04B-6 device found init detaching active kernel driver ... already detached init claiming interface ... ok init enabling reception ... ok in 0x04 47 03 00 10 12 00 45 delta 16 => | 04 | 47 | start-pause | | 1( 30%) | Y( ) | 0 | 45 hal start/stop enabled (pin # 4) hal OFF no axis active hal Y axis active hal step mode is continuous hal step size 12 halcmd:-Hup组合的含义是:HAL 模式(-H)、打印 USB 接收数据(-u)与 HAL 引脚消息(-p)。加载后组件在共享内存中注册为组件 id 80,创建形如xhc-whb04b-6.out.button.reset的 bit 输出引脚,随后接管 USB 设备并将按钮/旋钮/手轮事件实时写入 HAL。
结语
xhc-whb04b-6组件的价值在于:它在厂商不公开协议的前提下,通过完整的逆向工程把 WHB04B-6 的 USB 报文(接收 8 字节、发送 7 字节 + report ID)与显示编码全部解析清楚,并以结构体打包方式固化在 usb.h 中。组件由 Raoul Rubien 基于前代设备组件 xhc-hb04.cc 起步开发,2020 年由 alkabal_free.fr 为 LinuxCNC 更新维护。若你拥有该手轮,可先以-ue验证连通性,再按 example-configuration.hal 的模板将按钮、宏、手轮进给与主轴控制逐条接入自己的机器 HAL 文件,即可获得完整的无线手脉操作体验。
- 工业制造
- 嵌入式
【免费下载链接】linuxcnc
LinuxCNC controls CNC machines. It can drive milling machines, lathes, 3d printers, laser cutters, plasma cutters, robot arms, hexapods, and more.
相关推荐
LinuxCNC 内置 GTK 版 Verser Probe 探针测头屏幕:gladevcp 加载、HAL 引脚与自动测量实战指南
LinuxCNC 内置 GTK 版 Verser Probe 探针测头屏幕:gladevcp 加载、HAL 引脚与自动测量实战指南 本篇文章围绕 LinuxCN
工业制造嵌入式终极指南:LinuxCNC HAL组件中volatile关键字的深度解析与优化实践
终极指南:LinuxCNC HAL组件中volatile关键字的深度解析与优化实践 LinuxCNC作为一款功能强大的开源数控系统,能够驱动铣床、车床、3D打印
工业制造嵌入式RIOT IEEE802.15.4 无线电 HAL(RDM 0004)技术指南
RIOT IEEE802.15.4 无线电 HAL(RDM 0004)技术指南 RIOT 的 IEEE802.15.4 无线电 HAL:架构、接口定义与设备驱动
物联网嵌入式操作系统实时系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考