Here's my 'hack' to get the RTC to load properly at boot or use the NTP server.
First off ... I'll assume everyone has taken the 2 steps to get the module correctly loaded:
rtc-ds1307 .... added to /etc/modules
echo ds1307 0x68 > /sys/class/i2c-adapters/i2c-1/new_device .... added to /etc/rc.local
According to the Adafruit documentation this is all you need to do ... well, it isn't. By default, the Wheezy image has the the fake-hwclock enabled which can cause issues, so lets get rid of it.
Code: Select all
sudo apt-get --purge remove fake-hwclock
What we need now is a script to choose between the NTP servers time or the RTC. We're going to assume that the NTP server time is more correct than the RTC so it will take precedence if it's there. Since the NTP is automagically loaded on boot when we have internet, we'll presume that if we can see the internet then the NTP time has been loaded. If not then take the RTC time.
Code: Select all
#!/usr/bin/env python
# MUST BE RUN AS ROOT
# This script pings a website to see if we are connected to the internet
# and should work regardless of eth0 or wlan0
# -> if connected, assume that NTP set systime and update RTC
# -> if not, assume systime is incorrect and update from RTC
#
# It should be noted that if you boot up with internet connected then
# the os will automagically update systime but NOT the RTC
# hence this code will update RTC when ethernet connected
#
# NOTE: fake-hwclock may interfere if left enabled
# sudo apt-get --purge remove fake-hwclock
#
import subprocess
import os
# Any valid website will work
website_to_ping = "www.google.com"
# ping website and get reply
ping = subprocess.Popen(["ping", "-c", "1", website_to_ping], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
out, error = ping.communicate()
# We don't care what the actual reply is, only whether its a valid one or an error
# hence we check string length to see if it is a null string
#
# We also could have used if/else since there are only two possible conditions
#
if (len(out) <> 0):
#print out
print "Network available, copying systime to RTC"
os.system("hwclock -w")
if (len(error) <> 0):
#print error
print "Network NOT available, copying RTC to systime"
os.system("hwclock -s")
Running the code after the kernel is loaded works no problem, but we want it to run every time the system is booted. The problem arises in that the RTC module may not be fully functional before we run the above code. I had these issues when I tried to run it during the rcS start-up process. So where should we stick it? ... Figuratively speaking, of course.
After scouring this site, I found that you can run the code after loading the desktop. This provided the delay needed to make sure the modules were properly loaded before running. The LXDE (desktop) interface is loaded via
/etc/xdg/lxsession/LXDE/autostart
And after adding my code, it looked like this:
Code: Select all
@lxpanel --profile LXDE
@pcmanfm --desktop --profile LXDE
@xscreensaver -no-splash
sudo python /home/pi/settime.py
NOTE: Network status is NOT echoed back like it would be if run from a terminal.
In testing the system, the RTC is loaded to systime when the ethernet cable is disconnected and NTP is loaded to systime and RTC updated when ethernet is connected.
Improvements to my coding are welcomed and encouraged.
ISSUES that plagued me:
It seems that my monitor was back feeding power through the HDMI port when the RPi was turned off. The effect was that it pulled down the RTC battery voltage to ~1.7volts. This was low enough to stop the clock from running when powered down. Simple solution was to disconnect HDMI cable and everything worked fine.