Raspberry Pi与GPS构建NTP服务器

来源:互联网 发布:掌趣上游网络 编辑:程序博客网 时间:2024/06/04 19:57

  • 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型芯片,模块照片如图:
UM220-III
我们使用上方的串口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接口定义如下:
这里写图片描述
我们将要使用其中的串口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之
这里写图片描述

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-btforce_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   0pps_core          7092   1  pps_gpio

使用命令dmesg | grep pps
会看到
这里写图片描述

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: 0source 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 stopsudo 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.gzcd ntp-4.2.8p1/./configure --enable-linuxcaps

然后make,安装:

makesudo 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 portserver 127.127.20.0 mode 16 minpoll 4 iburst prefer truefudge 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/pps1server 127.127.22.0 minpoll 4 maxpoll 4 iburst truefudge 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

运行结果如下
这里写图片描述
每个字段的参考可见https://linux.cn/article-4664-1.html

这里写图片描述

这里写图片描述

至此,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 for ntp and -G to allow gpsd listen to all address, allowing gpsd client to connect from any reachable network)
然后运行下面命令,开机自启动(dpkg-reconfigure的运行效果在我这边有点奇怪,没有提示配置选择)

sudo dpkg-reconfigure gpsd

接下来通过运行

cgps -s

来查看gpsd的数据,你在开阔的地方,你将会看到类似下面的输出
这里写图片描述

D.b.b) 安装chrony

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

sudo apt install chrony

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

leapsectz right/UTCmakestep 1.0 3rtcsync

参考chrony.conf
其中 :
makestep 1.0 3表示前三次矫正如果与当前系统时差超过1.0s,则不矫正
rtcsync每11分钟自动矫正系统rtc时钟

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

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

ps:按照说明delay增大能选择更加优先,和delay越大距离越远矛盾

配置完成后重启服务

sudo service chrony restart

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

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

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

watch -n1 chronyc sources -vwatch -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 2makestep 1.0 3rtconutcrtcsync

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

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

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

原创粉丝点击