Closed newfaboc closed 2 years ago
Address 32004
means that it should be requested with FC3 (Read Holding Registers) and from address 2004
Address 40003
means that FC4 should be used and set the start address as 3
.
examples/index.php
is using FC3 for request but you can change it to FC4 by
$packet = new ReadHoldingRegistersRequest($startAddress, $quantity, $unitId);
to
$packet = new ReadInputRegistersRequest($startAddress, $quantity, $unitId);
NB: make sure to import that class also use ModbusTcpClient\Packet\ModbusFunction\ReadInputRegistersRequest;
I assume that 40003
is int8
type as that value may contain negative values. 40004
and 40005
are probably uint8
only positive values.
This is modified version of examples/fc4.php
<?php
use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ModbusFunction\ReadInputRegistersRequest;
use ModbusTcpClient\Packet\ModbusFunction\ReadInputRegistersResponse;
use ModbusTcpClient\Packet\ResponseFactory;
require __DIR__ . '/../vendor/autoload.php';
$connection = BinaryStreamConnection::getBuilder()
->setPort(502)
->setHost('127.0.0.1')
->build();
$startAddress = 3;
$quantity = 3;
$packet = new ReadInputRegistersRequest($startAddress, $quantity);
echo 'Packet to be sent (in hex): ' . $packet->toHex() . PHP_EOL;
try {
$binaryData = $connection->connect()
->sendAndReceive($packet);
echo 'Binary received (in hex): ' . unpack('H*', $binaryData)[1] . PHP_EOL;
/**
* @var $response ReadInputRegistersResponse
*/
$response = ResponseFactory::parseResponseOrThrow($binaryData);
echo 'Parsed packet (in hex): ' . $response->toHex() . PHP_EOL;
echo 'Data parsed from packet (bytes):' . PHP_EOL;
print_r($response->getData());
// set internal index to match start address to simplify array access
$responseWithStartAddress = $response->withStartAddress($startAddress);
print_r($responseWithStartAddress[3]->getInt16()); // 40003
print_r($responseWithStartAddress[4]->getUInt16()); // 40004
print_r($responseWithStartAddress[5]->getUInt16()); // 40005
} catch (Exception $exception) {
echo 'An exception occurred' . PHP_EOL;
echo $exception->getMessage() . PHP_EOL;
echo $exception->getTraceAsString() . PHP_EOL;
} finally {
$connection->close();
}
NB: your images seems to reference CRC this is implies that RTU is used but I do not understand how in this case you can get valid response with examples/index.php
? Does it support TCP?
Bits of register can be checked with print_r($responseWithStartAddress[5]->isBitSet(15)); // is register 40005 bit 15 set?
Note if you need only 0-14 bits from register you can use (i could be wrong here. did not test this)
print_r($responseWithStartAddress[4]->getUInt16() & 0x7FFF); // get 0-14 bits of register 40004
NB: your images seems to reference CRC this is implies that RTU is used but I do not understand how in this case you can get valid response with examples/index.php? Does it support TCP? -> i think yes. Like the image of exampel fc3. I enter the ip address of plc and it is response.
I will try your advice. thank you very much aldas.
Have you an email ? i will send a document if you want to read it. Thank you aldas.
nope :) but try with FC3 and FC4 starting from address 0
. It could be that documentation has some copy-paste error and that 40001
maybe needs to be 30001
.
One thing that I forgot - when documents talk about 40001
it would mean that address 1
should be 0
in this library. Modbus docs usually reference addresses starting from 1
but in packet level addresses start from 0
so you need to subtract 1.
and this picture from index.php
seems ok to me. dunno if these 130 and 400 values are ok.
i have try the modified the example/fc4.php
Packet to be sent (in hex): 2f5d00000006040400030003 Binary received (in hex): 2f5d00000009040406433031325631 Parsed packet (in hex): 2f5d00000009040406433031325631 Data parsed from packet (bytes): Array ( [0] => 67 [1] => 48 [2] => 49 [3] => 50 [4] => 86 [5] => 49 ) responseWithStartAddress[3] -> 17200 responseWithStartAddress[4] -> 12594 responseWithStartAddress[4] -> 22065
i have send after 1 minute but the "print_r" still same result but the Packet and Binary 2f5d.. always different (4 digit first ). i dont know how to read this. because i see the chiller the temperature "water in -> 11.2 C" and "the water out about -> 14.4 C".
May you help me ? what should next i do ?
modified version of
examples/fc4.php
dec 22065 -> hex 0x56 0x31-> binary 0101 0110 0011 0001 <-- does not seem to have 15th bit as 1
assuming that 15th bit shows if value is valid then you need to get 0-14 bits. Try this.
print_r($responseWithStartAddress[3]->isBitSet(15)); // is register 40003 valid?
print_r($responseWithStartAddress[3]->getUInt16() & 0x7FFF); // 40003 first 14 bits
print_r($responseWithStartAddress[4]->getUInt16() & 0x7FFF); // 40004 first 14 bits
print_r($responseWithStartAddress[5]->getUInt16() & 0x7FFF); // 40005 first 14 bits
print_r($responseWithStartAddress[3]->isBitSet(15)); // is register 40003 valid? print_r($responseWithStartAddress[3]->getUInt16() & 0x7FFF); // 40003 first 14 bits print_r($responseWithStartAddress[4]->getUInt16() & 0x7FFF); // 40004 first 14 bits print_r($responseWithStartAddress[5]->getUInt16() & 0x7FFF); // 40005 first 14 bits
Packet to be sent (in hex): 293e00000006040400030003 Binary received (in hex): 293e00000009040406433031325631 Parsed packet (in hex): 293e00000009040406433031325631 Data parsed from packet (bytes): Array ( [0] => 67 [1] => 48 [2] => 49 [3] => 50 [4] => 86 [5] => 49 ) isvalid -> responseWithStartAddress[3] -> 17200 responseWithStartAddress[4] -> 12594 responseWithStartAddress[5] -> 22065
the value of "print_r($responseWithStartAddress[3]->isBitSet(15)); // is register 40003 valid? " --> empty
I have no idea. Maybe it is endianess. By default we use big endian but maybe these values are in Little endian.
This is same thing with little endian
// should be added after reuires statements
Endian::$defaultEndian = Endian::LITTLE_ENDIAN;
or
print_r($responseWithStartAddress[3]->getUInt16(2) & 0x7FFF); // 40003 first 14 bits
print_r($responseWithStartAddress[4]->getUInt16(2) & 0x7FFF); // 40004 first 14 bits
print_r($responseWithStartAddress[5]->getUInt16(2) & 0x7FFF); // 40005 first 14 bits
print_r($responseWithStartAddress[3]->getUInt16(2) & 0x7FFF); // 40003 first 14 bits print_r($responseWithStartAddress[4]->getUInt16(2) & 0x7FFF); // 40004 first 14 bits print_r($responseWithStartAddress[5]->getUInt16(2) & 0x7FFF); // 40005 first 14 bits
i have try this and the result is : responseWithStartAddress[3] -> 0 responseWithStartAddress[4] -> 0 responseWithStartAddress[5] -> 0
but if i use big endian the code of this.. the result is : responseWithStartAddress[3] -> 12355 responseWithStartAddress[4] -> 12849 responseWithStartAddress[5] -> 12630
what it means ? I dont know why i have send again after several time it doesnt change.
no idea but try FC3 also with same addresses ($startAddress = 0; $quantity = 3). with and without little endian.
print_r($responseWithStartAddress[0]->getUInt16(2) & 0x7FFF); // 40003 first 14 bits / little endian
print_r($responseWithStartAddress[1]->getUInt16(2) & 0x7FFF); // 40004 first 14 bits
print_r($responseWithStartAddress[2]->getUInt16(2) & 0x7FFF); // 40005 first 14 bits
print_r($responseWithStartAddress[0]->getUInt16(1) & 0x7FFF); // 40003 first 14 bits / big endian
print_r($responseWithStartAddress[1]->getUInt16(1) & 0x7FFF); // 40004 first 14 bits
print_r($responseWithStartAddress[2]->getUInt16(1) & 0x7FFF); // 40005 first 14 bits
print_r($responseWithStartAddress[0]->getUInt16(2) & 0x7FFF); // 40003 first 14 bits / little endian print_r($responseWithStartAddress[1]->getUInt16(2) & 0x7FFF); // 40004 first 14 bits print_r($responseWithStartAddress[2]->getUInt16(2) & 0x7FFF); // 40005 first 14 bits print_r($responseWithStartAddress[0]->getUInt16(1) & 0x7FFF); // 40003 first 14 bits / big endian print_r($responseWithStartAddress[1]->getUInt16(1) & 0x7FFF); // 40004 first 14 bits print_r($responseWithStartAddress[2]->getUInt16(1) & 0x7FFF); // 40005 first 14 bits
the result is with FC4: little endian : responseWithStartAddress[0] -> 256 responseWithStartAddress[1] -> 25600 responseWithStartAddress[2] -> 16717 Big Endian : responseWithStartAddress[0] -> 1 responseWithStartAddress[1] -> 100 responseWithStartAddress[2] -> 19777
the result is with FC3: little endian : responseWithStartAddress[0] -> 256 responseWithStartAddress[1] -> 256 responseWithStartAddress[2] -> 512 Big Endian : responseWithStartAddress[0] -> 1 responseWithStartAddress[1] -> 1 responseWithStartAddress[2] -> 130
the value doesnt change after i send 1 minute.
hi aldas,
after i change From "print_r($responseWithStartAddress[3]->isBitSet(15)); // is register 40003 valid?
"
to
print_r($responseWithStartAddress[3]->isBitSet(14)); // is register 40003 valid?
it return 1. it means 14 bit ?
You are correct. I got this part wrong. The method implementation can be seen here.
@newfaboc you got it working? can I close the issue?
yes. it works @aldas . Thank you very much.
Hi aldas, I'm a newbie for PLC. I have try modbus-tcp-lient and it sucess get the data. But i don't know how to read the data. I want read the temperature of chiller. i have read the document of modbus.
here is the part of the document (content ):
Data frame format
Input register (Function code 0x04 supported)
Holding register (Function code supported 0x03/0x06/0x10)
I want Get the value of the address 40003 , 40004, and 40005 (temperature of chiller).
may you help me ? what should i do to get it ?
Thank you