- Опубликовано 25.12.2017 02:52
- Просмотров: 8833
Работаем с COM портом RS-232 напрямую из PHP для Peacefair pzem-004t
Иногда встречаются экзотические ситуации, когда приходиться работать напрямую с оборудованием используя языки программирования, совсем не предназначенные для этого, как например взаимодействие c COM портом в PHP. Некоторые скажут, что это невозможно, более продвинутые будут использовать посредников, эстеты предпочтут стороннюю библиотеку.
На самом деле всё не так страшно, и я опишу как взаимодействовать c COM RS-232 из PHP без сторонних библиотек и посредников в Linux, на примере вольтметра-амперметра Peacefair pzem-004t.
Сразу оговорюсь, что использовать PHP для работы с оборудованием по протоколу RS-232 далеко не самая лучшая затея, и для этого более предпочтительно использовать, например, C. Но если очень надо, то почему бы и нет?
Небольшое отступление касательно самого Peacefair pzem-004t, это вольтметр-амперметр для измерения параметров электрической сети 220В.
Обмен данными с устройством происходит по протоколу RS-232 TTL, это обычный COM порт, но только не с уровнями +12В -12В, а +5V либо +3.3В (чаще), в зависимости от реализации устройства.
В случае Peacefair pzem-004t TTL уровни +3.3В, однако доп питание +5В.
Для того чтобы подключить подобное устройство достаточно USB-TTL конвертора.
В системе такое устройство будет отображаться как обычный последовательный порт.
Рис. 4.
Ну да мы отвлеклись, работать я буду в консоли Linux на Raspberry Pi 3.
Собственно, простой код, который вы можете в последствии трансформировать в что-то более серьёзное.
<?php
$dev = '/dev/ttyUSB0';
function dev($dev, $tx){
exec("stty -F $dev 9600 raw -echo");
if ($handle = fopen($dev, "r+")){
fwrite($handle, $tx);
$rx = fread($handle, 7 );
fclose($handle);
//echo bin2hex($rx).PHP_EOL;
if (check($rx) === true)
return $rx;
else
return false;
}
else
return false;
}
function check($in){
$arr = str_split(bin2hex($in),2);
$summ = 0;
for ($i = 0; $i <= 5; $i++)
$summ += hexdec($arr[$i]); //hex to dec
if (substr(dechex($summ),-2) == $arr[6]) //last 2 chr. from hex
return true;
else
return false;
}
//voltage
$arr = str_split(bin2hex(dev($dev,hex2bin('B0C0A80101001A'))),2);
$voltage = hexdec($arr[1].$arr[2]) + hexdec($arr[3])/10;
//current
$arr = str_split(bin2hex(dev($dev,hex2bin('B1C0A80101001B'))),2);
$current = hexdec($arr[2]) + hexdec($arr[3])/100;
//active
$arr = str_split(bin2hex(dev($dev,hex2bin('B2C0A80101001C'))),2);
$active = hexdec($arr[1].$arr[2]);
//energy
$arr = str_split(bin2hex(dev($dev,hex2bin('B3C0A80101001D'))),2);
$energy = hexdec($arr[1].$arr[2].$arr[3]);
echo 'Voltage:'.$voltage.PHP_EOL;
echo 'Current:'.$current.PHP_EOL;
echo 'Active:'.$active.PHP_EOL;
echo 'Energy:'.$energy.PHP_EOL;
?>
Разберём код по порядку:
/dev/ttyUSB0 – устройство с которым я буду работать,
dev($dev, $tx) – функция задачей которой будет принять аргументы: имя устройства и данные для отправки, после чего вернуть принятые данные.
exec("stty -F $dev 9600 raw -echo") – мы настраиваем работу порта, указывая 9600 – скорость , raw – входные и выходные данные передаются напрямую как есть, без обработки, -echo не пересылать себе переданные собой же данные.
Далее мы работаем с устройством как с обычным файлом
fwrite($handle, $tx) – передаём данные
fread($handle, 7 ) – принимаем данные, 7 – поскольку в моём случае на каждый посыл команды меня интересует ответ в 7-мь байт.
Дальнейший код больше относиться к особенностям pzem-004t.
Функйия check($in) – проверяет корректность принятых данных по контрольной сумме байтов с 0-6 которая должна быть равна 7-му. Особой необходимости в ней нет, но если производитель использует контроль целостности, то можно реализовать проверку.
Далее, я поочерёдно посылаю запросы (предварительно переведя их из hex в bin’арные данные) на устройство и принимаю данные для вычисления:
hex: B0C0A80101001A – запрос напряжения
hex: B1C0A80101001B – запрос тока
hex: B2C0A80101001C – запрос текущей потребляемой мощности
hex: B3C0A80101001D – запрос потреблённой электроэнергии
Более подробно узнать о запросах, ответах, и том как их интерпретировать можно в документации: Peacefair pzem-004t specification
Ну и собственно результат выполнения.
Рис.5.
Как видите нет ничего сложного. Все желающие могут использовать этот код, сославшись в случае публикации на первоисточник.