Accessing Real Time Clock on Raspberry Pi using Lazarus/Free Pascal

I’ve really been buckling down and trying to get lots of time in on I2C today.

Once being able to communicate with Arduino from my Raspberry Pi using Free Pascal, I wanted to try to read a real time clock using FP as well.

I purchased a Tiny RTC on ebay, I believe. One like this:

http://www.ebay.com/itm/I2C-DS1307-Real-Time-Clock-Module-For-Arduino-Tiny-RTC-2560-UNO-R3-New-/261122560150?pt=LH_DefaultDomain_0&hash=item3ccc1e1096

First chore was to figure out exactly what I had. I found this explanation of the Tiny RTC:

http://www.hobbyist.co.nz/?q=real_time_clock

Not only is it an RTC, but it has some EEPROM on board as well as a temperature sensor.

First, to connect the RTC to the RPI, I used these instructions from Adafruit:

http://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/overview

No real trick, just connect GND, SCL, SDA as you would expect. Connect the VCC of the RTC to the 5V power supply on the RPI. When first testing the RTC, I connected it directly to the RPI as described above. However, once I saw it was running, I moved the RTC to the 5V side of the logic-level converter with the arduino just to be safe:

rtc-1

Once the RTC was connected, I did an i2cdetect to verify the RPI could see the RTC. It could. I then followed Adafruit’s instructions to set up the RTC as the RPI’s hardware clock. This allowed me to make sure the RTC’s time was valid. A quick summary of the commands necessary:

sudo su
modprobe rtc-ds1307
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
hwclock -r
hwclock -w

Once the hwclock is correct, you can set the system clock from it using

hwclock -s

By the way, if you accidentally set the system clock incorrectly, you can force it back using NTP with the following commands:

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

Once I knew the RTC was working fine, I was ready to try and read the date/time using Free Pascal. This is really pretty straight forward. 1st I needed a procedure to convert BCD to decimal:

function bcd2dec(bcd: integer): integer;
begin
  bcd2dec := (bcd div 16 * 10) + (bcd mod 16);
end;

then you write a zero to the RTC (I believe this indicates you are going to read from the zero register):

buf[0] := 0;
fpwrite(handle, buf, 1);

wait about 10ms, then read 7 bytes from the RTC

fpread(handle, buf, 7);

then you just format each byte in the buffer. Here are the seconds:

writeln('sec    : ', bcd2dec(buf[0] AND $7F));

One very important note: when using hwclock -w to set the RTC clock, it is going to set it to GMT, not your local time.

Here is the full source of my test program:

program testr2c;

{$mode objfpc}{$H+}

uses
    baseUnix,
    classes,
    {$IFDEF UNIX}{$IFDEF UseCThreads}
    cthreads,
    {$ENDIF}{$ENDIF}
    sysutils;

const
    I2C_SLAVE            = 1795;

var
    buf                  : packed array [0..9] of byte;
    devPath              : string = '/dev/i2c-1';
    handle               : Cint;
    iDevAddr             : Cint = $68;

function bcd2dec(
    bcd                  : integer)
                         : integer;

begin

bcd2dec := (bcd div 16 * 10) + (bcd mod 16);

end; // bcd2dec

begin

try
    handle := fpopen(devPath,O_RDWR);
    fpIOCtl(handle, I2C_SLAVE, pointer(iDevAddr));
except
    writeln('Error initalizing i2c');
    halt;
    end;

buf[0] := 0;

try
    fpwrite(handle, buf, 1); 
except
    writeln('Error writing');
    halt;
    end; //try

sleep(10);

try
    fpread(handle, buf, 7);
except
    writeln('Error reading');
    halt;
    end; //try

writeln('sec        : ', bcd2dec(buf[0] AND $7F));
writeln('min        : ', bcd2dec(buf[1]));
writeln('hour       : ', bcd2dec(buf[2] AND $3F));
writeln('WeekDay    : ', bcd2dec(buf[3]));
writeln('Day        : ', bcd2dec(buf[4]));
writeln('Month      : ', bcd2dec(buf[5]));
writeln('Year       : ', bcd2dec(buf[6]));

fpclose(handle);

end.

This experiment went smoothly and quickly the only thing I have left to try is reading/setting GPIO pins on the RPI using FP. And the day isn’t over yet…

Advertisements
This entry was posted in Arduino/RPI I2C, c-lazarus, c-rpi. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s