PTP概览: PTP是一种网络时间同步协议,设计用于实现局域网络中设备间的高精度时间同步,通常能达到亚微秒乃至纳秒级的同步精度。它主要服务于对时间同步有严格要求的应用场景,如金融交易、电信网络、科学研究、工业自动化等。
核心特点:
PTP作为一种高精度时间同步技术,能够实现亚微秒乃至约30纳秒的精准同步,但这需要网络中的交换机等节点具备PTP支持,以确保纳秒级的同步精度。尽管传统的NTP能满足多数应用场景,提供大约5毫秒内的时钟同步,非极高端需求外,PTP并非标配之选,因其对硬件和网络配置有着更高要求。
PTP协议在IEEE 1588标准中定义,主要通过两种方式在网络中传输数据包:
而想要在UDP上承载PTP,需要确保网络设备(如交换机和终端设备)能够支持PTP,并正确配置网络接口以使用UDP端口转发PTP消息。在软件层面,可以利用编程语言(如C、C++、Python或Go)中的网络编程库来发送和接收这些UDP数据包,并根据PTP协议规范处理时间戳和同步算法。
海康工业网口相机支持PTP时钟同步功能,可以通过PTP协议,实现多场景的高精度时间戳同步,例如:多个工业相机之间、工业相机与主机时间、工业相机与硬件授时模块(北斗/GPS授时服务器)等.
海康相机可以通过简单的参数配置,在参数配置Transport layer下启用IEEE 1588 V2(即PTP v2)功能,通过设置相机为主时钟(Master)或从时钟(Slave),并利用交换机等网络设备实现纳秒级的同步拍照。因此,在适当的网络配置下,海康工业相机能够利用PTP功能满足对时间同步有严格要求的应用场景。

海康工业相机支持的PTP状态模式如下:
工业相机中的时间戳是一种记录图像获取精确时刻的功能,它是工业视觉系统和高精度测量应用中的核心要素。以下是对工业相机时间戳的详细介绍:
时间戳指的是附着在每一帧图像数据上的时间信息,通常表示相对于相机内部时钟的相对时间(非UTC时间)。这个时间戳使得用户可以准确知道每幅图像的捕获时间,对于需要精确同步多相机系统、分析动态过程或与外部事件关联的应用至关重要。
a) 实现机制
海康工业相机支持多种途径获取相机内部时间戳,主要分类如下:
三种类型的时间戳,都是基于相机内部时钟产生相对时间,由硬件晶振生成时间基准,开始时间一般为相机上电时刻
| 相机参数 | 说明 |
|---|---|
| GevTimestampTickFrequency | 相机时间戳晶振频率,其倒数即为时间戳的单位,如时钟频率为 100MHz 时相机时间戳单位为 10ns,不同相机该频率可能不同,需要结合该参数具体值来确认 |
| GevTimestampControlLatch | 获取当前的时间戳值,时间戳值并不会自动更新,使用时需要执行该命令进 行获取 |
| GevTimestampValue | 时间戳值,需搭配GevTimestampControlLatch获取,本身不会主动更新 |
图像嵌入式时间戳,用于记录相机的拍照时刻。
通常需要结合sdk接口,在_MV_FRAME_OUT_INFO_EX_帧信息结构体获取得到;

也可以通过Wireshark抓包,获取相机的图像数据流GVSP包,在leader头包中获取;


海康工业相机支持多种事件,每一种事件产生,都会有时间戳记录
| 事件类型 | 简介 |
|---|---|
| Acquisition Start | 采集开始 |
| Acquisition End | 采集结束 |
| Frame Start | 帧开始 |
| Frame End | 帧结束 |
| Frame Burst Start | 帧触发开始 |
| Frame Burst End | 帧触发结束 |
| Exposure Start | 曝光开始 |
| Exposure End | 曝光结束 |
| Line0 Rising Edge | Line 0 上升沿 |
| Line0 Falling Edge | Line 0 下降沿 |
| Frame Start Over Trigger | 帧开始过触发 |
| Over Run | 过载 |
| Stream Transfer Overflow | 相机缓存内图像被覆盖 |
| Frame Trigger Wait | 帧触发等待,相机可被触发时输出event |
| Software Active | 软触发有效 |
| Image Error | 图像错误 |
在MVS中,设置操作方法:


以相机常用的时间戳为例,梳理了下工业相机比较场景的时间戳关系,以相机相对时间为基准,具体如下图:

3. Line0RisingEdge:触发信号通过line0给到相机
4. FrameStart:图像输出开始
5. nDevTimeStamp:时间戳打包到leader包时刻
6. ExposureStart:sensor开始曝光时刻
7. ExposureEnd:sensor结束曝光时刻
8. nHoststamp: 图像头包到达主机时间,主机时间,非相机时间戳
9. FrameEnd:相机端图像输出结束
// ch:开启相机Event功能 | en:Set Event On
char const *nEvent_ID[]={"Line0RisingEdge","FrameStart","FrameEnd", "ExposureStart","ExposureEnd"};
for(int i=0;i<sizeof(nEvent_ID)/sizeof(nEvent_ID[0]);i++)
{
nRet = MV_CC_SetEnumValueByString(handle, "EventSelector",nEvent_ID[i]);
if (MV_OK != nRet)
{
printf("Set Event Selector fail! nRet [0x%x],nEvent_ID:%d\n", nRet,i);
}
nRet = MV_CC_SetEnumValueByString(handle, "EventNotification", "On");
if (MV_OK != nRet)
{
printf("Set Event Notification fail! nRet [0x%x]\n", nRet);
}
// ch:注册event事件回调函数
nRet = MV_CC_RegisterEventCallBackEx(handle, nEvent_ID[i],EventCallBack, handle);
if (MV_OK != nRet)
{
printf("Register Event CallBack fail! nRet [0x%x]\n", nRet);
}
}
相机事件配置与事件回调函数注册
void __stdcall EventCallBack(MV_EVENT_OUT_INFO * pEventInfo, void* pUser)
{
if (pEventInfo)
{
int64_t nBlockId = pEventInfo->nBlockIdHigh;
nBlockId = (nBlockId << 32) + pEventInfo->nBlockIdLow;
int64_t nTimestamp = pEventInfo->nTimestampHigh;
nTimestamp = (nTimestamp << 32) + pEventInfo->nTimestampLow;
printf("EventName[%s],Timestamp[" "%" PRIu64 "]\n",pEventInfo->EventName,nTimestamp);
}
}
事件回调函数内部处理
void __stdcall ImageCallBackEx(unsigned char * pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{
uint64_t m_DevTimeStamp=0;//设备产生图像的时间
int64_t m_HostTimeStamp =0;//图像头包到达主机时间
if (pFrameInfo)
{
m_DevTimeStamp = pFrameInfo->nDevTimeStampHigh;
m_DevTimeStamp = (m_DevTimeStamp << 32)+pFrameInfo->nDevTimeStampLow;
m_HostTimeStamp=pFrameInfo->nHostTimeStamp;
printf("GetOneFrame, Width[%d], Height[%d], nFrameNum[%d],nDevTimeStamp[" "%" PRIu64 "],nHostTimeStamp[" "%" PRIu64 "]\n",
pFrameInfo->nWidth, pFrameInfo->nHeight, pFrameInfo->nFrameNum,m_DevTimeStamp,m_HostTimeStamp);
}
}
通过回调函数取流并通过帧信息结构体中获取nDevTimeStamp、nHoststamp
3. 相机参数时间戳获取
//获取相机当前时间戳
//仅网口相机支持
MVCC_INTVALUE_EX nGevTimestampValue;
nRet = MV_CC_SetCommandValue(handle, "GevTimestampControlLatch");
if (MV_OK != nRet)
{
printf("Gev TimestampControlLatch fail! nRet [%x]\n", nRet);
//break;
}else
{
nRet = MV_CC_GetIntValueEx(handle,"GevTimestampValue",&nGevTimestampValue);
if (MV_OK == nRet)
{
printf("Get GevTimestampValue = [%lld] Success!\n",(long long)nGevTimestampValue.nCurValue);
}
}
参考文章:ptpd安装部署
ptpd开源链接:github
ptpd通常指的是实现Precision Time Protocol (PTP) 协议的守护进程,用于在计算机网络中提供高精度的时间同步服务;
1|sudo apt-get install net-tools
2|ifconfig
2、查看网卡支持项
1|sudo apt-get install ethtool
2|sudo ethtool -T ens33

软件时间戳需要包括参数
SOF_TIMESTAMPING_SOFTWARE
SOF_TIMESTAMPING_TX_SOFTWARE
SOF_TIMESTAMPING_RX_SOFTWARE
硬件时间戳需要包括参数
SOF_TIMESTAMPING_RAW_HARDWARE
SOF_TIMESTAMPING_TX_HARDWARE
SOF_TIMESTAMPING_RX_HARDWARE
timedatectl status
sudo timedatectl set-ntp false

sudo apt-get install ptpd
sudo ptpd -M -i ens33
开启ptpd后,可在进程中发现ptpd相关进程

sudo ptpd -g -i ens33
注:步骤4和5加入-C参数的话,会在前台运行,并打印输出,如在主时钟端:
例:sudo ptpd -M -C -i ens33

7. 关闭进程
测试结束时,可直接使用kill命令,结束进程中的ptpd,恢复NTP服务
sudo pkill ptpd
sudo timedatectl set-ntp true
PTP时钟同步,可以搭配不同的硬件有多种Master、Slave组合,如下表所示
| Master | Slave |
|---|---|
| 电脑主机 | 工业相机、硬件同步设备、电脑主机 |
| 工业相机 | 电脑主机、工业相机、硬件同步设备 |
| 硬件同步设备(GPS等) | 工业相机、电脑主机、硬件同步设备 |
本文主要基于PTPD介绍表格中第一种情况,即Ubuntu主机,作为Master、工业相机作为Slave模式
测试方法:
sudo ptpd -M -i ens33


| 时间戳类型 | 时间戳ID | 时间戳 | 时间差us(100MHz) | ns | 说明 |
|---|---|---|---|---|---|
| Event | Line0RisingEdge | 1716878696804977842 | / | / | / |
| Event | FrameStart | 1716878696804990022 | 12.18 | 12180 | FrameStart- Line0RisingEdge |
| Image | nDevTimeStamp | 1716878696804990082 | 0.06 | 60 | nDevTimeStamp- FrameStart |
| Event | ExposureStart | 1716878696804991182 | 1.1 | 1100 | ExposureStart- nDevTimeStamp |
| Event | ExposureEnd | 1716878696810658622 | 5667.44 | 5667440 | ExposureEnd- ExposureStart |
| Host | nHostTimeStamp | 1716878696811 | 341.378 | 341378 | nHostTimeStamp- ExposureEnd |
| Event | FrameEnd | 1716878696836186552 | 25186.552 | 25186552 | FrameEnd- nHostTimeStamp |
HostTimeStamp与相机的各种时间戳时间单位基本一致
关闭ptpd进程服务,相机断电重新测试
sudo pkill ptpd

| 时间戳类型 | 时间戳ID | 时间戳 | 时间差us(100MHz) | ns | 说明 |
|---|---|---|---|---|---|
| Event | Line0RisingEdge | 32279293504138 | / | / | / |
| Event | FrameStart | 32279293509238 | 5.1 | 5100 | FrameStart- Line0RisingEdge |
| Image | nDevTimeStamp | 32279293509298 | 0.06 | 60 | nDevTimeStamp- FrameStart |
| Event | ExposureStart | 32279293510398 | 1.1 | 1100 | ExposureStart- nDevTimeStamp |
| Event | ExposureEnd | 32279299177970 | 5667.572 | 5667572 | ExposureEnd- ExposureStart |
| Host | nHostTimeStamp | 1716872579325 | / | / | / |
| Event | FrameEnd | 32279324706381 | 25528.41 | 25528411 | FrameEnd- ExposureEnd |
关闭ptpd服务后,主机时间nHostTimeStamp不与相机时间同步
其他: