开发手上的一个云台,使用的就是PELCO-D协议。这个协议开始网上找了一圈,发现下载完整版的协议大多是还都要收费,后面在官方下载了一份原版完整版协议的协议内容,配合网上搜索到的资料完成对手上这块云台的配置。 虽然原版的协议支持很多功能,包括摄像头的一些控制,这当然与具体的产品有关,手上的这款只是对云台的控制,包括复位,预置设置,调用和删除等一些基础的功能。
由于最终是要结合手上的串口摄像机,完成定时定点进行拍照的功能,所以这里先写云台的功能函数,下面写摄像头模块时再一起结合。

先来简单了解一下协议本身。

PELCO-D:

数据格式: 1 位起始位、 8 位数据、 1 位停止位,无效验位。波特率: 9600B/S(根据本身改变);
命令格式:

字节 1 字节 2 字节 3 字节 4 字节 5 字节 6 字节 7
同步字节 地址码 指令码 1 指令码 2 数据码 1 数据码 2 校验码

说明
1.该协议中所有数值都为十六进制数;
2.同步字节始终为 FFH ;
3.地址码为摄像机的逻辑地址号,地址范围: 00H –FFH ;
4.指令码表示不同的动作;
5.数据码 1、2 分别表示水平、垂直方向速度( 00-3FH ),FFH 表示 “turbo ”速度;
6.校验码 = MOD[ (字节 2 + 字节 3 + 字节 4 + 字节 5 + 字节 6)/100H]。

指令码格式:

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
命令字 1 Sence码 0 0 自动 /手动扫描 摄像机打开/关闭 光圈关闭 光圈打开 焦距拉近
命令字 2 焦距拉远 视角变宽 视角变窄 0

说明
Sence 码:与 Bit4 和 Bit3 有关。在 Bit4 和 Bit3 为 1 的情况下,如果 Sence 码为 1,则命令就是自动扫描和和摄像机打开;如果 Sence 码为 0,则命令就是手动扫描和摄像机关闭。当然如果Bit4 或 Bit3 为 0 的话那命令就无效了;
数据 1: 表示镜头左右平移的速度,数值从 $00( 停止 )到$3F( 高速 ),另外还有一个值是 $FF ,表示最高速;
数据 2: 表示镜头上下移动的速度,数值从 $00( 停止 )到$3F( 最高速 );
校验码:指 Byte2 到 Byte6 这 5 个数的和 (若超过 255 则除以 256 然后取余数 )。

以上就是PELCO-D协议的大致内容,如果是PELCO-P协议可以参考文末的文档做出相应的修改即可。

下面列出几组参考用例
以地址码 0x01 为例:
{0xff,0x01,0x00,0x08,0x00,0xff,0x08,}// 上
{0xff,0x01,0x00,0x10,0x00,0xff,0x10,}// 下
{0xff,0x01,0x00,0x04,0xff,0x00,0x04,}// 左
{0xff,0x01,0x00,0x02,0xff,0x00,0x02,}// 右
{0xff,0x01,0x00,0x07,0x00,0x01,0x09,}// 转至预置点 001
{0xff,0x01,0x00,0x03,0x00,0x01,0x05,}// 设置预置点 001
{0xff,0x01,0x00,0x05,0x00,0x01,0x07,}// 删除预置点 001
//以下几组我使用的云台没有功能,仅做参考。
{0xff,0x01,0x00,0x20,0x00,0x00,0x21,}// 变倍短
{0xff,0x01,0x00,0x40,0x00,0x00,0x41,}// 变倍长
{0xff,0x01,0x00,0x80,0x00,0x00,0x81,}// 聚焦近
{0xff,0x01,0x01,0x00,0x00,0x00,0x02,}// 聚焦远
{0xff,0x01,0x02,0x00,0x00,0x00,0x03,}// 光圈小
{0xff,0x01,0x04,0x00,0x00,0x00,0x05,}// 光圈大
{0xff,0x01,0x00,0x0b,0x00,0x01,0x0d,}// 灯光关
{0xff,0x01,0x00,0x09,0x00,0x01,0x0b,}// 灯光开以上对应的停命令均是 :
{0xff,0x01,0x00,0x00,0x00,0x00,0x01,}// 停命令

下面是各个封装的功能函数。

返回校验和

/********************************************************************
名称:uint16_t  ADD8_Check(uint8_t *num_Data,uint16_t num_Size)
功能:返回校验和
输入:校验数组,校验长度
输出:校验值
作者:liuguizhou
**********************************************************************/
uint16_t  ADD8_Check(uint8_t *num_Data,uint16_t num_Size){uint16_t i;uint16_t data_sum=0;for(i=1; i<num_Size; i++){data_sum += num_Data[i];}data_sum = (data_sum%256)&0xFF;   return data_sum;
}

复位功能

这个复位功能需要参考完整版协议,上面没有提到。
可以参考这篇博客,有个别功能的讲解。
协议要点整理

/********************************************************************
名称:void PTZ_rest()
功能:云台复位
输入:无
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_rest(void)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=0x33;                    //command2PTZ_TX_BUF[num++]=REST_level_speed; PTZ_TX_BUF[num++]=REST_pitch_speed; check_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}

云台停止移动

/********************************************************************
名称:void PTZ_stop()
功能:云台停止移动
输入:无
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_stop(void)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=0x00;            //command2PTZ_TX_BUF[num++]=0x00;                //level_speedPTZ_TX_BUF[num++]=0x00;         //pitch_speedcheck_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}

云台上下移动

/********************************************************************
名称:void PTZ_up_down(uint8_t command2)
功能:云台上下移动
输入:功能码2
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_up_down(uint8_t command2)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=command2;            //command2PTZ_TX_BUF[num++]=0x00;                //level_speedPTZ_TX_BUF[num++]=PTZ_speed;        //pitch_speedcheck_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; 

云台左右移动

/********************************************************************
名称:void PTZ_left_right(uint8_t command2)
功能:云台左右移动
输入:功能码2
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_left_right(uint8_t command2)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=command2;            //command2PTZ_TX_BUF[num++]=PTZ_speed;               //level_speedPTZ_TX_BUF[num++]=0x00;         //pitch_speedcheck_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}

云台预置点的设置、调用和删除

/********************************************************************
名称:void PTZ_Set_preset_point(uint8_t command2, uint8_t serial_num)
功能:云台设置预置点
输入:功能码2, 预置点参数
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_Set_preset_point(uint8_t command2, uint8_t serial_num)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=command2;            //command2PTZ_TX_BUF[num++]=0x00;                PTZ_TX_BUF[num++]=serial_num;        check_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}/********************************************************************
名称:void PTZ_Delete_preset_point(uint8_t command2, uint8_t serial_num)
功能:云台删除预置点
输入:功能码2, 预置点参数
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_Delete_preset_point(uint8_t command2, uint8_t serial_num)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=command2;            //command2PTZ_TX_BUF[num++]=0x00;                PTZ_TX_BUF[num++]=serial_num;        check_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}/********************************************************************
名称:void PTZ_Delete_preset_point(uint8_t command2, uint8_t serial_num)
功能:云台调用预置点
输入:功能码2, 预置点参数
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_Call_preset_point(uint8_t command2, uint8_t serial_num)
{uint16_t num=0;uint8_t check_num = 0;PTZ_TX_BUF[num++]=Sync_byte;PTZ_TX_BUF[num++]=PTZ_addres;     //PTZ地址码PTZ_TX_BUF[num++]=0x00;              //command1PTZ_TX_BUF[num++]=command2;            //command2PTZ_TX_BUF[num++]=0x00;                PTZ_TX_BUF[num++]=serial_num; check_num = ADD8_Check(PTZ_TX_BUF,num);PTZ_TX_BUF[num++]=check_num; PTZ_Send_String(PTZ_TX_BUF, num);
}

以上就是最基础的云台控制功能,下面就要实现跑点的操作。这个云台本身无法获取当前位置的信息,所以只有采取发送移动指令,运行一段时间,停止指令。但是每次这样通过时间控制,难免会出现空转,卡转等一些情况,所以还是采取先设置预置点,再依次跑预置点的方案。这样子会更准确一些,其实这里可以看到,预置点就是记录位置信息,所以肯定是可以获取位置信息的,而且通过查看协议,也可以看到有获取位置信息的功能码,不过经过测试,我手上这款云台并不支持这个功能。

/********************************************************************
/********************************************************************
名称:void PTZ_Init(void)
功能:云台第一次初始化
输入:无
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_Init(void)
{if(PTZ_Init_flag == 1){if(preset_point_count == 0){PTZ_move_left_right(left,14);if(set_Preset_point_success_flag == 1){set_Preset_point_success_flag = 0;Preset_point = ((Preset_point)%256)&0xff;PTZ_Set_preset_point(Set_preset_point, Preset_point);stop_timer_flag = 1;Timer_Start(ETIM1);feed_dogs();}}if((preset_point_count >= 1 && preset_point_count < 3) || (preset_point_count > 6 && preset_point_count < 9)){PTZ_move_left_right(left,76);if(set_Preset_point_success_flag == 1){set_Preset_point_success_flag = 0;Preset_point = ((Preset_point+1)%256)&0xff;PTZ_Set_preset_point(Set_preset_point, Preset_point);stop_timer_flag = 1;Timer_Start(ETIM1);feed_dogs();}}if(preset_point_count == 3 || preset_point_count == 6){PTZ_move_up_down(down, 35);if(set_Preset_point_success_flag == 1){set_Preset_point_success_flag = 0;Preset_point = ((Preset_point+1)%256)&0xff;PTZ_Set_preset_point(Set_preset_point, Preset_point);stop_timer_flag = 1;Timer_Start(ETIM1);feed_dogs();}}    if(preset_point_count > 3 && preset_point_count < 6){PTZ_move_left_right(right, 76);if(set_Preset_point_success_flag == 1){set_Preset_point_success_flag = 0;Preset_point = ((Preset_point+1)%256)&0xff;PTZ_Set_preset_point(Set_preset_point, Preset_point);stop_timer_flag = 1;Timer_Start(ETIM1);feed_dogs();}}}
}名称:void PTZ_move_left_right(uint8_t command2,uint16_t move_time)
功能:云台左右移动
输入:功能码2, 移动时间
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_move_left_right(uint8_t command2,uint16_t move_time)
{if(preset_point_count < 9){if(move_success_flag == 1){PTZ_left_right(command2);move_timer_flag = 1;Timer_Start(ETIM2);move_success_flag = 0;feed_dogs();}if(move_timer_count >= move_time){Timer_Close(ETIM2);move_timer_count = 0;stop_success_flag = 1;feed_dogs();}if(stop_success_flag == 1){set_Preset_point_success_flag = 1;printf("set_Preset_point_success_flag\r\n");PTZ_stop();stop_success_flag = 0;feed_dogs();}if(stop_timer_count >= 20){Timer_Close(ETIM1);stop_timer_count = 0;stop_timer_flag = 0;move_success_flag = 1;preset_point_count++;printf("preset_point_count+++ = %d \r\n", preset_point_count);feed_dogs();}}
}/********************************************************************
名称:void PTZ_move_up_down(uint8_t command2, uint16_t move_time)
功能:云台上下移动
输入:功能码2,移动时间
输出:无
作者:liuguizhou
**********************************************************************/
void PTZ_move_up_down(uint8_t command2, uint16_t move_time)
{if(preset_point_count < 9){if(move_success_flag == 1){move_timer_flag = 1;Timer_Start(ETIM2);PTZ_up_down(command2);move_success_flag = 0;feed_dogs();}if(move_timer_count == move_time){move_timer_count = 0;Timer_Close(ETIM2);stop_success_flag = 1;feed_dogs();}if(stop_success_flag == 1){set_Preset_point_success_flag = 1;PTZ_stop();stop_success_flag = 0;feed_dogs();}if(stop_timer_count == 20){Timer_Close(ETIM1);stop_timer_count = 0;stop_timer_flag = 0;move_success_flag = 1;preset_point_count++;printf("preset_point_count--- = %d \r\n", preset_point_count);feed_dogs();}}
}

这就完成了云台定点移动的基本功能,之前找资料下载了一个相对比较完整的小程序,我一起打包上传到资源中,有需要自取。

模块学习2:基于PELCO-D协议对云台进行定点控制相关推荐

  1. 西门子机械手臂基于S7-1200 PLC和Wincc组态的定点控制系统设计

    西门子机械手臂基于S7-1200 PLC和Wincc组态的定点控制系统设计

  2. Qt Creator 模块学习 ——音视频播放(解决了DirectShowPlayerService::doSetUrlSource问题)

    Qt Creator 模块学习 --音视频播放 Qt对于音视频的播放和控制,相机拍照,收音机等多媒体应用提供了强大的支持.Qt5有了专门的模块Qt Multimedia来实现多媒体的应用.C++中多媒 ...

  3. 《 Python程序设计项目案例》— 用Python开发的基于TCP通讯协议的私人聊天室 (期末大作业、结课作业、课程设计、毕业设计)

    基于Python与TCP协议的私人聊天室(GUI交互界面,用户注册.用户登录.实时聊天,文件上传与下载) 用Python开发的基于TCP通讯协议的实时聊天通讯和文件共享应用 目录 基于Python与T ...

  4. 基于MQTT应用层协议的物联网家庭温湿度监测系统

    引言 出生于互联网时代的我们,见证了智能手机和个人电脑通过计算机网络互相进行连接,把每个人紧密地连接在一起,形成了一个地球村.而今,我们即将迈入5G时代,在通信技术不断发展的今天,连接到互联网的将不仅 ...

  5. Python学习笔记28:从协议到抽象基类

    Python学习笔记28:从协议到抽象基类 今后本系列笔记的示例代码都将存放在Github项目:https://github.com/icexmoon/python-learning-notes 在P ...

  6. JavaScript之后端Web服务器开发Node.JS基本模块学习篇

    JavaScript之后端Web服务器开发Node.JS基本模块学习篇 基本模块 fs文件系统模块 stream支持流模块 http crypto加密模块 基本模块 因为Node.js是运行在服务区端 ...

  7. <转载>光模块学习总结

    作者写的非常详细全面,转载到这儿大家一起学习学习. 如有侵权请联删. 作者: 曹世宏 链接: https://cshihong.github.io/2020/08/16/光模块学习总结/ 光模块简介 ...

  8. 【深度学习】基于Pytorch进行深度神经网络计算(二)

    [深度学习]基于Pytorch进行深度神经网络计算(二) 文章目录 1 延后初始化 2 Pytorch自定义层2.1 不带参数的层2.2 带参数的层 3 基于Pytorch存取文件 4 torch.n ...

  9. 【深度学习】基于Torch的Python开源机器学习库PyTorch卷积神经网络

    [深度学习]基于Torch的Python开源机器学习库PyTorch卷积神经网络 文章目录 1 CNN概述 2 PyTorch实现步骤2.1 加载数据2.2 CNN模型2.3 训练2.4 可视化训练 ...

最新文章

  1. 一条命令安装Windows Subsystem for Linux
  2. MySQL触发器使用详解
  3. 震惊!Canvas原来还能这么搞!代码画一个时钟出来
  4. 星际战甲堕落轰击者结合目标_星际战甲-任务指南
  5. 远程协助TeamView软件 轻松控制计算机
  6. 三句代码调整进程优先级
  7. 实际的Reactor操作–检索Cloud Foundry应用程序的详细信息
  8. redis常用命令与特性
  9. vscode修改c 项目_windows 10上使用vscode编译运行和调试C/C++
  10. 如何使用android studio,怎么学习使用Android Studio?
  11. 让Minimal开源UI组件支持中文
  12. java转码工具应用程序_java转码工具native2ascii.exe的使用方法
  13. 阿里面试官内部题库,阿里发布2022年Java岗(正式版)面试题
  14. Emun 枚举类型使用浅析——包括enumSet enumMap
  15. 关系型数据库与非关系型数据库的简介、对比和说明!!!
  16. uboot 看门狗喂狗
  17. Android本地数据持久化:内部存储和外部存储
  18. 常用校验方式以及优缺点(奇偶校验,CRC校验,校验和)
  19. 什么是RNN?一文看懂强大的循环神经网络(Recurrent Neural Network, RNN)
  20. 2021-05-16刷题

热门文章

  1. Observability:Wavefront
  2. i5 1240p使用perf避坑指南
  3. 深度信念网络_【文章推荐】应用于油中溶解气体分析的深度信念网络与典型神经网络对比研究...
  4. 扫脸测试开什么车软件,扫脸测年龄app
  5. 服务器无法取消指令方块显示,我的世界服务器如何关掉命令方块的提示(如图)...
  6. VMware 虚拟磁盘文件备份与恢复
  7. Pytest+Unittest+Git+Jenkins企业级CICD自动化测试平台建设方案
  8. sina vistor system
  9. 【信息安全】屁股决定脑袋的COSO内控框架,一篇对COSO的趣评
  10. js修改对象数组⾥的对象名字