coassoftwaresystems / delphi-modbus Goto Github PK
View Code? Open in Web Editor NEWDelphi ModbusTCP components
Delphi ModbusTCP components
Hello,
Delphi IdModbusClient.pas:
function WriteRegisters(const RegNo: Word; const RegisterData: array of Word): Boolean;
C++Builder IdModbusClient.hpp:
bool __fastcall WriteRegisters(const System::Word RegNo, const System::Word *RegisterData, const int RegisterData_High);
When I use
System::Word myData[25];
// ..added values to myData and submit to register 1000 for 7 registers
WriteRegisters(1000, myData, 7);
I get on server side for "Count" instead of 7 a value of 8.
void __fastcall TForm1::IdModBusServer1WriteRegisters(const TIdContext *Sender, const int RegNr, const int Count, const TModRegisterData &Data, const TModBusRequestBuffer &RequestBuffer, BYTE &ErrorCode)
{
Caption = IntToStr(Count);
}
Why? Is this a bug?
UPDATE:
I think "RegisterData_High" means the last index for this "RegisterData"-array. Its not better to say here a Count? But that is now maybe not changeable without break exists code. So you can close this ticket. ;)
In line https://github.com/coassoftwaresystems/delphi-modbus/blob/develop/source/ModbusUtils.pas#L206 is ";" missing. So C++Builder compiler throws a error.
I need the Modbus client functionality within a service application.
Is delphi-modbus suitable for this?
I miss the required Copyright-Statement in the doc/source (https://www.mozilla.org/en-US/MPL/1.1/#exhibit-a).
Hello
Can someone tell me how many registers ReadHoldingRegisters function can read ?
I need to read a 440 registers block on SIEMENS PLC.
Was it possible in one read ?
Thanks for help.
Fred Mirande
Great tools, folks. Thank you! I am having a problem getting the components to show up in the Tool Palette. I load the DPK, compile both projects, install and it says it installs fine. If I check the packages under Options it shows up fine and lists both components, but neither component shows up in the Tool Palette. Any suggestions? This is in Berlin (10.1) and Tokyo (10.2) RAD Studio (using with C++).
For Delphi XE5 all platform identifiers in System.Classes:
{ Platform identifiers }
pidWin32 = $0001;
pidWin64 = $0002;
pidOSX32 = $0004;
pidiOSSimulator = $0008;
pidAndroid = $0010;
pidLinux32 = $0020;
pidiOSDevice = $0040;
pidWinNX32 = $0100;
But in ModBusPlatforms.inc witten pidOSX:
{$IFDEF DMB_DELPHIXE3}
[ComponentPlatformsAttribute(pidWin32 or pidWin64 or
{$IFDEF DMB_DELPHI10_2_TOKYO}
pidLinux32 or pidLinux64 or
{$ENDIF}
{$IFDEF DMB_DELPHI10_1_BERLIN}
pidiOSDevice32 or pidiOSSimulator32 or
pidAndroid32Arm or pidAndroid64Arm or
pidiOSDevice64 or pidiOSSimulator64 or
{$ELSE}
{$IFDEF DMB_DELPHIXE4}
pidiOSDevice or pidiOSSimulator or
{$ENDIF}
{$IFDEF DMB_DELPHIXE5}
pidAndroid or
{$ENDIF}
{$ENDIF}
{$IFDEF DMB_DELPHI10_3_RIO}
pidOSX32 or pidOSX64 or
{$ELSE}
pidOSX or // it is no correct for Delphi XE5
{$ENDIF}
0)] // Make statement complete with 0 (which is harmless)
{$ENDIF}
I installed the Modbus in Rio. I dropped the IdModbusClient component on a simple form. It gives this error:
[dcc32 Fatal Error] Unit3.pas(8): F2613 Unit 'IdModBusClient' not found.
Any suggestions?
Regards
Masoud Nasro
Hello, since RAD Studio 10 Seattle is now available the ModBusCompiler.inc must be updated.
The compiler version is VER300 (http://docwiki.embarcadero.com/RADStudio/Seattle/en/Compiler_Versions)
In my code I have added this temporary fix in order to compile the library:
{$IFDEF VER300}
{$DEFINE DMB_DELPHI1}
{$DEFINE DMB_DELPHI2}
{$DEFINE DMB_DELPHI3}
{$DEFINE DMB_DELPHI4}
{$DEFINE DMB_DELPHI5}
{$DEFINE DMB_DELPHI6}
{$DEFINE DMB_DELPHI7}
{$DEFINE DMB_DELPHI2005}
{$DEFINE DMB_DELPHI2006}
{$DEFINE DMB_DELPHI2007}
{$DEFINE DMB_DELPHI2009}
{$DEFINE DMB_DELPHI2010}
{$DEFINE DMB_DELPHIXE}
{$DEFINE DMB_DELPHIXE2}
{$DEFINE DMB_DELPHIXE3}
{$DEFINE DMB_DELPHIXE4}
{$DEFINE DMB_DELPHIXE5}
{$DEFINE DMB_DELPHIXE6}
{$DEFINE DMB_DELPHIXE7}
{$DEFINE DMB_DELPHIXE8}
{$DEFINE DMB_DELPHIXE8_ONLY}
{$ENDIF}
And in history.txt you have typo (nog):
Version 1.6.4 - June 17 - 2015
==============================
- Fix: TIdModbusServer did nog allow access to the last register of the
configured range (MaxRegister property).
- Added support for Delphi XE8.
Hi. How many registers can be read at once?
So far I can read up to 126 registers. Is this a limit or a bug in my program?
DelphiModbus2009.dpk says
requires
rtl,
IndyCore,
IndyProtocols,
IndySystem;
thats wrong. See http://www.indyproject.org/Sockets/Docs/Indy10Installation.de.aspx
D/CB/RAD 2009 is with extension 120, means IndyCore120 and so on.
I use ReadCoils to get coil message.
coil was 1,3,5,7 to be selected,but array feedback was 2,4,6,8
Please refer my code,has something wrong?
Var
iAmount: Integer;
i: Integer;
sLine: String;
myary :array[0..4096] of boolean;
begin
iAmount := StrToInt(edtReadAmount.Text);
if (iAmount > 0) then
begin
mctPLC.Host := edtIPAddress.Text;
if mctPLC.ReadCoils(iAmount,iAmount,myary) then begin
sLine := 'Register coil(s) read:';
for i := 0 to (iAmount - 1) do begin
sLine := sline+ #13#10' ' +
IntToStr(i) +':'+
BoolToStr(myary[i],True);
showmessage(sline);
end;
Does have Someone the Xe11 Alexandria Porting?
Thank you
Hello.
I installed the package and did a test project.
Error messages : undeclared identifier 'TIdModBusClient' at line.... and Cannot resolve unit name 'IdModBusClient' at line...
Anyone have an idea ?
Regards Geir
Hello,
I'm trying to use the TIdModBusClient component with a plc management software that communicates via MODBUS, I encounter problems in sending commands, I always receive an exception of DoResponseMismatch.
By debugging at the component level in the TIdModBusClient.SendCommand function, I receive data from the server but in the code step
{$ IFDEF DMB_INDY10}
iSize: = IOHandler.InputBuffer.Size;
IOHandler.ReadBytes (RecBuffer, iSize);
Move (RecBuffer [0], ReceiveBuffer, iSize);
the value of AModBusFunction that initially contains the correct code is reset to zero.
I do not understand where I'm wrong ...
Thanks for your help.
Hi.
On IdModBusServer, when we try read more than 112 coils; on PutCoilsIntoBuffer raise this exception
if (Length(data) < Count - 1) or (Length(data)=0) or (Count = 0) then begin raise exception.Create('PutCoilsIntoBuffer Data Length error '); end;
is this correct ? Is only 5 word read by time ?
Thank you
Just info:
Delphi 7, indy10
package DelphiModbus70; //DelphiModbus70.dpk Delphi 7, indy 10
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'Delphi Modbus components runtime package'}
{$RUNONLY}
{$IMPLICITBUILD ON} //change Delphi 7, indy 10
{$DEFINE FORCE_INDY10} //add Delphi 7, indy 10
requires
rtl,
//indy, //-remove delphi 7, indy 10
IndyCore70, //+add delphi 7, indy 10
IndyProtocols70, //+add delphi 7, indy 10
IndySystem70; //+add delphi 7, indy 10
contains
IdModbusClient in '..\source\IdModbusClient.pas',
IdModbusServer in '..\source\IdModbusServer.pas',
ModbusConsts in '..\source\ModbusConsts.pas',
ModbusTypes in '..\source\ModbusTypes.pas',
ModbusStrConsts in '..\source\ModbusStrConsts.pas',
ModbusUtils in '..\source\ModbusUtils.pas';
end.
package dclDelphiModbus70; //DelphiModbus70.dpk. Delphi 7, indy 10
{$R *.res}
{$R '..\source\ModbusReg.dcr'}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'Delphi Modbus components'}
{$DESIGNONLY}
{$IMPLICITBUILD ON} //change Delphi 7, indy 10
requires
rtl,
DelphiModbus70,
vcl,
designide,
vcljpg;
contains
ModbusReg in '..\source\ModbusReg.pas',
frm_About in '..\source\frm_About.pas' {frmAbout},
AboutComponentEditor in '..\source\AboutComponentEditor.pas';
end.
I use Panasonic PLC. When reading the value of a holding register with demo program, it is inconsistent with the actual value. For example, I read the value of register number 3002 and actually returned the value of register number 3001.、
Change the statement at the ‘problem‘ tag to ‘RegNumber := ARegNumber;‘ Post problem solving:
function TIdModBusClient.SendCommand(const AModBusFunction: TModBusFunction; const ARegNumber: Word; const ABlockLength: Word; var Data: array of Word): Boolean;
var
SendBuffer: TModBusRequestBuffer;
ReceiveBuffer: TModBusResponseBuffer;
BlockLength: Word;
RegNumber: Word;
dtTimeOut: TDateTime;
{$IFDEF DMB_INDY10}
Buffer: TIdBytes;
RecBuffer: TIdBytes;
iSize: Integer;
{$ENDIF}
begin
{$IFDEF DMB_INDY10}
CheckForGracefulDisconnect(True);
{$ELSE}
CheckForDisconnect(True, True);
{$ENDIF}
SendBuffer.Header.TransactionID := GetNewTransactionID;
SendBuffer.Header.ProtocolID := MB_PROTOCOL;
{ Initialise data related variables }
RegNumber := ARegNumber - FBaseRegister; //--------problem--------//
{ Perform function code specific operations }
Hi,
We ran into a issue (using Indy10, Delphi 2007) where our application was crashing to desktop and discovered there can be an overflow in
IdModbusClient
Move(RecBuffer[0], ReceiveBuffer, iSize)
if the server responds with too much data on the input buffer since MBPData is a fixed size but the client doesn't check if the amount of data returned will fit into the recievebuffer.
For my purposes I've added a simple size check and thrown away the rest of the buffer in that cycle and that's stopped the overflow (and random CTD) here.
I tried an application that uses a Modbus client using Port = 503. Reading and writing data using the Modbus master example and a couple of other Modbus master simulators from the WEB, the results were 100% correct. When I moved the application to the field to use it with a Modbus master module from the Honeywell DCS an error arose saying that the client is not available.
Questions to identify the problem: Shall the Nagel protocol be enabled in this case?; If the MB Client uses the UnitID as 255 (disabled), but if the Honeywell system sends a message using an ID 1 (for example), the Modbus client's response will use the same ID received from the master (an echo of the ID received) or the slave will change it? ... I am supposing here that the ID represents the Node Address.
Read coils and Read Discrete Inputs should be able to return up to 2000 registers with one request.
idModbusServer only returns the first 125 registers.
I beleave that the problem is in the InternalReadCoils and in the InternalReadInputBits methods.
Both methods at the end have this statement:
for i := 0 to (Count - 1) do
begin
if CoilData[i] then
Data[i] := 1;
end;
CoilData is of type TModCoilData (array of 2000 ByteBool) but Data is of type TModRegisterData (array of 125 words).
So when i>125 the statement fails.
Is there any Version that is working on Delphi 10.4?
Thanks in advance!
I downloaded the package version 1.7.0, followed the instructions and the objects are available in the palette bar in Delphi Rio 10.3.1. To run the Master demo program, I compiled the application without errors and it runs perfectly. But it doesn't connect to the client sending a message saying that the reading has failed, without details. I tried reading and writing using other software and there were no problems. How can I diagnose the problem of no connection at runtime?
When reading two or more different register blocks for one dataset and a timeout on a reading occurs then you get the data from the previous block for all the following readings. This is due to the inputbuffer is not cleared. It should be considered to clear the input buffer in all the read procedures.
This code from production show how we do from now on.
function TModBusCom.ReadInputRegisters(RegisterStart, Count: Word): Boolean;
begin
Result := False;
try
// Avoid reading previous data after a read timeout
if FmbClient.Connected then
FmbClient.IOHandler.InputBuffer.Clear;
Result := FmbClient.ReadInputRegisters(RegisterStart, Count, FRegisterData);
except
on E: EIdException do
ModBusError(ModBus_etIndyException, ModBus_ftNotUsed, E.Message);
end;
if Result then
ParseData(mbfReadInputRegs, RegisterStart, Count);
end;
Hello,
My application use the ReadHoldingRegisters function and one time per day, it crashes in this function
procedure TIdModBusClient.DoResponseMismatch(const RequestFunctionCode: Byte;
const ResponseFunctionCode: Byte; const ResponseBuffer: TModBusResponseBuffer);
begin
if Assigned(FOnResponseMismatch) then
FOnResponseMismatch(RequestFunctionCode, ResponseFunctionCode, ResponseBuffer);
end;
and it comes from
if ((AModBusFunction or $80) = ReceiveBuffer.FunctionCode) then
DoResponseError(AModBusFunction, ReceiveBuffer.MBPData[0], ReceiveBuffer)
else
DoResponseMismatch(AModBusFunction, ReceiveBuffer.FunctionCode, ReceiveBuffer);
Result := False;
How could i do solve it?
I use v 1.7.0 and delphi 10.2
Thanks
In its constructor, TIdModBusServer
creates a TCriticalSection
, assigns it to FLogCriticalSection
but never destroys it.
The client code cuts the request silently without generating exception or error code.
Aside from this, the limits are too small. See attached patch
Apologies, this is probably the wrong place for this...
To compile for 10.2 Tokyo, need to add a {$IFDEF VER320} in the ModBusCompiler.inc file.
I just copied the VER310 section.
Compiles and installs fine, and on very quick testing works as well.
Hi,
I have converted your Delphi Slave demo (Indy10) to Lazarus (Version 2.2.0 64bit on Windows 10).
I am sending 32-bit values from PLC to TIdModBusServer by using 16-PresetMultipleRegisters method.
For the sake of debugging, I have modified the code of your demo as follows (added logging to mmoErrorLog):
procedure TfrmMain.msrPLCWriteRegisters(const Sender: TIdContext;
const RegNr, Count: integer; const Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer; var ErrorCode: byte);
var
i: integer;
begin
mmoErrorLog.Lines.Add('Message register = ' + IntToStr(RegNr) +
'; Message length= ' + IntToStr(Count));
for i := 0 to (Count - 1) do
begin
SetRegisterValue(RegNr + i, Data[i]);
mmoErrorLog.Lines.Add('Message value ' + IntToStr(i) + ' = ' + IntToStr(Data[i]));
end;
end;
I sent the values 3 and 7993, and this is what I get in the ErrorLog:
Message register = 11; Message length= 2
Message value 0 = 3
Message value 1 = 7993
Message register = 11; Message length= 2
Message value 0 = 0
Message value 1 = 7993
As you can see, the event gets triggered twice, where the second one contains a wrong value (0 instead of 3).
Any solution to this problem?
Hello,
Using Delphi 10.2 with 1.6.7 version of the library. I have Indy 10.6.2.5366 installed.
I am using Indy10 ModbusMaster demo application to test a connection and I constantly receive socket error 10061 connection refused
.
I have installed Modbus Slave application of Witte Software in demo mode to make a test connection and that application can connect to PLC device just fine on same computer and apparently same settings.
Is there any known issues with siemens PLC devices?
Thanks.
How can we use this component to connect to modbus sensor. Bindings are readonly, adding IP at adding at runtime is readonly ? Shows registers on localhost which is not modbus client ? Any howto exists ?
I have a strange issue. Compile with C++Builder 10.1 I get this error:
[dcc32 Fehler] dclDelphiModbus101Berlin.dpk(33): E2029 'END' erwartet, aber Bezeichner 'rrequires' gefunden
Rad Studio 10.1 show me this
package dclDelphiModbus101Berlin;
{$R *.res}
{$R '..\source\ModbusReg.dcr'}
.....rrequires
rtl,
DelphiModbus101Berlin,
vcl,
designide,
xmlrtl,
vclactnband,
vclx,
vclimg;ocontains
ModbusReg in '..\source\ModbusReg.pas',
frm_About in '..\source\frm_About.pas' {frmAbout},
AboutComponentEditor in '..\source\AboutComponentEditor.pas',
ModbusSplash in '..\source\ModbusSplash.pas';d.
I open that file in a texteditor and see this:
package dclDelphiModbus101Berlin;
{$R *.res}
{$R '..\source\ModbusReg.dcr'}
.....requires
rtl,
DelphiModbus101Berlin,
vcl,
designide,
xmlrtl,
vclactnband,
vclx,
vclimg;contains
ModbusReg in '..\source\ModbusReg.pas',
frm_About in '..\source\frm_About.pas' {frmAbout},
AboutComponentEditor in '..\source\AboutComponentEditor.pas',
ModbusSplash in '..\source\ModbusSplash.pas';end.
What happen here? In texteditor is "requires", "contains" "end." correct. This problem happen every time I open this project and want install the components.
Hello,
I installed the package for delphi 10.4, it's OK.
But when i use client on my form, the programm build with no error, and at the beginning of run i have an error runtime 216.
I tried some solutions, but always this error.
The same code compiled with delphi 10.2 and modbus V1.6.7 is running without error.
Thanks
In Rad Studio 2009 (C++Builder) I get this error (german):
E2466 Ein 'Never-build' Package '.DelphiModbus2009' benötigt 'always-build' Package 'IndySystem120'
See http://docwiki.embarcadero.com/RADStudio/Berlin/en/E2466_Never-build_package_%27%25s%27_requires_always-build_package_%27%25s%27_(Delphi)
To fix this, I change in files DelphiModbus2009.dpk and dclDelphiModbus2009.dpk
{$IMPLICITBUILD OFF} to {$IMPLICITBUILD ON}
See http://docwiki.embarcadero.com/RADStudio/Berlin/en/Implicit_Build_(Delphi)
Hello,
I'm using the last version (1.6.5) with delphi XE8 + Indy 10 and I don't know why but the communication stops working (in a read request). I wasn't able to pin point exactly the problem, but when I stop the debugger a "Socket error 10004 Interrupted system call" is raised by the TIdIOHandler.ReadFromSource function. And althought I set a Read Timeout of 4s it doesn't seem to be working (even though the timeout parameter is correctly set inside the function).
I'd like to know if someone already experienced this and how could I handle it.
Thanks.
P.S.: tested on windows 7 - x64.
I installed the Modbus package using the pkg file. When I compile an existing app. with Rio there is an error saying
[dcc32 Error] IdModbusServer.pas(76): E2003 Undeclared identifier: 'TIdPeerThread'
If I compile the same project with Delphi 10.2 this error is not shown. What is missing?
I can connect to the controler via TCP/IP and read the registry, but i would like to read registry from the subnet of that device (that device is a panel with modbus ID:1 and i have thermostat connected via zigbee using modbus with different ID ex: 253,252,251,250,etc...) how can i read the registry of a modbus subnet ID:253 with this stack ?
Hello, since RAD Studio 10.1 Berlin is now available the ModBusCompiler.inc must be updated.
The compiler version is VER310 (http://docwiki.embarcadero.com/RADStudio/en/Compiler_Versions)
In my code I have added this temporary fix in order to compile the library:
{$IFDEF VER310}
{$DEFINE DMB_DELPHI1}
{$DEFINE DMB_DELPHI2}
{$DEFINE DMB_DELPHI3}
{$DEFINE DMB_DELPHI4}
{$DEFINE DMB_DELPHI5}
{$DEFINE DMB_DELPHI6}
{$DEFINE DMB_DELPHI7}
{$DEFINE DMB_DELPHI2005}
{$DEFINE DMB_DELPHI2006}
{$DEFINE DMB_DELPHI2007}
{$DEFINE DMB_DELPHI2009}
{$DEFINE DMB_DELPHI2010}
{$DEFINE DMB_DELPHIXE}
{$DEFINE DMB_DELPHIXE2}
{$DEFINE DMB_DELPHIXE3}
{$DEFINE DMB_DELPHIXE4}
{$DEFINE DMB_DELPHIXE5}
{$DEFINE DMB_DELPHIXE6}
{$DEFINE DMB_DELPHIXE7}
{$DEFINE DMB_DELPHIXE8}
{$DEFINE DMB_DELPHI10_SEATTLE}
{$DEFINE DMB_DELPHI10_1_BERLIN}
{$DEFINE DMB_DELPHI10_1_BERLIN_ONLY}
{$ENDIF}
I didn't do a Pull Request because I'm not sure if you want to use DMB_DELPHI10_1_BERLIN or DMB_DELPHI101_BERLIN (no underscore before the 1).
Is it possible to catch this message? I get this message in client, which read register periodicaly, but server is switched off.
I had a bit trouble to install delphi-modbus in lazarus.
(delphimodbuslazarus.pas(10,5) Fatal: Kann IdModBusClient nicht finden)
Finally i fixed it by renaming the source files to lower case letters and a modified delphimodbuslazarus.lpk.
Details:
System:
OS: Xubuntu 18.10 x86_64
CPU: AMD E-450 APU with Radeon(tm) HD Graphics
FPC: 3.0.4
Lazarus: 1.8.4
Indy10: indylaz.lpk 10.6.2.5468
dclDelphiModBus102Tokyo can not build to a win 64 bpl.
It can not find designide etc
why?
The component installed just fine, however when I run the test slave example, I get an an exception. It fails in the msrPLCReadHoldingRegisters procedure because the Count variable is huge. If I remove the event in the form designer and try to add it again. I get an error that reads "Property and method msrPLCReadHoldingRegisters are not compatible." Is this a bug or am I implementing it incorrectly?
I recommend adding a length control on GetRegistersFromBuffer
and PutRegistersIntoBuffer
to avoid an unhandled exception.
The solution I implemented was:
if (Length(data) < Count - 1) or (Length(data)=0) or (Count = 0) then
begin
raise exception.Create('GetRegistersFromBuffer Data Length error ');
end;
Example :
procedure GetRegistersFromBuffer(const Buffer: PWord; const Count: Word; var Data: array of Word);
var
WPtr: PWord;
i: Word;
begin
WPtr := Buffer;
if (Length(data) < Count - 1) or (Length(data)=0) or (Count = 0) then
begin
raise exception.Create('GetRegistersFromBuffer Data Length error ');
end;
for i := 0 to (Count - 1) do
begin
Data[i] := Swap16(WPtr^);
Inc(WPtr);
end;
end;
Thanks for the component
Event OnWriteRegisters fires up in separate (not main) thread so update of string grid (sgdRegisters) should not be processed here.
procedure TfrmMain.msrPLCWriteRegisters(const Sender: TIdContext;
const RegNr, Count: Integer; const Data: TModRegisterData;
const RequestBuffer: TModBusRequestBuffer);
var
i: Integer;
begin
for i := 0 to (Count - 1) do
SetRegisterValue(RegNr + i, Data[i]); // problem: call of VCL method in background thread
end;
procedure TfrmMain.SetRegisterValue(const RegNo: Integer; const Value: Word);
...
begin
...
sgdRegisters.Cells[1, Index + 1] := IntToStr(Value); // VCL is not threadsafe
...
end;
procedure TfrmMain.btnWriteClick(Sender: TObject);
var iAmount: Integer; Data: array[0..4096] of Boolean; i: Integer;
begin
mctPLC.Host := edtIPAddress.Text;
iAmount := StrToInt(edtReadAmount.Text);
if CheckBox1.Checked then Data[0] := True else Data[0] := False;
if CheckBox2.Checked then Data[1] := True else Data[1] := False;
if CheckBox3.Checked then Data[2] := True else Data[2] := False;
if CheckBox4.Checked then Data[3] := True else Data[3] := False;
if CheckBox5.Checked then Data[4] := True else Data[4] := False;
if CheckBox6.Checked then Data[5] := True else Data[5] := False;
if CheckBox7.Checked then Data[6] := True else Data[6] := False;
if CheckBox8.Checked then Data[7] := True else Data[7] := False;
if mctPLC.WriteCoils(StrToInt(edtWriteReg.Text), iAmount, Data) then
Label6.Caption := 'PLC Write Success!' else Label6.Caption := 'PLC Write Not Success!';
But not success. What is the problem?
IdModBusServer.patch.txt
I suggest patch for it.
This is possible a RAD Studio 2009 (C++Builder) compiler bug, in Rad Studio Berlin its working fine. I add this ticket only for Google. Compile a project with TIdModBusServer, I get two errors:
[BCC32 Error] IdModBusServer.hpp(120): E2370
[BCC32 Error] IdModBusServer.hpp(121): E2370
Line 120: __property TModBusCoilWriteEvent OnWriteCoils = {read=FOnWriteCoils, write=FOnWriteCoils};
Line 121: __property TModBusRegisterWriteEvent OnWriteRegisters = {read=FOnWriteRegisters, write=FOnWriteRegisters};
A maybe workaround is, to move this two lines in header-file in the next public: section. After this I can compile the project without a error. I can't tell the reason, but here is maybe a problem with convertion fixed-size arrays?
I'm able to read register values without any problem, but I'm not able to write to the register values.
mctPLC.WriteRegister is returning False because TIdModBusClient.SendCommand is returning False
IOHandler.ReadBytes(RecBuffer, iSize); is setting ReceiveBuffer.FunctionCode to 134 but it needs to be equal to AModBusFunction which is 6
I get the same result with the compiled demos as I do when I compile them myself.
Hi. I need to read the value of ReadHolding registers cyclically. I have tried to do this with the Timer. This works but makes the application very slow. How to do it correctly?
Hi,
I have a problem for installing the Modbus package under a RAD Studio 10.1 Berlin (Starter edition -> only C++Builder 10.1 Berlin , not Delphi): I cannot do the installation as I don't have the Delphi Berlin.
The RAD ide complains with the "Delphi.Personality".
I try to use dcc32 comand line but I am not at all an expert and I fail.
Any chance to have somebody to compile the designtime and the runtime in "bpl" packages for C++Builder Berlin 10.1? I will appreciate a lot.
Thanks
Best Regards
Olivier
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.