pelco协议及其实现的简单认识
pelco协议及其实现的简单认识
2014-07-03 13:50:49 6272
分类专栏:
版权
儿童过敏性咳嗽在搞visca的同时顺便也搞了pelco。这⾥再做个笔记。
西北望乡何处是pelco,中⽂翻译为“派尔⾼”,在⾏⽂和写代码过程,写pelco⽐写“派尔⾼”快很多,所以⼀般就写pelco。这个协议在云台控制中⽤得⽐较多,⽐较出名的有PTZ,⽤rs232或rs485来通信。pelco有两种协议,D协议和P协议,两者命令封装不太⼀样,⽹上有协议的说明⽂档,也有实现的代码,我找到⼀个C#写的,某搜索引擎上找得到的介绍派尔⾼协议的,基本上都是直接把每个命令的数据⼀⼀写成数组来调⽤,个⼈认为这样不太⽅便。
本⽂所讲的是pelco D协议。
⼀、命令格式
⽂档中说pelco D协议的命令都是7个字节的(实际上,有些不是),命令格式如下图:
说明:
字节1:D协议同步头为0xFF。
字节2:相机编号(或称地址),范围为1~0xFF,0x01表⽰相机1。
字节3:CMND1,命令1。
字节4:CMND2,命令2。作为扩展命令,命令数值为奇数。
字节5:数据字节1,作为motion命令,其表⽰pan的速度。
字节6:数据字节2,作为motion命令,其表⽰tilt的速度。
字节7:检验码,计算公式:(字节2+字节3+字节4+字节5+字节6)% 0x100。注:检验码是除了同步头及本⾝(CKSM)字节外的所有字节的的和,再除以265,取余数(⽤“%”即可)。
命令共2⼤类,motion命令,和⾮motion命令(注:可以称为基本命令和扩展命令/⾼级命令)。其中motion命令,在CMND2中Bit0始终为0。反之,该⽐特为1表⽰⾮motion命令。
motion命令包含了⽔平移动、垂直移动、光圈、变焦、对焦等功能。这类命令是由命令1和命令2的各个位来表⽰的。如下图:
要实现某⼀项功能,只要在对应的位置设为1即可,有些命令是可以同时设置的,但有些是不⾏的,⽐如,可以同时实现左(右)转和向上(下)转动,但不能同时左转及右转(两者是互斥的)。
Bit7含义为“n bit”(n⼀词,在linux内核中使⽤⽐较多,我其实也搞不明⽩这个词中⽂该怎么表达),它决定了Bit4和Bit3的含义。如下图所⽰:
其实说⽩了,就是这3个⽐特的哪些组合可以控制相机上断电,⾃动扫描,哪些⽆效,等等。说到这⾥,想起来了公司某部门发的⼀个邮件,说某客户想接⼊云台,是⽤派尔⾼协议来控制的,然后还顺带⼀个中⽂的协议⽂档,这个⽂档翻译得不伦不类,应该是机器翻译的,把“n bit”翻译成“感觉字节”,⼀开始看中⽂⽂档时,完全⼀头雾⽔,后⾯经过努⼒,上⽹上查了英⽂原版,才有点理解。所以,有时候,看英⽂原版获取的资源更通俗,更准确。
⼆、响应
相机返回的响应包有4种,0字节、4字节、7字节、18字节。除了第⼀种外,其它每种都和上⾯给出的命令格式相似,同步头+相机地址
+信息体+检验码。⽂档中有每种响应包的具体格式的描述,如果格式来解析即可得到想要的数据。⽂档中说⼤部分命令是有返回值的——像上⾯的motion命令,也有响应包,但我实际测试的结果,串⼝是没有返回什么数据的,或者是我拿到的那个东西本⾝就是这样的。
三、协议⽂档备注
协议⽂档中每条命令都讲得⽐较细,不过,有部分命令是⼚家⾃⼰实现的,⽐如,有些命令超过7个字节,这跟协议上讲的有冲突,但实际上却是可以的。这个主要是看⼚家提供的协议⽂档了。说到这,不得不提现在我接⼿的这个任务,⼚家提供的⽂档惜墨如⾦,不肯多写⼀点字,⽂档⼜不规范,东写⼀点,西写⼀点,给的⽂档也不全,有些命令还要问⼈家才知道。
四、实现
为了⽅便,专门为pelco通信定义了PELCOPacket_t结构体(其实它和上⼀篇⽂章的visca那个结构体是同⼀个东西),命令封装如下:
void _pelco_append_byte(PELCOPacket_t *packet, unsigned char byte)
{
packet->bytes[packet->length]=byte;
(packet->length)++;
东方明珠游戏机
}
void _pelco_init_packet(PELCOPacket_t *packet)
沫夜微光
{
// t it to null
memt(packet->bytes, '\0', sizeof(packet->bytes));
// we start writing at byte 2, the first byte and the cond will be filled by the
// packet nding function(_pelco_nd_packet). This function will also append a cksm.
packet->length = 2;
}
注意,初始化时,命令包的长度是2,因为pelco协议的真正数据是从第2个字节开始的,这让调⽤者关注的是真正的数据,⽽不⽤理会同步头、相机地址等信息。命令发送如下:
// All commands are 7 bytes long in D Protocol
int _pelco_nd_packet(PELCOInterface_t *iface, PELCOPacket_t *packet)
{
鸡肉怎么做int cksm = 0;
int i = 0;
// check data:
if (iface->address>0xff)
{
return PELCO_FAILURE;
}
// build header:
packet->bytes[0] = 0xff;
packet->bytes[1] = iface->address;
// e spec, some cmd has 7 bytes, some has 9 bytes
for (i = 0; i < packet->length; i++)
{
cksm += packet->bytes[1+i];
摩尔多瓦语}
cksm = cksm % 0x100;
/*
cksm = (packet->bytes[1] + packet->bytes[2] + packet->bytes[3] +
packet->bytes[4] + packet->bytes[5]) % 0x100;
*/
// append footer(cksm)
_pelco_append_byte(packet,cksm);
著名的物理学家return _pelco_write_packet_data(iface,packet);
}
因为有些命令不只有7个字节,所以这⾥⽤for循环计算每个需要计算的字节,⽽不是指定哪⼀些字节被计算。
命令的封装接⼝⽐较简单,基本上和visca⼀样,⽐如,像stop命令,就是所有的信息体都搞成0就⾏了。
int pelco_camera_stop(PELCOInterface_t *iface)
{
PELCOPacket_t packet;
_pelco_init_packet(&packet);
_pelco_append_byte(&packet,0x00);
_pelco_append_byte(&packet,0x00);
魔兽世界台词_pelco_append_byte(&packet,0x00);
_pelco_append_byte(&packet,0x00);
return _pelco_nd_packet_no_reply(iface, &packet);
}
参考资源:
后记:本⽂出现很多次“搞”,近来的确是东搞西搞,⼈在公司,⾝不由⼰。本⽂仅对协议进⾏描述,不贴出实际的实现代码。李迟记于2014年7⽉3⽇