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:

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

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:

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:


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;
  bcd2dec := (bcd div 16 * 10) + (bcd mod 16);

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+}

    {$IFDEF UNIX}{$IFDEF UseCThreads}

    I2C_SLAVE            = 1795;

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

function bcd2dec(
    bcd                  : integer)
                         : integer;


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

end; // bcd2dec


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

buf[0] := 0;

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


    fpread(handle, buf, 7);
    writeln('Error reading');
    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]));



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…

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: Logo

You are commenting using your 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