
ödev konusu şu bilgisayar kontrollü bir depo izleme sistemi var. Burada PLC'den
gelen bilgiler ekranda gösterilecek. ve ekranda basılan valf PLC tarafında
açılacak gibi birşey işte.
Omron CQM1H serisi için haberleşme protokolü :
Programın arayüzü:
Kullanılan Komponentler :
Cport v3.0, LMDTools v6.11, Delphi 7
Kod: Tümünü seç
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CPort, StdCtrls, ExtCtrls, CPortCtl, LMDCustomComponent,
LMDWndProcComponent, LMDCustomFormFill, LMDFormFill, Buttons, LMDControl,
LMDBaseControl, LMDBaseGraphicControl, LMDBaseLabel,
LMDCustomSimpleLabel, LMDSimpleLabel, LMDGraphicControl,
LMDBaseMeter, LMDCustomProgressFill, LMDProgressFill, LMDBaseShape,
LMDShapeControl, LMDShadowFill, LMDLEDCustomLabel, LMDLEDLabel,
LMDScrollText;
type
TForm1 = class(TForm)
ComPort1: TComPort;
TimerPLCRead: TTimer;
Panel1: TPanel;
ComLed1: TComLed;
ComLed2: TComLed;
ComLed3: TComLed;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
LMDFormFill1: TLMDFormFill;
BitBtn1: TBitBtn;
Memo2: TMemo;
Image1: TImage;
Image2: TImage;
Image3: TImage;
LMDSimpleLabel1: TLMDSimpleLabel;
LMDSimpleLabel2: TLMDSimpleLabel;
LMDProgressFill1: TLMDProgressFill;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
LMDShapeControl1: TLMDShapeControl;
Image4: TImage;
Image5: TImage;
LMDSimpleLabel3: TLMDSimpleLabel;
LMDSimpleLabel4: TLMDSimpleLabel;
SpeedButton3: TSpeedButton;
SpeedButton4: TSpeedButton;
LMDShapeControl2: TLMDShapeControl;
LMDSimpleLabel5: TLMDSimpleLabel;
LMDLEDLabel1: TLMDLEDLabel;
LMDSimpleLabel6: TLMDSimpleLabel;
LMDLEDLabel2: TLMDLEDLabel;
LMDSimpleLabel7: TLMDSimpleLabel;
LMDShadowFill1: TLMDShadowFill;
LMDSimpleLabel8: TLMDSimpleLabel;
Image6: TImage;
Image7: TImage;
Image8: TImage;
LMDSimpleLabel9: TLMDSimpleLabel;
LMDSimpleLabel10: TLMDSimpleLabel;
LMDProgressFill2: TLMDProgressFill;
SpeedButton5: TSpeedButton;
SpeedButton6: TSpeedButton;
LMDShapeControl3: TLMDShapeControl;
LMDLEDLabel3: TLMDLEDLabel;
LMDSimpleLabel14: TLMDSimpleLabel;
LMDLEDLabel4: TLMDLEDLabel;
LMDSimpleLabel15: TLMDSimpleLabel;
LMDShadowFill2: TLMDShadowFill;
LMDSimpleLabel16: TLMDSimpleLabel;
Image11: TImage;
LMDSimpleLabel11: TLMDSimpleLabel;
Image9: TImage;
Image10: TImage;
LMDSimpleLabel17: TLMDSimpleLabel;
LMDSimpleLabel18: TLMDSimpleLabel;
SpeedButton7: TSpeedButton;
SpeedButton8: TSpeedButton;
LMDShapeControl4: TLMDShapeControl;
Image12: TImage;
Image13: TImage;
Image14: TImage;
Label4: TLabel;
Label5: TLabel;
LMDSimpleLabel12: TLMDSimpleLabel;
LMDSimpleLabel13: TLMDSimpleLabel;
procedure FormCreate(Sender: TObject);
procedure TimerPLCReadTimer(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
Function hexToInt(hexStr: string): longint;
procedure VarstoEdits;
procedure SpeedButton4Click(Sender: TObject);
procedure Panel1Click(Sender: TObject);
private
cSendBuffer : PChar; // Gönderilecek verinin tutulduğu buffer değişken
cRcvBuffer : PChar; // Gelen verinin tutulduğu buffer değişken
CharCntReceived : Integer; // Porta gelen veri sayısı
iErrorCount : integer; // Cevap alamama sayısı
myReadOnlyDMArea : array [0..14] of Word; // PLC DM areasının aynası
procedure CalcCRC(sStr:PChar;iLength :Integer; var Fcs1,Fcs2:Char);
Function CheckCRC(sStr:PChar;iLength :Integer): Boolean;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{--------------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
cRcvBuffer := StrAlloc(512);
cSendBuffer := StrAlloc(512);
for i:=0 to 511 do cSendBuffer[i] := #0;
for i:=0 to 14 do myReadOnlyDMArea[i]:=0;
CharCntReceived := 0;
iErrorCount := 3;
comport1.Connected:=TRUE;
comport1.ClearBuffer(TRUE,TRUE);
TimerPLCRead.Enabled := TRUE;
end;
{--------------------------------------------------------------------------}
{Tform1.FormClose}
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
// Program kapatılmadan önce timer ve seri port kapatılmalı.
// Seri portta çıkan bir hatadan dolayı kapatmadan önce Clearbuffer ile temizlenmesi lazım
TimerPLCRead.Enabled:=FALSE;
comport1.ClearBuffer(TRUE,TRUE);
//comport1.Connected:=FALSE;
Close;
end;
{--------------------------------------------------------------------------}
// Tüm SpeedButtonlar Bu Fonksiyna Bağlı
(*
DM 4: Vana ve Pompa Açma Komutu
0001 : Output 100.0 Depo 2 - Çıkış Valfi-Pompa
0010 : Output 100.1 Depo 2 - Giriş Valfi
0100 : Output 100.2 Depo 1 - Çıkış Valfi-Pompa
1000 : Output 100.3 Depo 1 - Giriş Valfi
*)
procedure TForm1.SpeedButton4Click(Sender: TObject);
var cFcs1 , cFcs2:Char;
begin
try
cSendBuffer[0] := '@';
cSendBuffer[1] := '0';
cSendBuffer[2] := '0';
cSendBuffer[3] := 'W';
cSendBuffer[4] := 'D';
cSendBuffer[5] := '0';
cSendBuffer[6] := '0';
cSendBuffer[7] := '0';
cSendBuffer[8] := '4';
if SpeedButton1.Down then cSendBuffer[9] := '1' else cSendBuffer[9] := '0';
if SpeedButton3.Down then cSendBuffer[10] := '1' else cSendBuffer[10] := '0';
if SpeedButton5.Down then cSendBuffer[11] := '1' else cSendBuffer[11] := '0';
if SpeedButton7.Down then cSendBuffer[12] := '1' else cSendBuffer[12] := '0';
CalcCRC(@cSendBuffer[0], 13, cFcs1, cFcs2);
cSendBuffer[13] := cFcs1;
cSendBuffer[14] := cFcs2;
cSendBuffer[15] := '*';
cSendBuffer[16] := #13;
cSendBuffer[17] := #0;
label4.Caption:= cSendBuffer;
comport1.WriteStr(cSendBuffer);
iErrorCount:= 4;
finally
//TimerPLCRead.Enabled:=TRUE;
end;
end;
{--------------------------------------------------------------------------}
procedure TForm1.TimerPLCReadTimer(Sender: TObject);
var PacketOK : boolean;
LastCount : integer;
y : integer;
begin
inc(iErrorCount);
// Porttan tampona gelen veriyi alır ve tampon değişkene aktarır.
// Eğer AsyncPro bileşenleri kullanılacak ise bu iki satır siline aşağıdaki ek yapıla
LastCount := comport1.read(cRcvBuffer[CharCntReceived],512);
CharCntReceived := CharCntReceived + LastCount;
PacketOK := ((CharCntReceived = 65 ) and (cRcvBuffer[0] = '@') and (cRcvBuffer[69] = '*'));
if PacketOK then PacketOK := CheckCRC(@cRcvBuffer[0],67);
if PacketOK or (iErrorCount > 5 ) then
begin
//Eğer packet sağlam ise stringi parse et..
if PacketOK then
begin
for y:=0 to 14 do myReadOnlyDMArea[y] := hexToInt(Uppercase(copy(cRcvBuffer,8+(y*4),4)));
VarsToEdits;
end;
// Bufferi temizle ve PLC'den yeni paket veri iste
iErrorCount:=0;
CharCntReceived := 0;
comport1.WriteStr('@00RD0000001552*'+#13+#0);
end;
end;
{--------------------------------------------------------------------------}
(*<<<>>><<<>>>DM Area Map<<<>>><<<>>>
DM 0 : Depo 1 Analog Sıcaklık Bilgisi
DM 1 : Depo 1 Analog Basınç Bilgisi
DM 2 : Depo 2 Analog Sıcaklık Bilgisi
DM 3 : Depo 2 Analog Basınç Bilgisi
<<<>>><<<>>>DM Area Map<<<>>><<<>>>*)
procedure Tform1.VarstoEdits;
var tempStr : string;
y : integer;
begin
//<<<>>><<<>>>DEPO 1 için<<<>>><<<>>>
//Sıcaklık
tempStr:= Floattostrf(((myReadOnlyDMArea[0]*200/65535)-100),fffixed,8,1);
while length(tempStr)<6 do
tempStr:= ' '+tempStr;
LMDLEDLabel1.Caption := tempStr+' C';
//Basınçtan miktar
LMDProgressFill1.UserValue := myReadOnlyDMArea[1];
tempStr:= Floattostrf(((myReadOnlyDMArea[1]*4000/65535)),fffixed,8,1);
while length(tempStr)<6 do
tempStr:= ' '+tempStr;
LMDLEDLabel2.Caption := tempStr+' L';
//<<<>>><<<>>>DEPO 2 için<<<>>><<<>>>
//Sıcaklık
tempStr:= Floattostrf(((myReadOnlyDMArea[2]*200/65535)-100),fffixed,8,1);
while length(tempStr)<6 do
tempStr:= ' '+tempStr;
LMDLEDLabel3.Caption := tempStr+' C';
//Basınçtan miktar
LMDProgressFill2.UserValue := myReadOnlyDMArea[3];
tempStr:= Floattostrf(((myReadOnlyDMArea[3]*4000/65535)),fffixed,8,1);
while length(tempStr)<6 do
tempStr:= ' '+tempStr;
LMDLEDLabel4.Caption := tempStr+' L';
//Memo2 gelen DM bilgilerini ekranda göstermek için kullanılır.
//Memo2 LED panele tıklayınca açılır.
if memo2.Visible then
begin
memo2.Lines.Clear;
for y:=0 to 14 do
memo2.Lines.Add('DM'+inttostr(y)+' = ' + inttostr(myReadOnlyDMArea[y]));
end;
end;
(*
--------------------------------------------------------------------------
-------------------------- YARDIMCI FONKSIYONLAR -------------------------
--------------------------------------------------------------------------
HexToInt : girilen Hexadesimal sayıyı integera çevirir
CalcCRC : girilem Length uzunluğunda pchar stringin 16bit CRC kodunu hesaplar
ChechkCRC: girilen Length uzunluğunda pchar stringin 16bit CRC kodunu hesaplar
ve verilen CRC kodu ile karşılaştırır, doğru ise TRUE döner.
*)
Function Tform1.hexToInt(hexStr: string): longint;
var iErr:integer;
begin
Result := 0;
Val('$' + hexStr,Result , iErr);
end;
{--------------------------------------------------------------------------}
procedure TForm1.CalcCRC(sStr:PChar;iLength :Integer;var Fcs1,Fcs2:Char);
var cFcs, cTmpFcs:Byte;
i:Integer;
begin
cFcs := 0;
for i := 0 to iLength-1 do
cFcs := cFcs XOR ORD(sStr[i]);
cTmpFcs := cFcs AND $0f;
Fcs2:=CHAR(cTmpFcs+$30);
end;
{--------------------------------------------------------------------------}
Function TForm1.CheckCRC(sStr:PChar;iLength :Integer): Boolean;
var cFcs1, cFcs2: Char;
begin
result:= FALSE;
CalcCRC(@sStr[0], iLength, cFcs1, cFcs2);
if (cFcs1 = sStr[67]) and (cFcs2 = sStr[68]) then
Result := TRUE;
end;
{--------------------------------------------------------------------------}
procedure TForm1.Panel1Click(Sender: TObject);
begin
//Memo2 gelen DM bilgilerini ekranda göstermek için kullanılır.
//LED panele tıklayınca açılır.
memo2.Visible := NOT memo2.Visible;
label4.Visible := NOT label4.Visible;
end;
end.
Kod: Tümünü seç
object ComPort1: TComPort
BaudRate = br9600
Port = 'COM1'
Parity.Bits = prEven
StopBits = sbTwoStopBits
DataBits = dbSeven
Events = [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR,
evError, evRLSD, evRx80Full]
FlowControl.OutCTSFlow = False
FlowControl.OutDSRFlow = False
FlowControl.ControlDTR = dtrDisable
FlowControl.ControlRTS = rtsDisable
FlowControl.XonXoffOut = False
FlowControl.XonXoffIn = False
Left = 112
Top = 16
end
Eğer AsyncPro bileşenleri kullanılacak ise... aşağıdaki fonksiyonu ekleyin.
Kod: Tümünü seç
procedure TForm1.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var LastCount,I : integer;
begin
LastCount:= Count;
for I := 1 to LastCount do
begin
cRcvBuffer[CharCntReceived]:= ApdComPort1.GetChar;
inc(CharCntReceived);
end;
end;
ve
Kod: Tümünü seç
ApdComPort1.OutPut := '@00RD0000001552*'+#13+#0;
//comport1.WriteStr('@00RD0000001552*'+#13+#0);
Kod: Tümünü seç
object ApdComPort1: TApdComPort
ComNumber = 1
Baud = 9600
Parity = pEven
DataBits = 7
StopBits = 2
TraceName = 'APRO.TRC'
LogName = 'APRO.LOG'
OnTriggerAvail = ApdComPort1TriggerAvail
Left = 32
Top = 32
end