(This post discusses communication between arduino and raspberry Pi using I2C. If you want to use the USB connection as a serial connection, see this post: Serial Communications (USB) between a Raspberry Pi and an Arduino Using Lazarus / Free Pascal).
Spent a couple of days researching how to use I2C on the Raspberry Pi with Lazarus/Free Pascal. My prior experiment was to use a python program verbatim:
I can kind of read python and that’s about all. It isn’t a language I have any plans to use. My preference is Pascal. So I wanted to see what is necessary to use I2C with Pascal. Ends up being pretty simple.
There are some links on the FP website regarding accessing RPI hardware with FP:
http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi
There is a library listed on that web page, RPI_HAL, that supports I2C. I downloaded the library and did the sample (which doesn’t do any I2C calls). I then attempted to write a program to do a simple I2C write. I got run time errors unrelated to I2C. I decided it would be easier to just directly access I2C rather than figure out why the library was acting up.
Turns out, it is VERY easy to access I2C with Free Pascal. To do so you open I2C as a file:
iDevAddr : Cint = $04; devPath : string = '/dev/i2c-1'; handle := fpopen(devPath,O_RDWR); fpIOCtl(handle, I2C_SLAVE, pointer(iDevAddr));
To write a byte from buf:
fpwrite(handle, buf, 1);
To read a byte into buf:
fpread(handle, buf, 1);
Here is my program that is a replacement of the python program from my prior post:
program testrpi; {$mode objfpc}{$H+} uses baseUnix, classes, {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} sysutils; const I2C_SLAVE = 1795; var buf : packed array [0..1] of char; c : char; devPath : string = '/dev/i2c-1'; handle : Cint; iDevAddr : Cint = $04; begin try handle := fpopen(devPath,O_RDWR); fpIOCtl(handle, I2C_SLAVE, pointer(iDevAddr)); except writeln('Error initalizing i2c'); halt; end; while true do begin write('Enter digit 1-9:'); readln(c); if (not(c in ['1'..'9'])) then begin writeln('oops - try again'); continue; end; buf[0] := chr(ord(c) - ord('0')); try fpwrite(handle, buf, 1); except writeln('Error writing'); halt; end; //try buf[0] := #99; sleep(10); try fpread(handle, buf, 1); except writeln('Error reading'); halt; end; //try writeln('buf=', ord(buf[0])); end; //while fpclose(handle); end.
I got to use my new logic analyzer while learning I2C. Here is the trace of the RPI sending a ‘2’ to the Arduino:
and here is the Arduino echoing the 2 back:
Aug 2014 Update:
If you are using a user other than ‘pi’, MAKE SURE that user has been assigned to the I2C group in the /etc/group file. Click here if you don’t know how to do this.
Pingback: Serial Communications (USB) between a Raspberry Pi and an Arduino Using Lazarus / Free Pascal | Big Dan the Blogging Man
Hi,
thanks for this post. I would have a question. What is 1795? How did you get this number?
This is a constant used by IOCTL to indicate you will be communicating with an I2C slave. Google “ioctl i2c_slave” and you should be able to find more details, if you need them.
Thanks Dan! 🙂
This program working great!!! Thank you!
But how to access ds1307 RTC from lazarus form application?
Hi, thanks for this example. How to do the same in Form application?
The concept is the same. Create a Lazarus Application and you will use the same calls as used in this console example.