USB转串口 模拟 PPS+GPRMC 进行授时

把 PC的系统时间 通过USB转串口发出来 来模拟 PPS+GPRMC 授时, 这大冷天的, 用来在室内测试MCU或者SOC的授时功能, 传感器的授时与线束检测, 测试干扰等等, 还是比较合适的.

如下图, 左边为 USB转9针RS232串口, 右边为 USB转TTL串口

在这里插入图片描述

原理:

  • PPS 有 3V3 / 5V / 12V 等规格, 这里用串口芯片的RTS引脚来模拟PPS(DTR引脚也可以), 左边RS232的DB9口中虽然也有RTS引脚, 但是实测是±9V, 所以用右边的USB转TTL芯片的3.3V的RTS来代替
  • GPRMC 是RS232 电平, 直接用左边DB9中的PIN3–TXD引脚发出来就可以了
  • 图左都是RS232电平, 图右都是TTL电平, 所以才用了两个来混搭, 如果自己打板子用一个USB转串口芯片+RS232芯片就够了

Python3 的脚本1.py如下(Win下为 COM*, Ubuntu下为/dev/ttyUSB*, 需要先安装pyserial和nmeasim)

#!/usr/bin/python3

# python3 -m pip install pyserial
# python3 -m pip install nmeasim

from nmeasim.models import GpsReceiver
from threading import Timer
from datetime import datetime
import serial

ttl_ser   = serial.Serial('COM7')	# 右边板子的串口号, 用到RTS或者DTR引脚, 模拟PPS
rs232_ser = serial.Serial(port="COM14", baudrate=9600)	# 左边板子的串口号, 用到TXD, 9600波特率, 模拟GPRMC

gps = GpsReceiver(output=('RMC',))	# 单GPRMC输出
# https://gitlab.com/nmeasim/nmeasim/-/blob/master/nmeasim/models.py
# output=("GGA", "GLL", "GSA", "GSV", "RMC", "VTG", "ZDA")

def pps_high():
    ttl_ser.setRTS(False)	# -9V, 3.3V, PPS输出高, 如果用DTR引脚就setDTR

def pps_low():
    ttl_ser.setRTS(True)	# 9V, 0V, PPS输出低

def pps_init():
    # print('pps_init')
    pps_low()	# 初始低电平

def gprmc_out():
    gps.date_time = datetime.now()	# 获取电脑的系统时间

    gps.__lat_sign = 'N'	# GPRMC中的一些信息, 只要时间的话下面这些参数可以不用设置
    gps.lat = 39.1234
    gps.__lon_sign  = 'N'
    gps.lon = 116.5678
    gps.__mag_sign = 'E'
    gps.mag_var = 4.1
    gps.kph = 1.0
    gps.heading = 1.0

    rs232_ser.write(gps.get_output()[0].encode('utf-8') + b'\r\n')	# 发出GPRMC信息, 结尾加上\r\n
    # print(gps.get_output()[0].encode('utf-8'))
    # ts = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
    # print('gprmc_out :', ts, ts[-3:])
    # print()

def pps_out():
    pps_high()
    ts = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]	# 精确到ms
    print(ts)
    Timer(1 - int(ts[-3:])/1000, pps_out).start()	# 每次都进行补偿
    Timer(0.02, pps_init).start()   # PPS高电平持续时间20ms, 示波器实测约32ms
    Timer(0.10, gprmc_out).start()  # PPS上升沿后100ms, 发出GPRMC

pps_init()
pps_out()

运行python3 1.py, 环境为 Win10, i7-8086K, 测试时间为 2021年12月30日, 北京时间减去8小时就是下面GPRMC中的时间

在这里插入图片描述

换算成十六进制, 结尾一定要有0x0D, 0x0A, 如果没有, 以Velodyne的激光雷达VLP-16为例, 即便网页可能有之前的GPS Position信息, 但是Wireshark里面抓到的512字节的数据包只会显示PPS Locked, 却没有GPRMC信息

在这里插入图片描述

左边为PPS发出的时间戳, 加上8小时刚好是北京时间, 精度在4ms以内, 通用测试还是可以的

PPS波形(CP2104芯片, PPS高电平持续时间, 示波器实测脉宽比设置的20ms多出12ms, 不过PPS用的上升沿, 这个应该影响不大)

在这里插入图片描述

两个脉冲上升沿的间隔 1s

在这里插入图片描述

上升沿有点惨不忍睹 快1ms了, 这带来的PPS误差又多了1ms, 把9600bps改成115200bps也没有改善, 换成CH340或者空载差别也不大, 如果用MCU来模拟可能会好一点, 或者加个74芯片

在这里插入图片描述

如果只是单纯授时, 脚本中不要定位信息也是可以的, 如下

def gprmc_out():
    gps.date_time = datetime.now()
    rs232_ser.write(gps.get_output()[0].encode('utf-8') + b'\r\n')
    
# $GPRMC,024941.113,A,0000.000,N,00000.000,E,0.0,0.0,301221,,,A*64
# $GPRMC,024942.119,A,0000.000,N,00000.000,E,0.0,0.0,301221,,,A*6D
# $GPRMC,024943.114,A,0000.000,N,00000.000,E,0.0,0.0,301221,,,A*61
# $GPRMC,024944.113,A,0000.000,N,00000.000,E,0.0,0.0,301221,,,A*61
# $GPRMC,024945.119,A,0000.000,N,00000.000,E,0.0,0.0,301221,,,A*6A

用VLP-16做个测试, 首先看下VLP-16用户手册中时间同步的要求:

  • PPS + 每秒一次的NMEA V2.3 GPRMC 或 GPGGA
  • PPS是固定的, 后面的NMEA 可以通过 串口 或者 以太网口 发送, 以太网口需要通过 TCP/UDP/广播 发送 NMEA 消息 到 10110 端口, 这里就不考虑了, 以下GPRMC只指通过串口 RS232电平 发出来的信息
  • PPS和GPRMC在高电平要能提供至少2mA的电流, 可能是为了抗干扰, 加了类似光耦的装置? 想要一根线挂很多激光雷达可能不太行
  • PPS是TTL电平, 3.3V/5V, 脉宽10us-200ms, 下面程序里设置成20ms
  • GPRMC是RS232电平, 9600bps, 格式可以是 HHMMSS, HHMMSS.s, HHMMSS.ss, 或 HHMMSS.sss(上面程序用的这个), 结尾要有0x0D, 0x0A, 也就是\r\n 或者叫 <CR><LF>, 时序要求见下图, 下面程序里设置成PPS上升沿100ms后发出

在这里插入图片描述

一开始网页界面重叠, 还以为是雷达坏了

在这里插入图片描述

其实是浏览器的字体设置成特大了, 改成推荐的中就正常了(相信有遇到同样情况的)

在这里插入图片描述

没有 PPS+GPRMC 授时的时候显示

在这里插入图片描述

发出PPS+GPRMC后, 网页显示锁定

在这里插入图片描述

Wireshark也能抓到GPRMC的包

在这里插入图片描述

00f4位置的02代表PPS Locked, 测试完成.

在这里插入图片描述

欢迎扫描二维码关注本人微信公众号, 及时获取最新文章:
在这里插入图片描述

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值