参考
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的时间服务器是整个系统的基础。
目前在淘宝买高端版的UBLOX gps模块并不方便,原因在于国内为了扶持北斗系统采取了一定的禁售。目前gps比北斗的定位仍然比较优秀,而授时服务基本没有差距。
根据我们的需求,我们只需购买对应的国产的双模接受模块(GPS+北斗)
我们选择了淘宝上的UM220-III型芯片,模块照片如图:
我们使用上方的串口1进行设置和测试,相应的引脚分别是:
vcc_3, RXD1, TXD1, GND
带有短接帽的引脚连接的是pps信号和一颗led,在短接帽连接下,pps信号会驱动led一闪一闪。由于我们要使用pps,拔出短接帽,使用右边的pps信号来源口。
参考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 |
按照淘宝说明在windows下连接测试可用
默认的波特率是9600, 主要完成3方面的配置:
参考:
https://www.raspberrypi.org/documentation/usage/gpio/README.md
使用的是Raspberry-Pi 3 model B。
其GPIO接口定义如下:
我们将要使用其中的串口15作为gps的NMEA语句接收端口,GPIO 18作为pps的接收端口。
raspberry pi的系统我们使用官方推荐raspbian,安装参考官方的安装说明
raspberry pi | gps model |
---|---|
3.3v | vcc_3 |
Ground | GND |
GPIO 15 | TXD1 |
GPIO 18 | pps |
参考:
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
关闭树莓派的串口登陆功能,使得树莓派可以使用GPIO 14和GPIO15作为串口通信。
进入系统后,进行配置:
sudo raspi-config
需要注意的是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, 串口接下来可以用作通信
试试
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数据,你将会看到类似如下信息
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
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模块未设置导致。
常见的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的优点有:
所以,对于移动和不稳定的网络结构,建议使用chrony,对于稳定的网络结构,ntpd不失为可靠的选择,而且ntp还有认证的安全功能。
下面我们将对两种方案在Raspberry pi上的部署进行说明
参考:
http://blog.csdn.net/qishi_blog/article/details/52843696
http://wengkai.github.io/ntpserver/ntpserver.html
系统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
编辑/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
运行
ntpq -crv -p
运行结果如下
每个字段的参考可见https://linux.cn/article-4664-1.html
至此,ntp服务已经在树莓派上起来了。
官网上有相关的说明。
ntp支持多种设备驱动,而chrony除了对pps的支持,对于GPS的串口连接的NMEA语句没有支持,只有通过gpsd的共享内存的方式来获取。
开始之前,先运行rcconf
来将ntpd的开机启动关闭吧(如果没有rcconf可以通过apt安装哈)
运行命令:
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.service
至Before=chrony.service
ps: 其他项的设置可能也要实际的情况修改
然后运行
sudo systemctl enable gpsd
之后重启即可
接下来通过运行
cgps -s
来查看gpsd的数据,你在开阔的地方,你将会看到类似下面的输出
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
有很多种方法。我们下面讲下利用chrony的自动更新功能来更新本地时钟。
我们首先讲树莓派和需要连接的主机放在同一个局域网里头,这里假设是192.168.2.xx
网段。树莓派需要配置静态ip,这里假设是192.168.2.100
在树莓派的chrony.conf
中添加一行:
allow
这将允许所有的ipv4和ipv6的地址的客户端的访问.
同时确定下没有拦截树莓派的ntp服务端口123
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
需要说明的是:
重启每台主机的chrony服务即完成基于树莓派的ntp服务对本地时钟的校准