Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi I2C LM75 sensor (https://www.delphipraxis.net/206446-i2c-lm75-sensor.html)

yacdrak 22. Dez 2020 14:51

I2C LM75 sensor
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo zusammen,
Ich habe ein Problem mit der slave ACK. Hier möchte ich der Temperatur messen, dafür benutze ich eine Bibliothek von Asynchron Pro (https://github.com/TurboPack/AsyncPro).
Das Problem ist, dass ich kein ACK von Slave schicken kann. Das ist mein Quellcode und Vielen Danke für eure Hilfe. LG

muss normalaweise so sein (Anhängen foto):


mein Delphi Code :




unit Unit1;

interface


uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs , i2cusb, Vcl.StdCtrls, Vcl.ComCtrls;



const
cTimeoutInMs = 1000;
cTimeoutInit = 5000;
SCL90 = 'A'; { SCL 90 kHz PCD8584 Clocktakt }
SCL45 = 'B'; { SCL 45 kHz }
SCL11 = 'C'; { SCL 11 kHz }
SCL1_5 = 'D'; { SCL 1.5kHz }
type
//Ti2cUsb = class(TObject);
TForm1 = class(TForm)
Button1: TButton;
StatusBar1: TStatusBar;
Label1: TLabel;
procedure Button1Click(Sender: TObject);





private
{ Déclarations privées }
public


end;

var
Form1: TForm1;
ic, slave : Ti2cUsb;
Temperatur1 : Byte;
Temperatur2 : Byte;
Wert : Double ;
Byte1, Byte2 :Byte;
a : Double;



implementation

{$R *.dfm}


Function i2cLM75_in(Var Temperatur1 , Temperatur2 : Byte):double; //Liest einen Wert (2 Byte) vom LM75 Temperatursensor
var Byte1, Byte2 :byte;
Wert : double ;

begin
Byte1 := Temperatur1; //1. Byte Wert vom LM75 lesen
Byte2 := Temperatur2;

If (Byte1 And 128) = 0 Then
Wert := Byte1 //Temperatur Vorkomma >= 0°C
Else
Wert := Byte1 - 255; //Temperatur Vorkomma < 0°C

If ((Byte2 And 128) <> 0) Then
Wert := Wert + 0.5;

i2cLM75_in := Wert;

End;



procedure TForm1.Button1Click(Sender: TObject);

begin
ic := Ti2cUsb.Create;
slave := Ti2cUsb.Create;
//Check if the I2C is Initialized

Repeat
ic.Init(4,SCL90);
Until ic.Is_Initialized = True;
ic.relais_on ;
Sleep(1000);


ic.start_iic(False,146,'w'); // Start LM75
ic.wr_byte_iic(0);
ic.stop_iic;


ic.restart_iic (False, 147 , 'r');

ic.rd_byte_iic(Temperatur1,False);
ic.rd_byte_iic(Temperatur2,True);

ic.relais_off ;
ic.stop_iic;


a := i2cLM75_in(Temperatur1 , Temperatur2 );

ShowMessage(a.ToString);

end;

End.

generic 23. Dez 2020 11:47

AW: I2C LM75 sensor
 
In der AsyncPro finde ich keine Datei für die i2c Kommunikation.

Was ist die Unit i2cusb ?
Welches Interface nutzt du zum i2c bus?

Rollo62 24. Dez 2020 13:40

AW: I2C LM75 sensor
 
Ich bin nicht 100% sicher, denke aber AsyncPro unterstützt nur Rs232 Interfaces.
Vielleicht gibt es mittlerweile ja was Neues, denke aber nicht.
Mit Rs232 könnte man evtl. etwas über die Steuerleitungen simulieren,
Aber echtes I2C wird wohl schwierig.

Es könnte sein das Du noch einen Rs232 zu I2C Konverter brauchst.

newIndy 25. Dez 2020 08:00

AW: I2C LM75 sensor
 
Vielleicht hilt das weiter:
https://www.horter.de/i2c/i2c-beispi..._delphi_1.html

Frohe Weihnachten und bleibt gesund.

yacdrak 7. Jan 2021 11:46

AW: I2C LM75 sensor
 
Guten Morgen, vielen Danke für eure Antwort. Ich benutze Delphi IDE für I2C.
1) Unit i2cusb ist die Bibliothek von Asynchron Pro aus Github. Das Problem, dass ich verpflichtet bin, diese Bib zu nutzen.
Ich bin mir sicher, dass die verkabel richtig aufgebaut sind. Aber bekomme ich 255 als Antwort. Irgendwie mein i2c Master liest nicht aus der Slave LM75, sondern aus der Bus allgemein.

Haupt Funktionen, die ich benutze sind :
1- function start_iic (MRX_ACK: boolean; dest: byte; mode: char): byte;
Die Funktion erzeugt einen Startrahmen mit der Zieladresse dest. Der Wert mode (r oder w) gibt die
Richtung der Übertragung an. Letztlich bestimmt der mode das niederstwertigste Bit der Adresse des
anzusprechenden I2C-Bausteins. Der boolesche Parameter MRX_ACK gibt an, ob ein Acknowledge beim
nächsten übertragenen Byte zu unterdrücken ist (false) oder nicht.

2- stop_iic
function stop_iic: byte;
erzeugt eine Stopp-Bedingung auf dem I2C-Bus. Rückgabewert siehe oben.
2.3.3 wr_byte_iic
function wr_byte_iic(b: byte ): byte;
schreibt – als Master-Transmitter – ein Byte auf den I2C-Bus. Rückgabewert siehe oben.


3- rd_byte_iic
function rd_byte_iic (var B: BYTE; NOACK: Boolean):byte;
liest ein Byte (als Master Receiver) vom I2C-Bus. (Bedingt durch den Aufbau des Geräts wird immer das
Byte ausgegeben, was vor der aktuellen Übertragung auf dem Bus zu beobachten war. Dieser Wert wird
in B übergeben. Der Parameter NOACK bewirkt – falls er auf true gesetzt wird – daß bei der nächsten
Übertragung ein negatives Acknowledge generiert wird. Rückgabewert siehe oben.


4- restart_iic
function restart_iic (MRX_ACK: boolean; dest: byte; mode: char ):byte;
erzeugt eine Start-Bedingung innerhalb einer laufenden Kommunikation. Die Parameterbeschreibungen
entsprechen denjenigen bei start_byte_iic. Rückgabewert siehe oben.


5- wr_byte_port
procedure wr_byte_port (zuSchreiben: byte);
schreibt ein Byte (zuSchreiben) auf den I/O-Ausgang des USB-ITS-Geräts. Man beachte die Beschaltung
des Ports! Erzeugt werden TTL-Signale.

6- rd_byte_port
procedure rd_byte_port (var gelesen: byte);
liest ein Byte (gelesen) vom I/O-Port des USB-ITS-Geräts. Die erkannten Spannungsbereiche sind TTLkonform.

7- Init
function Init (ComPortNr: byte): byte; overload; und
function Init (ComPortNr: byte; Takt: char): byte; overload;
dienen der Initialisierung des USB-ITS-Gerätes, verschiedener Timer und Konstanten. Eine dieser Funktionen ist zu Beginn der Arbeit mit dem System aufzurufen. Als Parameter erwartet Init die Nummer des
COM-Ports, an dem das Gerät zu finden ist. Weiterhin ist optional die Angabe des Bustaktes möglich.
Dafür sind die Werte SCL90, SCL45, SCL11 und SCL1_5 vorgesehen, die für 90 kHz, 45 Khz, 11 kHz
und 1,5 kHz stehen. Voreingestellt ist ein Wert von 90 kHz als I
2C-Bustakt (falls der Parameter Takt fortgelassen wird).

8- Is_Initialized
property Is_Initialized:boolean kann ausgelesen werden und zeigt – falls sie TRUE ist – an, daß
die Initialisierung des Gerätes und damit des I2C-Busses erfolgreich abgeschlossen wurde.

9- Relais_On
procedure relais_on läßt das Relais für die zusätzliche Busversorgung anziehen.
Bei den angesprochenen Relais handelt es sich um umschaltende Relais, die beidseitig beschaltet sind.
Möglicherweise kann auch die invertierte Bedienung den gewünschten Effekt erzeungen.

10- Relais_Off
procedure relais_off läßt das Relais für die zusätzliche Busversorgung abfallen.
Bei den angesprochenen Relais handelt es sich um umschaltende Relais, die beidseitig beschaltet sind.
Möglicherweise kann auch die invertierte Bedienung den gewünschten Effekt erzeungen.


Ich habe keine Lösung noch gefunden und ich versuche noch paar sachen. Wenn ihr Idee habt, bitte mir helfen.
Vielen Danke für eure Hilfe

Rollo62 7. Jan 2021 12:46

AW: I2C LM75 sensor
 
Bist Du denn sicher dass bei deinem I2C 5V ankommen,
der RS232-Ausgang ist normalerweise 12V.

Die Frage nach dem Hardware-Interface, von generic, ist noch offen.

yacdrak 7. Jan 2021 15:11

AW: I2C LM75 sensor
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja normalerweise

Moombas 8. Jan 2021 06:52

AW: I2C LM75 sensor
 
Die 5V scheinen zumindest für den Sensor zu passen.
Hast du mal ein komplettes Schaltbild mit entsprechend richtigen Bezeichnungen (wo welches IC mit welchen Pins etc.)?

generic 8. Jan 2021 10:21

AW: I2C LM75 sensor
 
Zitat:

Zitat von yacdrak (Beitrag 1480470)
Guten Morgen, vielen Danke für eure Antwort. Ich benutze Delphi IDE für I2C.
1) Unit i2cusb ist die Bibliothek von Asynchron Pro aus Github. Das Problem, dass ich verpflichtet bin, diese Bib zu nutzen.

Kann ich leider nicht finden, hättest du bitte einen Link für mich. Ich möchte mir die i2usb im Quelltext anschauen.
Danke

mschaefer 8. Jan 2021 11:53

AW: I2C LM75 sensor
 
Moin, der Link wird sich nicht bei Async finden:

Async .... It provides direct access to serial ports, TAPI, and the Microsoft Speech.

Das könnte dieses USB-I²c-Interface sein:
http://www.braintechnology.de

Hier könnte man mal schauen
http://www.braintechnology.de/braint...l_help_en.html

Das hat schon seinen Kniffel-Faktor :-)

himitsu 8. Jan 2021 15:43

AW: I2C LM75 sensor
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also ja, man könnte die CTS/RTS/...-Leitungen eines Comports manuell ansteuern und darüber die Daten für I2C übertragen.
Man braucht ja "nur" irgendwelche 2 bis 3 IO-Pins -> SCL (OUT) und SDA (InOut oder IN+OUT).

Es gibt bestimmt auch fertige USB-I2C-Adapter, [ADD] https://www.amazon.de/gp/product/B07VSMW6P6, https://www.amazon.de/ELV-USB-I%C2%B.../dp/B007IR9CDY , ... [/ADD]
und wenn selber-machen, dann nicht deletantisch über CTS/RTS, sondern ich würde eher einen µPC empfehlen (z.B. ein winziger Arduiono-Kompatibler), wo man ein Programm draufmacht, welches COM-Port auf I2C weiterleitet (gibt es schon fertig in den Demos).
Oder sowas wie einen RaspberryPI, wo derartige Dinge direkt am GPIO verfügbar sind. Es gibt/gab auch für x86 (Intel) ein paar Mainboards, mit derartigen GPIO.


zu den USB-Comport-Adaptern oder oft auch auf Mainbords verbaut:
Oft sind Multi-Purpose-Chips verbaut, für die Windows oft sogar die Treiber im automatischen Download drin hat.
FT232R (Serial + frei programmierbare Ports des CBUS), FT232H (Serial, SPI und I2C), CP2102 (nur Serial), CH340 (Serial, Print, I2C und SPI) oder PL2303/TUSB3410 (Serial, I2C, Infrarot-I/O und 4 freie I/O-Ports)

Links die kleinen USB-ComPort-Adapter sind minimalbeschaltet, also raus gehen oft nur RX/TX/GND/VDD
aber es gibt auch "Besseres", bis hin zu den "Extremen", wie links unten.
Das ist ein vollbeschalteter CH341, wo man sieht, was diese Chips eigentlich können.

COM und LPT (ganz rechts die Stifte und mittig die Lötkontakte, welche den "kompletten" ComPort/UART mit 25 Pins oder den großen Druckerport darstellen)
und dazu dann noch I2C, SPI, ...
Er arbeitet je nach Mode-Schalter als CH340 (ComPort, VID=1A86,PID=7523) oder CH341 (I2C+SPI, VID=1A86,PID=5512)

Beim CH341 muß man zwar den Treiber sich selbst besorgen, aber dafür findet man dort neben der DLL auch eine Header-Datei für den Zugriff auf I2C.
http://deviceinbox.com/drivers/845-u...2c-ch341a.html
die kleine CH341PAR_2.2.2009.6.ZIP


https://othermod.com/gpio-buttons/
https://www.raspberrypi-spy.co.uk/20...ader-and-pins/

https://www.amazon.de/AZDelivery-Dig.../dp/B01N7SGC1I
https://www.amazon.de/AZDelivery-Atm...dp/B078SBBST6/

Der ATtiny85 hat nur einen USB-Emulator (nicht sehr optimal, da der Chip eigentlich zu langsam ist) ... es gibt einen besseren Nachfahren mit "neuerem" Chip (hab den Namen grad vergessen)


[ADD]
Der Ersatz für den ATTiny85 mit echtem Hardware-USB, anstatt einer "bösen" Emulation, die nicht immer zuverlässig funktioniert und einen eigenen Treiber benötigt.
https://www.amazon.de/TECNOIOT-Beetl.../dp/B07VL6G914
https://forum.pjrc.com/threads/50507...upt#post172802
Statt dem Original kann man aktuell überall eh nur den ChinaKlon kaufen.
Schade/witzig, dass selbst die Chinesen nichtmal auf eigene Ideen kommen, wie z.B. den unnötig großen Spannungswandler gegen einen Kleinen zu ersetzen ... allein die Stromversorgung belegt nutzlos über 70% des Platzes.

yacdrak 10. Apr 2021 20:54

AW: I2C LM75 sensor
 
Hallo zusammen,
Danke für eure Hilfe. Leider habe ich keine lösung gefunden. Ich habe den Code geändert aber ich bekomme noch 255 253 als Ergebnis. können sie bitte mir helfen ?

Delphi-Quellcode:
unit Unit1;

interface


uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs , i2cusb, Vcl.StdCtrls, Vcl.ComCtrls;


const
cTimeoutInMs = 1000;
cTimeoutInit = 5000;

type
  TArray = array[0..7] of Byte;
  TArray11 = array[0..10] of Byte;
  TByteArr = array of byte;
  TForm1 = class(TForm)
  Button1: TButton;
  StatusBar1: TStatusBar;
  Label1: TLabel;

  procedure Button1Click(Sender: TObject);


  private
    { Déclarations privées }
  public


  end;

   function start_i2c ( address : Integer ):ShortInt;
  function stop_i2c():ShortInt;
  function slave_port( address: TArray): ShortInt;
  function ACK_Slave():ShortInt;
  function ACK_Master():ShortInt;
 Function temperature_LM75_lesen():TArray;
 function Integer_To_Byte(str: String):TByteArr;
 function write( Wert : TArray ):ShortInt;
 function read():TArray;
 function No_ACK_Master():ShortInt;


var
  Form1: TForm1;
  ic : Ti2cUsb;
  Temperatur1 : Byte;
  Temperatur2 : Byte;
  Wert : Double ;
  Byte1, Byte2 :Byte;
  a : Double;
  write_add_temp : TArray = (1,0,0,1,0,0,0,0);
  read_add_temp : TArray = (1,0,0,1,0,0,0,1);
  write_add_pca : TArray = (0,1,0,0,1,1,1,0);
  read_add_pca : TArray = (0,1,0,0,1,1,1,1);
  init_temp : TArray = (0,0,0,0,0,0,0,0);
  pointer_Byte : TArray = (0,0,1,1,0,0,0,1);

implementation

     {$R *.dfm}



function slave_port( address : TArray): ShortInt;
var i:ShortInt;
begin
    for i := 0 to 7 do
   begin
   if address[i] = 1 then
   begin
  ic.wr_byte_port(1); //SDA = 1 SCL = 0
   ic.wr_byte_port(0); //SDA = 1 SCL = 1
   end
   else
   begin
   ic.wr_byte_port(3); //SDA = 0 SCL = 0
   ic.wr_byte_port(2); //SDA = 0 SCL = 1
   end;
   end;
   Result := 0;
end;

function start_i2c ( address : Integer ):ShortInt;
begin

  ic.wr_byte_port(0); //SDA = 1 ; SCL = 1
  ic.wr_byte_port(2); //SDA = 0 ; SCL = 1

   if address = 144 then
   begin
     slave_port(write_add_temp);
   end
   else if address = 145 then
   begin
     slave_port(read_add_temp);
   end
   else if address = 78 then
   begin
     slave_port(write_add_pca);
   end
   else if address = 79 then
   begin
     slave_port(read_add_pca);
   end;
   Result := 0;
end;



function ACK_Slave():ShortInt;
begin
  ic.wr_byte_port(1); //SDA = 1 SCL = 0
   ic.wr_byte_port(0); //SDA = 1 SCL = 1
   ic.wr_byte_port(3); //SDA = 0 SCL = 0         //   3
   Result := 0;
end;

function ACK_Master():ShortInt;
begin
    ic.wr_byte_port(3); //SDA = 0 SCL = 0
   ic.wr_byte_port(2); //SDA = 0 SCL = 1
   ic.wr_byte_port(3); //SDA = 0 SCL = 0
   Result := 0;
end;

function No_ACK_Master():ShortInt;
begin

   ic.wr_byte_port(1); //SDA = 1 SCL = 0
   ic.wr_byte_port(0); //SDA = 1 SCL = 1
   ic.wr_byte_port(3); //SDA = 0 SCL = 0
   Result := 0;
end;


function stop_i2c():ShortInt;
begin
  ic.wr_byte_port(3); //SDA = 0 SCL = 0
  ic.wr_byte_port(0); //SDA = 1 ; SCL = 1
  Result := 0;
end;





Function temperature_LM75_lesen():TArray; //Liest einen Wert (1 Byte) vom LM75 Temperatursensor
var
 i:ShortInt;
 value:Byte;
 arr:TArray;
begin

       for i := 7 downto 0 do
       begin
           ic.wr_byte_port(1);
           ic.wr_byte_port(0);
           ic.rd_byte_port(value);
          arr[i] := value;
          ShowMessage(value.ToString);


       end;

 Result := arr;


end;





function Integer_To_Byte(str: String):TByteArr;
var
i: integer;
begin
SetLength(Result, Length(str));
for i := 0 to length(str)-1 do
  Result[i] := ord(str[i+1]) -48;
end;




function write( Wert : TArray ):ShortInt;
var

myByte : TArray;
i : ShortInt;
begin
myByte := Wert;

   for i := 7 downto 0 do
   begin
   if myByte[i] = 1 then
   begin
   ic.wr_byte_port(1); //SDA = 1 SCL = 0
   ic.wr_byte_port(0); //SDA = 1 SCL = 1
   end
   else
   begin
   ic.wr_byte_port(3); //SDA = 0 SCL = 0
   ic.wr_byte_port(2); //SDA = 0 SCL = 1
   end;
   end;
Result := 0;
end;

function read():TArray;
 var
 i:ShortInt;
 value:Byte;
 arr : TArray;
begin

       for i := 7 downto 0 do
       begin
           ic.wr_byte_port(1);
           ic.wr_byte_port(0);
           ic.rd_byte_port(value);
           arr[i] := value;

       end;

 Result := arr;
 end;




procedure TForm1.Button1Click(Sender: TObject);

 var
 val1 : TArray;
 val2 : TArray;
 temp : TArray11;
 Value : double ;
  I: Integer;
 begin


 //Register Temp configurate
 ic := Ti2cUsb.Create;
 ic.Init(3);
 start_i2c(78);
 ACK_Slave;
 write(init_temp);
 ACK_Slave;
 stop_i2c;


 //Read Temp register with preset Pointer (2 Byte Data)
 start_i2c(79);
 ACK_Slave;
 val1 := temperature_LM75_lesen;
 ACK_Master;
 val2 := temperature_LM75_lesen;
 No_ACK_Master;
 stop_i2c;






  for I := 0 to 10 do
begin
   if I<3 then
   begin
     temp[I] := val2[I];

   
   end
   else
   begin
     temp[I] := val1[I];

 
   end;







end;

 end;

End.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz