Recent

Author Topic: All i2c lazarus packages for raspberry  (Read 6003 times)

pascalbythree

  • Sr. Member
  • ****
  • Posts: 255
All i2c lazarus packages for raspberry
« on: December 11, 2021, 02:14:23 pm »
Hey lazarus crew,

On the internet i found the folllowing packges

pascalio
PXL
RPI-hal
Wiringpi

I am going to test my i2c setup, but the question is weither there are more packges / fpc code available to i2c on my Raspberry.

Does anybody know with packages i did might forget ?

Greets, Wouter van Wegen

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: All i2c lazarus packages for raspberry
« Reply #1 on: December 11, 2021, 02:34:58 pm »
When I looked at it I went straight to the kernel, wasn't difficult. Not sure whether I've still got the code to hand...

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

pascalbythree

  • Sr. Member
  • ****
  • Posts: 255
Re: All i2c lazarus packages for raspberry
« Reply #2 on: December 11, 2021, 02:45:56 pm »
Can i ask for  a second opinion ?

ThomasK

  • New Member
  • *
  • Posts: 48
Re: All i2c lazarus packages for raspberry
« Reply #3 on: February 24, 2022, 10:50:29 am »
A wrapper unit for baseunix calls.
Code: Pascal  [Select][+][-]
  1. unit i2cbasic;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   baseUnix, Classes, SysUtils;
  9. type
  10.   Regarray  = array [0..63] of byte;
  11.   pRegarray = ^Regarray;
  12.  
  13. function i2cfpIoctl(i2c_deviceaddress: ptruint): cint;
  14. function i2cfpgeterrno() : longint;
  15. function i2cOpen()  : cint;
  16. function i2cClose() : cint;
  17. function i2cwrite(var  buf ; nbytes : TSize) : Tsize;
  18. function i2cread( var  buf ; nbytes : TSize) : Tsize;
  19.  
  20. var
  21.   i2c_device           : cint    =  -1;    //file handle preset
  22.   i2c_address_sht35    : ptruint = $44;    //address of SHT75 sensor as found per i2cdetect -y 1
  23.   i2c_address_sht35a   : ptruint = $45;    //alternative address of SHT75 sensor as found per i2cdetect -y 1
  24.   i2c_address_sht85    : ptruint = $44;    //address of SHT85 sensor as found per i2cdetect -y 1
  25.   i2c_address_sgp30    : ptruint = $58;    //address of SGP30 SVM30 board as found per i2cdetect -y 1
  26.   i2c_address_sgp40    : ptruint = $59;    //address of SGP40 sensor from data sheet, i2cdetect -y 1 does not show it!
  27.   i2c_address_dps310   : ptruint = $77;    //address of DPS310 sensor as found per i2cdetect -y 1
  28.   i2c_address_svm40    : ptruint = $6A;    //address of SVM40 board as found per i2cdetect -y 1
  29.   i2c_address_mpc23017 : ptruint = $27;    //address of MPC23017 board as found per i2cdetect -y 1
  30.   i2c_address_pca9685  : ptruint = $70;    //address of PCA9685 board as found per i2cdetect -y 1
  31.   i2c_address_shtc1    : ptruint = $70;    //address of SHTC1 on SVM30 board as found per i2cdetect -y 1
  32.   i2c_address_all      : ptruint = $00;    //Broaadcast
  33.   data                 : Regarray;
  34.   count                : uint16;
  35.   pdata                : pRegarray;
  36.  
  37. (*
  38. pi@RasPiHW:~ $ i2cdetect -y 1
  39.      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  40. 00:          -- 04 -- -- -- -- -- -- -- -- -- -- --
  41. 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  42. 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  43. 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  44. 40: -- -- -- -- 44 45 -- -- -- -- -- -- -- -- -- --
  45. 50: -- -- -- -- -- -- -- -- 58 59 -- -- -- -- -- --
  46. 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  47. 70: 70 -- -- -- -- -- -- 77
  48. pi@RasPiHW:~ $
  49. *)
  50.  
  51.  
  52.  
  53. const
  54.   I2C_DEVICE_PATH   : string ='/dev/i2c-1';         //i²c bus on header pins 3 & 5
  55. // The following defines were taken from i2c-dev.h.
  56.   I2C_SLAVE         = 1795;  // 0x0703 - 1795 dec
  57.   I2C_WRITE_FAILED  = -1;
  58.   I2C_READ_FAILED   = -1;
  59.  
  60. implementation
  61.  
  62. function i2cfpIoctl(i2c_deviceaddress: ptruint): cint;
  63. //  i2c_device as file handle, Ndx (=I2C_SLAVE) is the IOCTL function request type, data is the target i2c device address.
  64. begin
  65.   Result := BaseUnix.FpIOCtl(i2c_device, I2C_SLAVE, pointer(i2c_deviceaddress));
  66. end { i2cfpIoctl } ;
  67.  
  68. function i2cfpgeterrno() : longint ;
  69. begin
  70.   result:=fpgeterrno;
  71. end { i2cfpgeterrno } ;
  72.  
  73. function i2cOpen() : cint;
  74. begin
  75.   i2c_device := fpopen(I2C_DEVICE_PATH, O_RdWr);
  76.   Result:=i2c_device;
  77. end { i2cOpen } ;
  78.  
  79. function i2cClose() : cint;
  80. begin
  81.   if i2c_device >= 0
  82.   then result:=fpclose(i2c_device)
  83.   else result:=-1;
  84. end { i2cClose } ;
  85.  
  86. function i2cwrite(var buf ; nbytes : TSize) : Tsize;
  87. begin
  88.   result:= fpwrite(i2c_device, buf, nbytes);
  89. end{ i2cwrite};
  90.  
  91. function i2cread(var buf; nbytes : TSize) : Tsize;
  92. begin
  93.   result:= fpread(i2c_device, buf, nbytes);
  94. end{ i2cread};
  95.  
  96. end { i2cbasic}.        
  97.  

As an example for reading SHT35 temp:
Code: Pascal  [Select][+][-]
  1. function sht35_get_t_rh_hi  ( i2c_deviceaddress : ptruint) : longint;
  2. var
  3.   rslt, i : integer;
  4.   crc : uint8;
  5.   locbuf : array[0..1] of byte;
  6. begin
  7.   result:=-1;
  8.   result:=i2cfpIOCtl(i2c_deviceaddress);
  9.   if result<0 then exit;
  10.   data[0]:=hi(sht35_SingleShot_Hi);
  11.   data[1]:=lo(sht35_SingleShot_Hi);
  12.   count :=2;
  13.   rslt:=i2cwrite(data[0],count);
  14.   if rslt<>count then
  15.   begin
  16.     result:=rslt;
  17.     exit;
  18.   end;
  19.   sleep(50); //not less, needed for processing of command - I know shall be avoided but for now...
  20.   count :=6;
  21.   rslt:=i2cread(data[0],count);
  22.   if rslt<>count then
  23.   begin
  24.     result:=rslt;
  25.     exit;
  26.   end;
  27.   locbuf[0]:=data[0];
  28.   locbuf[1]:=data[1];
  29.   crc:=sensirion_i2c_generate_crc(locbuf);
  30.   crc8_t_err:= crc<>data[2];
  31.   if crc8_t_err then loc_temperature := 22.47;
  32.   locbuf[0]:=data[3];
  33.   locbuf[1]:=data[4];
  34.   crc:=sensirion_i2c_generate_crc(locbuf);
  35.   crc8_h_err:= crc<>data[5];
  36.   if crc8_h_err then loc_humidity := 65.11;
  37.   if not (crc8_t_err or crc8_h_err)
  38. {
  39. t_degC = -45 + 175 * t_ticks/65535
  40. rh_pRH =  100 * rh_ticks/65535
  41. }
  42.   then begin
  43.     i:= data[0] * 256 + data[1];
  44.     loc_temperature := (175 * i/ 65535.0) - 45;
  45.     i:= data[3] * 256 + data[4];
  46.     loc_humidity := 100 * i / 65535.0;
  47.     result:=0;
  48.     exit;
  49.   end
  50.   else begin
  51.     loc_temperature := 22.47;
  52.     loc_humidity := 65.11;
  53.     exit;
  54.   end;
  55.   result:=0;
  56. end { sht35_get_t_rh_hi } ;  
  57.  
it works.
don't forget error handling:
Code: Pascal  [Select][+][-]
  1.   if i2c_device>0 then
  2.   begin
  3.     rslt:= sht35_get_t_rh_hi  ( i2c_address_sht35 );
  4.     if rslt=-1
  5.     then begin
  6.       if not crc8_t_err or crc8_h_err
  7.       then begin
  8.         ioctlerr:=i2cfpgeterrno;
  9.  
translate error code to string
Code: Pascal  [Select][+][-]
  1. function ioctlerrortext(const error_no): string;
  2. var
  3.   I : byte;
  4. begin
  5. I:=byte(error_no);
  6. case I of
  7.     1 : result:=  'EPERM                Operation not permitted';
  8.     2 : result:=  'ENOENT               No such file or directory';
  9. //cnt
  10.   131 : result:=  'ENOTRECOVERABLE      State not recoverable';
  11.   else result:='unknown';
  12. end;  
  13.  
« Last Edit: February 24, 2022, 10:54:42 am by ThomasK »
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: All i2c lazarus packages for raspberry
« Reply #4 on: February 24, 2022, 11:12:18 am »
I agree that that thin wrapper is entirely adequate, but I'd like to add a couple of comments due to experience over the last few days.

First, correct behaviour of the i2cdetect program depends on the interface chip and Linux driver. While this is not directly relevant to an RPi, if using something like a CH341A attached to a PC via USB then i2cdetect shows all devices present ("phantom devices"), and the only known fix for this breaks access to certain types of slave chip (e.g. mfrc522 RFID reader).

Second, there is an additional write/read facility available via another ioctl call. This is illustrated at https://github.com/SAmeis/pascalio/blob/master/src/i2c_dev.pas but DO NOT USE THIS CODE: the i2c_msg definition is broken.

I have a fixed version which I will probably put on Github after more testing, but until then I'll post it here if anybody wants it.

Also note that the combined write/read facility will have device-specific limitations: a CH341A can only handle a 63-byte read as a single transfer.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ThomasK

  • New Member
  • *
  • Posts: 48
Re: All i2c lazarus packages for raspberry
« Reply #5 on: February 24, 2022, 11:28:20 am »
Thanks for the comment.

The intention was to show that it is possible to avoid libraries and give a short example how to use it with a sensor.

I do not expect working on other platforms than rapberry pi without  mods. And there are a lot i2c device specific limitations, one has to look into the datasheets in each case.

I just wanted to isolate all baseunix jobs in one unit and later adding the cability to use it under windows with a MCP2221A.

I need to use i2c devices without a pi.

Due to not availablity of the hardware (pi) we have to do so.
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: All i2c lazarus packages for raspberry
« Reply #6 on: February 24, 2022, 11:35:33 am »
I do not expect working on other platforms than rapberry pi without  mods. And there are a lot i2c device specific limitations, one has to look into the datasheets in each case.

I believe your code will work on other Linux systems without problems.

I agree with your point about the desirability of being able to access something like I2C with no unnecessary libraries etc. interposed: it really is a very simple kernel-level interface, and does not deserve obfuscation.

However, if we look at the other popular bus at this level i.e. SPI, we find that /all/ operations are via in-memory parameter blocks, and at that point I think it is desirable for the programmer to at least be aware that there is a comparable facility for I2C (even if there are differences in detail due to SPI's requirement for padding bytes).

MarkMLl
« Last Edit: February 24, 2022, 02:19:04 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

ThomasK

  • New Member
  • *
  • Posts: 48
Re: All i2c lazarus packages for raspberry
« Reply #7 on: April 13, 2022, 12:46:39 pm »
I created a full working application running on a Pi and together with a MCP2221a also on a Windows PC.

https://github.com/EllenLouiseRipley/I2CRaspiAndWin.git
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

pascalbythree

  • Sr. Member
  • ****
  • Posts: 255
Re: All i2c lazarus packages for raspberry
« Reply #8 on: October 18, 2023, 11:03:45 am »
Code: Pascal  [Select][+][-]
  1. program i2cbasictest;
  2.  
  3. uses WVW_I2CBASIC, types, crt;
  4.  
  5. begin
  6.    i2cfpIoctl($38);
  7.    i2cOpen;
  8.    repeat
  9.       i2cread(data[0],1);
  10.           writeln(data[0]);
  11.           delay(155);
  12.    until keypressed;     
  13.    i2cClose;
  14. end.

Can somebody help me out getting this RPI code to work ? Looking for a Raspberry slave and  a AVR as master.
Just need to stuff strings ... Not that well in pointers and memory adresses

Can somebody give me a extra example?

Greets, Wouter van Wegen, PasCalByThree ...

ThomasK

  • New Member
  • *
  • Posts: 48
Re: All i2c lazarus packages for raspberry
« Reply #9 on: October 23, 2023, 01:17:26 pm »
what is wvw_i2cbasic?
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

 

TinyPortal © 2005-2018