Pi & Lazarus I2C

I’ve been asked a few times now how we got I2C working without third party code. The reality is that thanks to the way Linux handles drivers it’s pretty easy and I’d expect direct access to 1 wire to be the same (We have bridges with FIFOs, parasitic power etc so we  dont need to try it)

First make sure you can talk to your I2C decvice with I2Ctools. Theres loads of info on this, off you go and hunt it down.

NOTE, BIG GOTCHYA!
latest versions of Raspbian use a new way of handling devices, make sure you use a tutorial that matches the way your system is setup as simply uncmmenting things in the modules blacklist may not be enough.

You shouldnt be running code as root, developing, yes, running as an end product, no. There are arguments against developing too but thats not why this article is here.  By default only root has access to I2C and we need to change that if your apps are going to work in userland. Its easy to do. Say we want pi to be able to do it:

sudo groupadd i2c pi

Now we can use the standard FPOpen(), FPRead(), FPWrite() to do the job.

var
  DEV_IMU : integer;
addr : byte;

This is the handle for the fle we are about to open and addr is the target device address on the bus

procedure openI2c;
var
   count : integer;
   data: byte;
   reg : byte;
begin
  DEV_IMU:= fpopen(‘/dev/i2c’,O_RDWR);
  if DEV_IMU= -1 then begin
             // we couldn’t open the bus
              exit;
              end
else begin
// associate this handle with an address on the bus
fpioCTL(DEV_IMU,1795, pointer(addr));
//success

end;

Now to read:

function readbyte(reg:word):word
var
    count : integer;
   data : byte;
begin
// we have to write before the read to send the register we want
     count := fpwrite(DEV_IMU,reg,1);
     if count <> 1 then begin
              // we couldnt do the write!
              exit;
              end;
// now read
    count := fpread(DEV_IMU,data,1);
     if count =0 then begin
              // nothing came back
              exit;
              end
  else result := data;
end;

And the write is easy enough. The read is write then read as we always nbeed to send the target register out. In the case of a write we can do this ‘back to back’

procedure writebyte(reg,data:byte)
var
    buffer : array [1..2] of byte;
    count : integer;
begin
     buffer[1] := reg;
     buffer[2] := data;
     count := fpwrite(DEV_IMU,buffer,2);
     if count <> 2 then begin
              // write failed
              exit;
              end
     else // write ok
end;

This should have you up and running in no time.

Leave a Reply

Your e-mail address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.