使用 PHP 从 RS485 modbus 获取响应

问题描述 投票:0回答:1

我正在尝试使用以下脚本从我使用 PHP 发送到 RS485 设备的命令中获取响应:

<?php
class rapidserial{
  function _blocking($device,$mode){
      stream_set_blocking($device, $mode);
      return true;
     }
  }
$rapidserial = new rapidserial();
$device = "COM3";
shell_exec("mode $device BAUD=9600 PARITY=n DATA=8 STOP=2 xon=off octs=off rts=off"); 
$comport = fopen($device, "r+b");
if ($comport === false)
    {
    die("Failed opening com port<br/>");
    }
    else
    {
    echo "Com Port Open<br/>"; 
    }
//Set non-blocking mode for writing
$rapidserial->_blocking($comport,0);
$atcmd = "\x0A\x04\x00\x00\x00\x49\x30\x87"; //
fputs($comport, $atcmd);
usleep(2000);
// Set blocking mode for reading
$rapidserial->_blocking($comport,1);
echo 'Response:';
$res = fgets($comport, 4017);
var_dump ($res);
fclose($comport);
?>

这取自我在这里发表的相关帖子:https://superuser.com/questions/1815811/issue-addressing-modbus-via-rs485-and-php-on-windows在那里我被帮助发送了命令,帮助我的人提供的脚本有效。现在我尝试发送命令并获取响应,但它不起作用,响应为空。

我也尝试过使用https://github.com/toggio/PhpSerialModbus但它告诉我“无法打开设备”。

我知道我可以与设备通信,因为如果我使用某些 modbus 软件,我可以发送命令并获取响应。 enter image description here

更新:所以我已经从 Windows 设备转移到 Linux 设备来执行此操作,现在我在 PHP 中使用不同的 modbus 类取得了一些成功(https://github.com/toggio/PhpSerialModbus),但是问题是我没有收到所有返回的数据,它似乎被截断了,即使我尝试进一步请求寄存器(不是从零开始),我也没有收到我期望的所有数据。我知道它在那里,因为如果我使用如图所示的 modbus 软件,我可以看到它。

我的代码现在看起来像这样:

<?php
include("/var/www/html/PhpSerialModbus.php");
$modbus = new PhpSerialModbus();
$modbus->deviceInit('/dev/ttyUSB0',9600,'none',8,2,'none');
$modbus->deviceOpen();
$modbus->debug = false;
$rawquery="\x0A\x04\x00\x00\x00\x49\x30\x87";
$modbus->sendRawQuery($rawquery.$modbus->crc16($rawquery),false);
$result=$modbus->getResponse(true);
function hex2float($strHex) {
    $hex = sscanf($strHex, "%02x%02x%02x%02x%02x%02x%02x%02x");
    $bin = implode('', array_map('chr', $hex));
    $array = unpack("Gnum", $bin);
    return $array['num'];
}
$bin_result = bin2hex($result);
$bin_result = chunk_split($bin_result, 2, ',');
$bin_result = substr($bin_result, 9);
$myresults = print_r($bin_result, true);
$final_array = explode(",", $myresults);
print_r ($final_array);
?>

这给了我这个:

[0] => 42
[1] => 48
[2] => 33
[3] => 33
[4] => 43
[5] => d3
[6] => 92
[7] => 00
[8] => 43
[9] => 75
[10] => 54
[11] => 86
[12] => 40
[13] => 66
[14] => 66
[15] => 72
[16] => be
[17] => dc
[18] => 7a
[19] => de
[20] => 44
[21] => 5c
[22] => f0
[23] => 0a
[24] => 44
[25] => 34
[26] => 50
[27] => 09
[28] => 42
[29] => f2
[30] => cc
[31] => cd
[32] => be
[33] => f9
[34] => db
[35] => 24
[36] => 40
[37] => 25
[38] => c2
[39] => 8f
[40] => 42
[41] => 06
[42] => cc
[43] => cd
[44] => 42
[45] => 90
[46] => 00
[47] => 07
[48] => 42
[49] => ef
[50] => 99
[51] => 9a
[52] => 43
[53] => d3
[54] => 51
[55] => 65
[56] => 43
[57] => 73
[58] => c2
[59] => 9b
[60] => 40
[61] => 80
[62] =>
php serial-port modbus rs485
1个回答
0
投票

PhpSerialModbus.php执行的读取循环是:

while( ($byte = $this->serial->ReadPort()) && ((microtime(true)-$startTime)<3.0)) {
    $responseString=$responseString.$byte;
    usleep(50);
}

它有问题:它只等待 50 微秒,这太短了。没有额外的数据 足够的时间到达并且循环提前终止。也许开发者的意思是 50 毫秒, 所以你可以像这样改变它:

    usleep(50000);

如果您不想更改 PhpSerialModbus.php,您可以在代码中执行以下操作:

$result = $modbus->getResponse(true);
do
{
    usleep(50000);
    $data = $modbus->getResponse(true);
    $result .= $data;
}
while($data);
© www.soinside.com 2019 - 2024. All rights reserved.