树莓派:光阴的故事

做者:Vamei 出处:http://www.cnblogs.com/vamei 严禁任何形式转载。html

 

对于电子设备来讲,时间都是基础性的功能,也很容易被人忽视。上世纪的“千年虫”问题,就是时间方面设计缺陷形成的。对于网络链接的多设备来讲,保持时间同步又是一个新的问题。对于树莓派的众多应用情景来讲,时间的准确性都相当重要。python

 

NTP服务

树莓派中内置了NTP服务,因此连上网以后就能够自动调整时间。NTP是网络时间协议(Network Time Protocol)的简称,主要用于网络时间的同步。NTP协议早在80年代就已经诞生,至今仍是互联网的基础性协议之一。NTP通讯分为服务器和客户端两方。客户端发出的数据包中,包含有发出时客户端的时间。服务器收到数据包并回复。回复的数据包中,附加了服务器收到和发出数据包的时间。客户端收到回复后,就能够得到网络延迟时间,以及本身和服务器的时间差。客户端据此调整本身的时钟,就能够与服务器时间保持同步。bash

NTU客户与服务器服务器

 

你能够经过下面命令来查询当前使用的NTP服务器:网络

sudo ntpq -pn

 命令返回:ide

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 203.135.184.123 .GPS.            1 u  322   64   20  365.136   -7.571  15.792
 223.112.179.133 .INIT.          16 u    - 1024    0    0.000    0.000   0.000
*202.112.29.82   202.118.1.46     2 u  122   64  276   53.148    0.766   0.868

行首加*号的是当前服务器。此外,还列出了网络延迟时间(delay)、与服务器时间差(offset)等关键的NTP时间数据。单位是milliseconds。工具

 

若是NTP服务出现问题,形成树莓派时间错误,能够强制要求NTP对表: ui

sudo service ntp stop
sudo ntpd -gq
sudo service ntp start

上面的第一句和第三句分别用于中止和启动NTP服务。 this

 

不使用NTP,你也能够手动调整系统时间: spa

sudo date -s "1 Jan 2017 00:00:00"

即把系统时间调整为2017年1月1日00:00:00。

  

而后用date命令来显示系统当前时间:

date

 

时区设置

地球自西向东转到。因此,全球不一样经度地点的日出日落以及正午的时间不一样。人们又习惯于用一样的12点来表明正午,这意味着不一样经度的人要用不同的表。但是,若是人每时每刻都要根据经度调表,就会很是麻烦。所以,地球以15度的经度来划分时区,一个时区内的表用统一的时间,向东跨过一个时区,就须要把表调快1小时。固然,时区的划分不是严格的按照15度。好比说,一些地跨多个时区的国家有可能用统一一个时区,例如中国。下面是地球上时区分布的地图。

 

对于不一样地区的用户来讲,每每须要把树莓派调整成当地的时区。你能够用raspi-config进入到树莓派的设置页面,在"4 Localisation Options"->"I2 Change Timezone"中修改时区。

固然,你也能够用下面的命令手动修改:

sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

注意到,/user/share/zoneinfo中有多个以各大洲名字命令的文件夹,里面的文件以该州的主要城市命名。把对应城市的文件复制到/etc/localtime,就能够把系统的时区设成该城市所用的时区。这里我把时区修改成"Shanghai",也就是上海。修改以后,用date命令查看时间,能够看到时区简写变成CST,也就是“上海时间”的缩写:

Tue  3 Jan 20:42:24 CST 2017

 

用date命令查看UTC时间:

date -u

显示的时间正好相差8个小时:

Tue  3 Jan 12:42:24 UTC 2017

 

实时时钟

大多数电脑在主板上包含了一个实时时钟(RTC,Real Time Clock)。实时时钟是一个有电源的表,能在电脑断电时继续计时。所以,电脑断电后一天再开机,你会发现电脑的时钟也往前走了一天。但树莓派并不包含一个实时时钟。所以,若是树莓派断电一天再开机,在NTP服务校订时间以前,你会发现树莓派的时间还停留在一天前。为了克服这一问题,你能够给树莓派附加一个实时时钟,好比PiFace专门为树莓派设计的实时时钟。

这个实时时钟设计成一个使用纽扣电池的电路板。把PiFace电路板的孔对准树莓派的GPIO针脚插入,就可使用了。插入位置以下图所示。插入正确的状况下,电池正好在树莓派CPU的上方。网上也有人诟病这一设计,认为电池的发热会影响树莓派CPU的散热。不过我在使用中并无太大问题。

为了使用这款实时时钟,我还须要进行一些设置。首先,这块电路板是经过I2C接口与树莓派通讯的,因此要在raspi-config的页面中打开I2C接口。而后,安装所需的工具包: 

sudo apt-get install i2c-tools
sudo apt-get install python-smbus

 

接下来,赋予用户pi使用I2C接口的权限:

sudo usermod -aG i2c pi

 

打开文件/etc/modules,这里面列出了系统能够加载的模块。检查是否有以下两行。若是没有的话请添加:

i2c-dev
i2c-bcm2708

 

下面一段程序修改自官网程序,用来让树莓派在开机时自动加载实时时钟。把下面程序保存为rtc.bash,并运行:

#!/bin/bash #======================================================================= # NAME: set_revision_var # DESCRIPTION: Stores the revision number of this Raspberry Pi into # $RPI_REVISION #======================================================================= set_revision_var() { revision=$(grep "Revision" /proc/cpuinfo | sed -e "s/Revision\t: //") RPI2_REVISION=$((16#a01041)) RPI3_REVISION=$((16#a02082)) if [ "$((16#$revision))" -ge "$RPI3_REVISION" ]; then RPI_REVISION="3"
    elif [ "$((16#$revision))" -ge "$RPI2_REVISION" ]; then RPI_REVISION="2"
    else RPI_REVISION="1"
    fi } #======================================================================= # NAME: start_on_boot # DESCRIPTION: Load the I2C modules and send magic number to RTC, on boot. #======================================================================= start_on_boot() { echo "[info]Create a new pifacertc init script to load time from PiFace RTC."
    echo "[info]Adding /etc/init.d/pifacertc ."

    if [[ $RPI_REVISION == "3" ]]; then i=1  # i2c-1
    elif [[ $RPI_REVISION == "2" ]]; then i=1  # i2c-1
    else i=0  # i2c-0
    fi

    cat > /etc/init.d/pifacertc  << EOF #!/bin/sh ### BEGIN INIT INFO # Provides: pifacertc # Required-Start:    udev mountkernfs \$remote_fs raspi-config # Required-Stop: # Default-Start: S # Default-Stop: # Short-Description: Add the PiFace RTC # Description: Add the PiFace RTC ### END INIT INFO . /lib/lsb/init-functions case "\$1" in start) log_success_msg "Probe the i2c-dev"
    modprobe i2c-dev # Calibrate the clock (default: 0x47). See datasheet for MCP7940N log_success_msg "Calibrate the clock" i2cset -y $i 0x6f 0x08 0x47 log_success_msg "Probe the mcp7941x driver"
    modprobe i2c:mcp7941x log_success_msg "Add the mcp7941x device in the sys filesystem" # https://www.kernel.org/doc/Documentation/i2c/instantiating-devices
    echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-$i/device/new_device log_success_msg "Synchronise the system clock and hardware RTC" hwclock --hctosys ;; stop) ;; restart) ;; force-reload) ;; *) echo "Usage: \$0 start" >&2 exit 3 ;; esac EOF chmod +x /etc/init.d/pifacertc echo "[info]Install the pifacertc init script" update-rc.d pifacertc defaults } set_revision_var && start_on_boot

 

完成后重启电脑。此时树莓派应该已经自动经过I2C接口加载了实时时钟。你能够经过下面命令来检查实时时钟是否就位:

sudo i2cdetect -y 1

若是就位,那么60开头的行会有一个"UU"的标准位。你能够经过下面的命令,读出实时时钟的时间:

sudo hwclock -r 

你能够经过下面的命令,把当前系统时间写入实时时钟:

sudo hwclock --systohc

 

有了实时时钟,你就能够在无网环境下保持时间的连续性。PiFace的产品卖得有一些贵。淘宝上还有一些便宜的实时时钟能够选购。另外,PiFace官网速度很慢。须要说明书的,能够在这里下载 

 

date用例

文章中多处使用了date命令。date是UNIX系统下经常使用的时间命令工具,能提供很是丰富的时间功能,好比以特定格式显示时间:

date +"%Y year %m month %d day"

+号后面的字符串表明了时间显示格式。%开头的标识符会用时间信息填充。%Y表明了年,%m表明了month,%d表明了日期。因此上面命令返回:

2017 year 01 month 01 day

更多的标识符能够经过man date来查询文档。

 

date不必定只显示当前时间,它还能够用来显示一个用户输入的时间:

date --date="2017/01/03 12:00:00"

这个功能看起来有些鸡肋,但实际上能够用于时间推算。好比说下面的命令就能够用于推算2016年11月12日以前1个月的时间:

date --date="2016/11/12 -1 month"

除了"-1 month",还能够是"+1 second"、"-2 day"等多种时间差,能知足各类各样的时间推算需求。

 

date的功能极为丰富,这里只列出了一些常见用例。其余使用能够参考man date的文档。

 

总结

树莓派提供了NTP服务,经过网络来校订时间。即便在断网状况下,也能够物理计时实施来校订时间。而树莓派使用的Linux系统,也提供了date这样便利的时间工具。

 

欢迎阅读“骑着企鹅采树莓”系列文章 

相关文章
相关标签/搜索