aldas / modbus-tcp-client

PHP client for Modbus TCP and Modbus RTU over TCP (can be used for serial)
Apache License 2.0
191 stars 55 forks source link

Question about data types #143

Closed maltsaar closed 1 year ago

maltsaar commented 1 year ago

Sorry in advance if this a stupid question.

I'm trying to read an input register from my inverter. The documentation says that the data type that it returns is an Uint32. However when I run:

$binaryData = $connection->connect()->sendAndReceive($packet);
$response = ResponseFactory::parseResponseOrThrow($binaryData);

foreach ($response as $word) {
    print_r(get_class_methods($word));
}

I basically see that I can only get: [0] => getInt16 [1] => getUInt16

When I try either of those the data doesn't seem to make any sense. When I'm getting a register that returns UInt16 for example everything seems to work fine.

How would I be able to get the data to return as UInt32 in this context?

Environment:

aldas commented 1 year ago

Hi,

You are seeying getInt16 and getUInt16 because ReadHoldingRegistersResponse implement iterator this way

https://github.com/aldas/modbus-tcp-client/blob/09bd467b9821d394f4b29f5bf5b0984c005fbdb0/src/Packet/ModbusFunction/ReadHoldingRegistersResponse.php#L163-L166

meaning

foreach ($response as $word) {
    print_r(get_class_methods($word));
}

will return Word class instances which represent 16bit / 2 byte long data.

If you want to access 32bit / double word fields you can do

https://github.com/aldas/modbus-tcp-client/blob/09bd467b9821d394f4b29f5bf5b0984c005fbdb0/examples/fc3.php#L45-L48

on:

aldas commented 1 year ago

https://github.com/aldas/modbus-tcp-client/blob/master/examples/index.php this example is handy for debugging different data types and has overview how different types can be accessed

https://github.com/aldas/modbus-tcp-client/blob/09bd467b9821d394f4b29f5bf5b0984c005fbdb0/examples/index.php#L86-L99

aldas commented 1 year ago

If you are seeing strange numbers returned by getUInt32 you might want to try different Endians (Default is BIG_ENDIAN_LOW_WORD_FIRST)

    print_r($responseWithStartAddress->getDoubleWordAt($myAddress)->getUInt32(Endian::LITTLE_ENDIAN));
    print_r($responseWithStartAddress->getDoubleWordAt($myAddress)->getUInt32(Endian::LITTLE_ENDIAN | self::LOW_WORD_FIRST));
maltsaar commented 1 year ago

@aldas Thanks for the very detailed response! I got it to work now.