普密斯电动变倍镜头通过 RS-232(或以太网)控制,协议是一套精简的 ASCII 指令,共 5 条。每条指令都是三个字节:字母 X、一个命令字母、回车符 0x0D。控制器用九字节帧应答位置与行程查询,用单字节状态值 0x55 表示运动结束。本文按实现原样记录协议,包括两个换算公式,以及最容易让集成工程师踩坑的一条行为:电机运动期间控制器停止应答。
本文面向把电动变倍镜头接到 PLC、运动控制器、单板计算机或 Linux 主机的工程师——这些场景用不上 Windows SDK,只能直接操作字节流。
| 项目 | 值 |
|---|---|
| 指令数量 | 5 条(XH、XG、XZ、XM、XN) |
| 帧结束符 | 0x0D(CR)——指令与应答均使用 |
| 串口配置 | 9600 波特率、8 数据位、无校验 |
| 以太网端口 | 4196 |
| 停止判据 | 0x55——其他任何值或读取超时,均视为「仍在运动」 |
| 行程公式 | maxLength = (readData − 750) × 1.3 |
| 位置公式 | pos = (readData − 500) × 1.3 |
| 轮询建议 | 每次状态查询间隔至少 50 ms;整体超时给到 10 秒以上 |
| 参数 | 值 | 说明 |
|---|---|---|
| 物理层 | RS-232(直连或经 USB 转 RS-232)或以太网 | 控制器二选一,不支持同时使用 |
| 波特率 | 9600 | 协议文档与控制卡 API 文档取值一致 |
| 数据位 | 8 | — |
| 校验位 | 无 | — |
| TCP 端口 | 4196 | 走网络接口时使用 |
| 结束符 | 0x0D | 收发双向 |
在讨论协议之前,接线必须正确:先接好并锁紧电机线与 RS-232 线,再上电。在控制器带电状态下插拔电机线,是现场损害最大的一类操作,可能永久损坏电机。若电机线需要超过 5 m,请直接向工厂订购加长线,不要用多根短线拼接——拼接线或自制线不满足阻抗与屏蔽要求。
每条指令的形式都是 'X' + 命令字母 + 0x0D。
| 序 | 功能 | ASCII | HEX | 应答 |
|---|---|---|---|---|
| 1 | 回原点(回零) | X H CR | 0x58 0x48 0x0D | 无 |
| 2 | 运动到目标脉冲位置 | X G + 6 位 HEX + CR | 0x58 0x47 … 0x0D | 无 |
| 3 | 查询运动状态 | X Z CR | 0x58 0x5A 0x0D | 1 字节 |
| 4 | 读取总行程(最大脉冲) | X M CR | 0x58 0x4D 0x0D | 9 字节 |
| 5 | 读取当前位置 | X N CR | 0x58 0x4E 0x0D | 9 字节 |
XHTX: 0x58 0x48 0x0D # 'X' 'H' CR
镜头回到机械原点。注意:每次上电时镜头也会自动执行一次该复位,初始化耗时 25–35 秒,期间镜头不接受任何指令。因此上位机程序应在上电后至少等待 35 秒再打开端口。
XG数据段按 C 格式串 "%C%C%6X%C" 组织:字母 X、字母 G、一个六位十六进制数(不足六位时左侧用空格 0x20 补齐)、以及结束符 0x0D。
| 目标脉冲 | ASCII 字符 | 字节序列 |
|---|---|---|
| 100 | X G ␠␠␠␠ 6 4 CR | 0x58 0x47 0x20 0x20 0x20 0x20 0x36 0x34 0x0D |
| 1000 | X G ␠␠␠ 3 E 8 CR | 0x58 0x47 0x20 0x20 0x20 0x33 0x45 0x38 0x0D |
| 5000 | X G ␠␠ 1 3 8 8 CR | 0x58 0x47 0x20 0x20 0x31 0x33 0x38 0x38 0x0D |
| 10000 | X G ␠␠ 2 7 1 0 CR | 0x58 0x47 0x20 0x20 0x32 0x37 0x31 0x30 0x0D |
重要行为:若请求位置与当前位置相同,镜头不动,也不报错。因此上位机绝不能把「指令已发出」当作链路正常的证据。回读位置才是可靠的链路探针。
// 运动到绝对脉冲位置
int moveTo(int fd, long pulse) {
char buf[16];
// "%C%C%6X%C" —— 六位十六进制、空格补齐、CR 结尾
int n = snprintf(buf, sizeof(buf), "%c%c%6lX%c", 'X', 'G', pulse, '\r');
return write(fd, buf, n) == n ? 0 : -1;
}
XZTX: 0x58 0x5A 0x0D
等待 20 ms
RX: 1 字节
| 应答 | 含义 |
|---|---|
0x55 | 运动结束——镜头已停止 |
| 其他任何值 | 仍在运动 |
| 完全无数据 | 同样按「仍在运动」处理 |
这是整套协议中最重要的行为细节,厂商文档也明确写明:控制卡驱动电机期间,通信会被挂起。在一次变倍运动过程中,串口或网络链路可能完全读不到任何数据。
由此得到的工程结论是:轮询循环必须建立在「重试」之上,而不是建立在「故障检测」之上。参考实现如下:
XZ。0x55,等待后重试——不要判定为故障。厂商自有的 API 流程图在每次状态查询前等待 50 ms,并设置10 秒以上的整体超时。只有当整体超时耗尽仍无有效应答时,上位机才应判定镜头连接失败。
// 等待运动结束:每次轮询 50 ms,整体超时 10 s
int waitStop(int fd, int timeout_ms) {
int waited = 0;
char c;
while (waited < timeout_ms) {
usleep(50 * 1000); // 参考流程图:等待 50 ms 或更久
write(fd, "XZ\r", 3); // 0x58 0x5A 0x0D
usleep(20 * 1000); // 协议规定:读取前等待 20 ms
if (read(fd, &c, 1) == 1 && (unsigned char)c == 0x55)
return 0; // 已停止
waited += 70;
}
return -1; // 连接或运动异常
}
XMTX: 0x58 0x4D 0x0D
等待 20 ms
RX: 9 字节
| 字节 | 内容 |
|---|---|
| 1 | 0x58(固定) |
| 2 | 空 |
| 3–7 | 行程数据——五个字节,按 "%5X" 解析为整数并存入 readData |
| 8 | 0x0D |
| 9 | 空 |
sscanf(tbuffer + 2, "%5X", &readData);
maxLength = (readData - 750) * 1.3;
厂商文档中的算例:应答为 0x58 -- -- -- '2' '7' '1' '0' 0x0D -- 时,readData = 10000,故 maxLength = (10000 − 750) × 1.3 = 12025。
XNTX: 0x58 0x4E 0x0D
等待 20 ms
RX: 9 字节 (结构与 XM 完全相同)
sscanf(tbuffer + 2, "%5X", &readData);
pos = (readData - 500) * 1.3;
算例:readData = 10000 时,pos = (10000 − 500) × 1.3 = 12350。
(1) XH 回原点 -> 轮询 XZ 直到停止
(2) XM 读取总行程 -> 验证链路,取得 maxLength
(3) XG <6 位 HEX> 运动到目标位置 -> 轮询 XZ 直到停止
(4) XN 读取当前位置 -> 与目标比对(闭环)
两点让该时序可靠成立:
整套协议在语义上是严格串行的——发指令 → 运动 → 回读状态 → 发下一条。它不支持对同一支镜头并发下发指令。
本协议只提供位置回读能力。它不定义、也不保证任何重复定位精度数值。测试方法见同系列的《倍率与脉冲位置对应》一文;任何精度数字都应来自你在自身工况下的实测。
它其实指两种完全不同的东西,选错型号是常见且代价高昂的错误。
| 形态 | 型号标记 | 实际能力 |
|---|---|---|
| 被动倍率反馈 | 后缀 DS9 或 DS6,例如 PMS-LZ-63100DS9 | 变倍方式仍为手动。RS-232 只输出当前倍率或档位位置,不能接受指令。 |
| 主动电动控制 | 变倍类型码 04、05、09 或 10,例如 PMS-LZ-650104 | 五条指令全部接受。RS-232 主动驱动倍率变化。 |
下单前先看型号后缀。带 DS9 的镜头可以读、不能被控。
不是故障。控制卡在驱动电机期间会主动挂起通信,这是设计行为。用「超时 + 重试」处理,不要触发故障报警或重启。
若目标位置等于当前位置,镜头保持不动并静默成功。要么在上位机内维护当前位置,要么每次运动前用 XN 回读一次。
脉冲位置与具体型号绑定。它们来自随 SDK 提供的各型号脉冲表,同一倍率在不同型号、不同电机类型上对应的脉冲数并不相同。先用 XM 读取总行程,确认目标值落在有效区间内。
| 协议指令 | 旧版 SDK API | SDK V4.4.7 |
|---|---|---|
XH 回零 | MoveHome(Motor) | GoHome |
XG 运动 | MoveGoto(Motor, long dest) | MoveTo(pulse) |
XZ 状态 | MoveStatus(Motor) → 0 运动中 / 1 空闲 / 2 异常 | GetStatus |
XM 行程 | MoveMaxLength(Motor) | GetMaxPos |
XN 位置 | MovePos(Motor) | GetPos |
不要在同一个链路上混用两种方式。它们操作同一批硬件寄存器,混用——尤其在回零基准附近——会产生不一致的状态。
9600 波特率、8 数据位、无校验。走以太网时使用 TCP 端口 4196。
因为控制卡在驱动电机期间会主动挂起通信。用带超时的重试处理状态查询,不要把那段时间的静默当成故障。
看型号中的变倍类型码。04、05、09、10 为电动类型;DS9 或 DS6 后缀仅为被动反馈,变倍仍是手动。
可以。指令集就是五条 ASCII 字符串,带空闲串口的 PLC 可以直接组帧发送。PLC 侧程序需要你自行编写;我们提供协议定义,不提供 PLC 功能块。
不需要。DLL 只是同一套字节级协议在 Windows 上的便利封装。任何能打开串口或 TCP 套接字的平台都能控制该镜头。
XG 要发送的脉冲值从哪来
您将收到我们最新的动态资讯