Interfacing RaspberryPi with DS1307,I2C based Real Time Clock.

Introduction


RaspberryPi, the popular Open Source Hardware Board operating out of different Linux based flavors like Debian, Fedora, Archlinux ARM and Android, does indeed support a Real Time Clock to be integrated in the form of a Hardware module to it. Here, RaspberryPi Foundation gives the user, the flexibility to implement and integrate a Real time Clock, using popular Real Time Clock chips available in the market, among them the most popular ones like DS1307, DS1338, NXP PCF2127T, NXP PCF2129T, DS1302 et al.

In this, way, it really helps and allows the user to explore, learn interfacing and develop programs using I2C/SPI Protocols in a Linux based environment. RaspberryPi truly, remains true to its name as a pure Development, Open Source Board.  Using simple circuitry involving these popular RTC chip's, Vcc, Gnd and some 32.768kHz crystal, one can easily interface these chips using the I2C interfacing lines, SDA, SCL or SPI lines, MISO, MOSI, CS and Sclk.

There are very subtle differences between, the ICs that i have listed above. Unlike DS1307, which requires 5Volt, for its operation, DS1338 can operate on 3.3 Volt, using I2C Bus. DS1302 is SPI based Real Time Clock. The extra-accurate NXP PCF2127T, NXP PCF2129T, supports both SPI and I2C, and thus user can use and be happy with anyone as per their requirements. The below references can be used for further understanding:

DS1307:             http://datasheets.maximintegrated.com/en/ds/DS1307.pdf
DS1302:             http://datasheets.maximintegrated.com/en/ds/DS1302.pdf
DS1338:             http://pdf1.alldatasheet.com/datasheet-pdf/view/85349/MAXIM/DS1338.html
NXPPCF2129T:     http://www.nxp.com/products/interface_and_connectivity/real_time_clocks/rtcs_with_temp_compensation/PCF2129T.html
NXPPCF2127T: http://www.nxp.com/products/interface_and_connectivity/real_time_clocks/rtcs_with_temp_compensation/PCF2127T.html

The RTC Circuit


What i have tried with this blog is to show how,we can add a RTC, say DS1307 with RaspberryPi, register it with the Linux Kernel, and the methods involved. First, we need to put a circuit in a Breadboard using any of these RTC ICs. A breadboard, few single strand wires, DS1307 and a 32.768 kHz, crystal oscillator.
My circuit for RTC, using D1307

The above shows my circuit diagram, i have used a 9V DC Adaptor, so a Fixed Voltage Regulator, LM7806, which gave me a constant was used, which gave me 6V, output. Two diodes, IN4001, are connected in series,back to back, which give me a close of 1.2 V drop, so, that a Vcc of 5V could be fed to the DS1307 for its operation. The Crystal oscillator, 32.768kHz, is connected between 1 and 2 pins. The pin 3 of DS1307 is connected to 3.3V pin on the Expansion header of RaspberryPi. The pin 4 is pulled to Gnd. The pins 5 and 6 are SDA and SCL Lines of DS1307, which are connected to the SDA and SCL lines on RaspberryPi. Apart, from using a 9V Adaptor, one can use a 5V Battery directly, and connect it to Vcc and common the ground of the entire with the RaspberryPi Gnd. This is usually,a common mistake, we often make, while assembling a circuit, that the ground is not made common.The below Fritzing diagram shows quite an accurate 3D representation of the above implemented circuit.


Fritzing diagram of the above circuit



I have used a cool tool, Fritzing to develop the schematic of the same.Fritzing can be downloaded from below link. Its size
is close to 50 Mb.( http://fritzing.org/download/ )


Now, to begin with, we are trying to have a RTC Circuit around DS-1307, which would be powered using a 5V Battery 
at all  times, while the RaspberryPi, will be powered as per user convenience, at any Time. When, the RaspberryPi powers 
up, it should detect the DS1307 and register its module, rtc-ds1307, with the kernel, and create a Device node in the /dev 
directory, namely as 'rtc0' or 'rtc1'. Subsequently, RaspberryPi, should read the Date and Time from the EEPROM of DS1307, 
and after startup, and should show the current time. This, is the aim of this small exercise.

After, connecting the above circuit, we will check if RTC module,DS1307 is present in the kernel image or not. If, not build 
the kernel with the following changes in the config file, as given below:
#
# I2C RTC drivers
#
CONFIG_RTC_DRV_DS1307=m
CONFIG_RTC_DRV_DS1307=y

For, convenience, one can refer the following config file that i have attached in the form of .txt here
(https://drive.google.com/file/d/0B6Cu_2GN5atpMzUxOXJCSmlzOEk/edit?usp=sharing), copy, 
make the above change,and place it inside '/arch/arm/configs' directory of the Linux Kernel Source. 
After, this start the usual cross-compilation of the Kernel source, using the following steps:


#export CCPREFIX= /home/rajiv/RPI/tools-master/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
#export KERNEL_SRC= /home/rajiv/RPI/linux-rpi-3.6.y
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} distclean
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} RPI_defconfig 
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} 
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} modules_install
#make ARCH=arm CROSS_COMPILE=${CCPREFIX} install


Finally, the kernel image will be built in the following path, 'arch/arm/boot/' as 'zimage', rename it as 
'kernel.img', and copy the built Kernel image in the '/boot' partition of the RaspberryPi.  After, this 
add the below lines in '/etc/modules' file, which specifies the modules to be loaded at boot time:

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

i2c-dev
i2c-bcm2708
rtc-ds1307
snd-bcm2835

Now, that, RTC, DS1307 Module is present in the Linux Kernel,the next step would be to install 
i2c-tools which will help us detect if any I2C capable device is using the I2C Bus of RaspberryPi and 
the corresponding device address, using i2cdetect.The sources for i2c-tools can be downloaded from:
http://ftp.acc.umu.se/debian/pool/main/i/i2c-tools/

Download 'i2c-tools_3.1.0.orig.tar.bz2', and copy it in the SD Card of your RaspberryPi, in some 
location, say. '/home/pi'. After, booting up RaspberryPi, go to the location, '/home/pi', and extract the 
source for i2c-tools.
#tar -xvzf  i2c-tools_3.1.0.orig.tar.bz2
After, extracting the source, a folder by 'i2c-tools_3.1.0' will be created. Build the i2c-tools sources 
from this extracted source.
#cd  i2c-tools_3.1.0
#make 
#make install
This, will install the i2c-tools and now we are ready to use i2cdetect to detect any I2C device or 
peripheral connected to I2C Bus of RaspberryPi. After powering on and connecting, the RTC circuit 
to RaspberryPi, we power on the RaspberryPi and run i2cdetect for i2c-0 and i2c-1.
#i2cdetect -y -a 0
#i2cdetect -y -a 1



The Above figure shows that ds1307 is detected on I2C-1 Bus, on address 0x68, however 'UU' means that the device is 
busy, and is not available. To, detect the DS1307 RTC at RaspberryPi startup, a few changes would be required in the 
RaspberryPi startup files. So, to start looking at them, lets look into the file'/etc/rc.local ', in the Root File System 
partition.

Add the following lines, at the beginning, of the file, '/etc/rc.local':

echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
/sbin/hwclock -s

update-rc.d -f  fake-hwclock remove
update-rc.d -f  ntp remove



As, shown in the figure above, in the 'rc.local' file,we have added the following lines, which will set the DS1307 to use
I2C Bus with device address 0x68. Also, we have removed the default fake HWClock, which is governed by Kernel 
timer mechanism, since now we will set the HWClock as being updated externally using RTC.

After this, in the boottime parameters and bootargs of RaspberryPi, we have to add the following argument:
rtc.i2c=ds1307,1,0x68

In the file '/boot/cmdline.txt' in the Boot Partition,the above lines would be added in the following way:
dwc_otg.lpm_enable=0 rtc.i2c=ds1307,1,0x68 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 
root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

After, this power in the RTC DS1307 circuit, first and after that power up RaspberryPi. The RaspberryPi boots up
and starts successfully. Now, check, the 'dmesg' logs using:
#dmesg | tail

The following output should be displayed, which shows that DS1307 has been registered as a Device node, 'rtc0'

[   22.999268] rtc-ds1307 1-0068: rtc core: registered ds1307 as rtc0
[   22.999309] rtc-ds1307 1-0068: 56 bytes nvram
[   22.999363] i2c i2c-1: new_device: Instantiated device ds1307 at 0x68

Check, the '/dev' directory, and we can see a device node 'rtc0' has been created successfully.




Next, we delete the current Timezone and update the Timezone using the below commands:

# rm -f /etc/localtime
# ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime


After, this set the Time, using 'date' command:
# date --set="2014-11-23 18:35:47"

and, update the HWClock using:
/sbin/hwclock --systohc

Now, check, the date and time using 'date' command:
#date

After, Date and Time has been set correctly, restart RaspberryPi

Now, check the date and time, after restarting RaspberryPi.


We can see, that the date and time is retaining and is updating successfully, after restarting RaspberryPi as displayed 
above.

This, completes the Task of interfacing RTC DS1307 Clock with RaspberryPi.
Comments and suggestions, most welcome.

Thanks,
Rajiv.















































No comments:

Post a Comment