Raspberry Pi与GPS构建NTP服务器

  • A ntp服务器简介
  • B GPS模块
    • Ba TTL和RS232电平
    • Bb GPS模块测试
    • Bc 模块配置
  • C Raspberry-Pi
    • Ca 连线
    • Cb 准备Raspberry-pi的串口
      • Cba 关闭串口登陆功能
      • Cbb 关闭蓝牙功能
      • Cbc 测试串口
      • Cbd 测试pps
  • D 配置ntp服务
    • Da ntpd
      • Daa 编译安装ntpd
      • Dab 配置ntpd从串口连接本地串口
      • Dac 测试
    • Db chrony
      • Dba 安装gpsd
      • Dbb 安装chrony
  • E 使用NTP服务
    • Ea 配置主NTP
    • Eb 配置从NTP

A) ntp服务器简介

参考

  • 百度百科
  • http://chuansong.me/n/1453137833223(https://help.ubuntu.com/lts/serverguide/NTP.html)
  • http://cn.linux.vbird.org/linux_server/0440ntp.php
  • http://www.ntp.org/ntpfaq/NTP-s-config-adv.htm#S-CONFIG-ADV-PPS

NTP服务器【Network Time Protocol(NTP)】是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按NTP服务器的等级传播。按照离外部UTC源的远近把所有服务器归入不同的Stratum(层)中。

NTP提供准确时间,首先要有准确的时间来源,这一时间应该是国际标准时间UTC。 NTP获得UTC的时间来源可以是原子钟、天文台、卫星,也可以从Internet上获取。这样就有了准确而可靠的时间源。时间按NTP服务器的等级传播。按照离外部UTC 源的远近将所有服务器归入不同的Stratum(层)中。Stratum-1在顶层,有外部UTC接入,而Stratum-2则从Stratum-1获取时间,Stratum-3从Stratum-2获取时间,以此类推,但Stratum层的总数限制在15以内。所有这些服务器在逻辑上形成阶梯式的架构相互连接,而Stratum-1的时间服务器是整个系统的基础。

B) GPS模块

目前在淘宝买高端版的UBLOX gps模块并不方便,原因在于国内为了扶持北斗系统采取了一定的禁售。目前gps比北斗的定位仍然比较优秀,而授时服务基本没有差距。
根据我们的需求,我们只需购买对应的国产的双模接受模块(GPS+北斗)
我们选择了淘宝上的UM220-III型芯片,模块照片如图:
Raspberry Pi与GPS构建NTP服务器_第1张图片
我们使用上方的串口1进行设置和测试,相应的引脚分别是:

vcc_3, RXD1, TXD1, GND

带有短接帽的引脚连接的是pps信号和一颗led,在短接帽连接下,pps信号会驱动led一闪一闪。由于我们要使用pps,拔出短接帽,使用右边的pps信号来源口。

B.a) TTL和RS232电平

参考TTL电平与RS232电平的区别

电平名称 输出L 输出H 输入L 输入H
TTL <0.8V >2.4V <1.2V >2.0V
RS232 +3~+15V -3~-15V +3~+15V -3~-15V
CMOS <0.1*Vcc >0.9*Vcc <0.3*Vcc >0.7*Vcc

B.b) GPS模块测试

按照淘宝说明在windows下连接测试可用

B.c) 模块配置

默认的波特率是9600, 主要完成3方面的配置:

  • 关闭北斗频点,只使用GPS(由于后面的ntpd只识别GPS的NMEA语句,不支持扩展的北斗NMEA语句,故我们只使用GPS)
  • 设置授时脉冲,周期为1000ms,脉冲长为100ms,脉冲上升沿与整秒对齐。只在授时有效时才输出授时脉冲(这一点暂时保留争议,看后续的使用)
  • 设置动态模型为车载模式

C) Raspberry-Pi

参考:
https://www.raspberrypi.org/documentation/usage/gpio/README.md

使用的是Raspberry-Pi 3 model B。

其GPIO接口定义如下:
Raspberry Pi与GPS构建NTP服务器_第2张图片
我们将要使用其中的串口15作为gps的NMEA语句接收端口,GPIO 18作为pps的接收端口。

raspberry pi的系统我们使用官方推荐raspbian,安装参考官方的安装说明

C.a) 连线

raspberry pi gps model
3.3v vcc_3
Ground GND
GPIO 15 TXD1
GPIO 18 pps

C.b) 准备Raspberry-pi的串口

参考:
https://www.modmypi.com/blog/raspberry-pi-gps-hat-and-python
http://blog.csdn.net/qishi_blog/article/details/52843696
http://wengkai.github.io/ntpserver/ntpserver.html
http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html

C.b.a) 关闭串口登陆功能

关闭树莓派的串口登陆功能,使得树莓派可以使用GPIO 14和GPIO15作为串口通信。
进入系统后,进行配置:

sudo raspi-config

找到Serial这一项,disable之
Raspberry Pi与GPS构建NTP服务器_第3张图片

C.b.b) 关闭蓝牙功能

需要注意的是Raspberry-Pi 3相比于1和2在使用串口的时候会有问题

原因是树莓派CPU内部有两个串口,一个是硬件串口(官方称为PL011 UART),一个是迷你串口(官方成为mini-uart)。在树莓派2B/B+这些老版树莓派上,官方设计时都是将“硬件串口”分配给GPIO中的UART(GPIO14&GPIO15),因此可以独立调整串口的速率和模式。而树莓派3的设计上,官方在设计时将硬件串口分配给了新增的蓝牙模块上,而将一个没有时钟源,必须由内核提供时钟参考源的“迷你串口”分配给了GPIO的串口,这样以来由于内核的频率本身是变化的,就会导致“迷你串口”的速率不稳定,这样就出现了无法正常使用的情况。

操作如下:

step 1
/boot/config.txt修改

enable_uart=0

enable_uart=1

然后添加

dtoverlay=pi3-miniuart-bt
force_turbo=1

step 2
修改/boot/cmdline.txt
删除所有的console=xxx的语句,例如将

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

改成

dwc_otg.lpm_enable=0 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

step 3
修改蓝牙服务,编辑/lib/systemd/system/hciuart.service
修改[Unit]中的After字段,由

After=dev-serial1.device

改至

After=dev-ttyS0.device

修改[Service]中的ExecStart字段,由

ExecStart=xxx(根据具体表示)

改成

ExecStart=/usr/lib/hciattach /dev/ttyS0 bcm43xx 460800 noflow -

注:其中的bcm43xx真的是xx哦

重启Raspberry Pi, 串口接下来可以用作通信

C.b.c) 测试串口

试试

cat /dev/ttyAMA0

能不能读到类似

$GPGSA,A,3,02,04,12,25,24,05,10,,,,,,02.4,01.1,02.1*07 
$GPGLL,2834.2631,N,07720.5426,E,102954.00,A,A*6E 
$GPGSV,3,1,07,02,71,345,50,04,40,038,48,12,62,315,47,25,20,321,45*7F 
$GPGSV,3,2,07,05,41,167,23,10,48,086,23,24,24,236,30,,,,*48 
$GPGSV,3,3,07,,,,,,,,,,,,,,,,*7E 

的数据,如果ok,那就证明串口正常,如果不行,用minicom或者stty设置端口的波特率为9600 8n1之后再试

你也可以使用

gpsmon  /dev/ttyAMA0

来读取串口的gps数据,你将会看到类似如下信息

C.b.d) 测试pps

step 1
安装工具

sudo apt install pps-tools

step 2
修改/boot/cmdline.txt,添加

dtoverlay=pps-gpio,gpiopin=18

step 3
修改/etc/modules,添加

pps-gpio

step 4
重启树莓派,
使用命令lsmod | grep pps
应该能看到下面类似消息

pps_gpio          2555   0
pps_core          7092   1  pps_gpio

使用命令dmesg | grep pps
会看到
Raspberry Pi与GPS构建NTP服务器_第4张图片

step 5
这个时候使用命令sudo ppstest /dev/pps0将会看到类似下面的输出

trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1421066632.974111422, sequence: 1698 - clear  0.000000000, sequence: 0
source 0 - assert 1421066633.974045488, sequence: 1699 - clear  0.000000000, sequence: 0

每一秒输出一条,如果发现输出间隔不是1s,可能是连线错误或者gps模块未设置导致。

D) 配置ntp服务

常见的ntp server的实现有ntpd和chrony。从RHEL 7开始默认的系统ntp服务已经由ntpd更换成了chrony。
常见ntp server的区别可以参考:
CentOS / RHEL 7 : Chrony V/s NTP (Differences Between ntpd and chronyd)
Comparison of NTP implementations

总结来说chrony的优点有:

  • 同步更快,只需要几分钟收敛到最小误差,而ntpd可能需要几个小时
  • 对变频环境有优化
  • 对于断线和延迟有更好的优化

所以,对于移动和不稳定的网络结构,建议使用chrony,对于稳定的网络结构,ntpd不失为可靠的选择,而且ntp还有认证的安全功能。

下面我们将对两种方案在Raspberry pi上的部署进行说明

D.a) ntpd

参考:
http://blog.csdn.net/qishi_blog/article/details/52843696
http://wengkai.github.io/ntpserver/ntpserver.html

D.a.a) 编译安装ntpd

系统apt安装的nptd是一个裁剪版,不支持PPS,所以得自己下载源码编译一个。
如果系统里头已经安装了ntpd,先卸载

sudo service ntp stop
sudo apt remove ntp

先安装libcap-dev:

sudo apt install libcap-dev

然后从: http://archive.ntp.org/ntp4/ 找到最新的ntpd版本,下载在rpi上:
比如

wget http://archive.ntp.org/ntp4/ntp-4.2.8p1.tar.gz

解压、配置、编译:

tar xzf ntp-4.2.8p1.tar.gz
cd ntp-4.2.8p1/
./configure --enable-linuxcaps

然后make,安装:

make
sudo make install 
sudo cp /usr/local/bin/ntp* /usr/bin/
sudo cp /usr/local/sbin/ntp* /usr/sbin/

重新启动ntpd

sudo service ntp start

D.a.b) 配置ntpd从串口连接本地串口

编辑/etc/ntp.conf

# NMEA refclock driver directly from serial port
server 127.127.20.0 mode 16 minpoll 4 iburst prefer true
fudge 127.127.20.0 flag1 1 flag2 0 flag3 0 flag4 0 time1 0.1 refid GPS
# ATOM PPS driver directly from interrupt through /dev/pps1
server 127.127.22.0 minpoll 4 maxpoll 4 iburst true
fudge 127.127.22.0 flag2 0 flag3 0 flag4 1 time1 0.1 refid PPS

server, fudge的配置说明请参看man ntp.conf。这里的127.127.t.u并不是真实的ip地址,而是Reference clock,根据t来指定实际类型,根据u来指定设备。t对应的实际设备需要看文档,在源代码目录ntp/html/drivers/driverxx.html中也有。

配置完成以后重启ntpd

sudo service ntp restart

D.a.c) 测试

运行

ntpq -crv -p

运行结果如下
Raspberry Pi与GPS构建NTP服务器_第5张图片
每个字段的参考可见https://linux.cn/article-4664-1.html

Raspberry Pi与GPS构建NTP服务器_第6张图片

Raspberry Pi与GPS构建NTP服务器_第7张图片

至此,ntp服务已经在树莓派上起来了。

D.b) chrony

官网上有相关的说明。

ntp支持多种设备驱动,而chrony除了对pps的支持,对于GPS的串口连接的NMEA语句没有支持,只有通过gpsd的共享内存的方式来获取。

开始之前,先运行rcconf来将ntpd的开机启动关闭吧(如果没有rcconf可以通过apt安装哈)

D.b.a) 安装gpsd

运行命令:

sudo apt install gpsd gpsd-clients python-gps

修改/etc/default/gpsd文件,修改

DEVICES="/dev/ttyAMA0"
GPSD_OPTIONS="-n -G"

-n = don’t wait for client connects to poll GPS
-G = make gpsd listen on INADDR_ANY

接下来配置开机启动,由于这个版本的raspbian使用systemd作为系统管理,我们可以通过systemctl工具来配置开机启动。
首先,修改/lib/systemd/system/gpsd.service文件,在[install]后面添加

WantedBy=multi-user.target

修改[Unit]中的After=chrony.serviceBefore=chrony.service
ps: 其他项的设置可能也要实际的情况修改
然后运行

sudo systemctl enable gpsd

之后重启即可

接下来通过运行

cgps -s

来查看gpsd的数据,你在开阔的地方,你将会看到类似下面的输出
Raspberry Pi与GPS构建NTP服务器_第8张图片

D.b.b) 安装chrony

raspbian源上的chrony貌似挺新的,直接通过apt安装

sudo apt install chrony

配置文件是/etc/chrony.conf或是/etc/chrony/chrony.conf
确保有以下内容(如果没有则添加)

leapsectz right/UTC
makestep 1.0 -1
rtcsync

参考chrony.conf
其中 :
makestep 1.0 -1表示超过1秒立刻修正,不回归
rtcsync每11分钟自动矫正系统rtc时钟

参考 GPSD说明
chrony.conf文件中继续添加pps和gpsd的连接配置,

refclock PPS /dev/pps0 lock GPSD prefer refid PPS
refclock SHM 0 offset 0.0 delay 0.2 refid GPSD

ps:注意这里的delay的大小,delay代表信号源往返信号的时间预估,其值的一半会作为信号的误差,且不同的信号源的范围需要overlay。比如pps的delay和offset都很小,接近0,而gpsd的offset如果在100ms左右,这个时候就需要设置delay大于0.2(两倍100ms,我会设置0.3)。否则的话,通过`chronyc sources -v`会看到型号元前面是time may be error的标志

配置完成后重启服务

sudo service chrony restart

可以通过下面两个命令来查看连接状态

数据统计:chronyc sources -v
源状态: chronyc sourcestats -v

如果想要连续观察,可以借助linux的watch命令,即

watch -n1 chronyc sources -v
watch -n1 chronyc sourcestats -v

E) 使用NTP服务

有很多种方法。我们下面讲下利用chrony的自动更新功能来更新本地时钟。

E.a) 配置主NTP

我们首先讲树莓派和需要连接的主机放在同一个局域网里头,这里假设是192.168.2.xx网段。树莓派需要配置静态ip,这里假设是192.168.2.100
在树莓派的chrony.conf中添加一行:

allow

这将允许所有的ipv4和ipv6的地址的客户端的访问.
同时确定下没有拦截树莓派的ntp服务端口123

E.b) 配置从NTP

step 1
在所有的需要同步的主机安装chrony

step 2
所有从主机的/etc/hosts文件添加

192.168.2.100 rpi

step 3
在主机的chrony.conf中添加

server rpi minpoll 2 maxpoll 4 polltarget 30 maxdelaydevratio 2 iburst

leapsectz right/UTC
makestep 1.0 -1
rtconutc
rtcsync

具体参数说明可以参考chrony.conf
需要说明的是:

  • maxdelaydevratio 一种类似测量标准差般的存在,越大对错误数据的容忍度越高,错误数据的扰动越大。默认是10
  • rtconutc 表明更新RTC时钟到UTC时间
  • rtcsync 在linux是每11分钟更新,macos是每60分钟更新,其余系统上无效

重启每台主机的chrony服务即完成基于树莓派的ntp服务对本地时钟的校准

你可能感兴趣的:(自动驾驶,智能硬件相关)