<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Obsługa Modbus/TCP z poziomu języka php</title>
<meta name="keywords" content="Moduły pomiarowe kontrolno-pomiarowe moduł pomiarowy kontrolno-pomiarowy ADAM USB I/O Advantech">
<meta name="description" content="Moduły pomiarowe kontrolno-pomiarowe moduł pomiarowy kontrolno-pomiarowy ADAM USB I/O Advantech">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
<meta name="author" content="Jacek Bonecki - Elmark Automatyka Sp. z o.o. - http://www.elmark.com.pl">
<meta name="verify-v1" content="dFPC/7SMwqEjaoI9PbBxgMy61Tm7deLBY7wDvMEdY3E=">
<style type="text/css">
<!--
a:HOVER{TEXT-DECORATION:UNDERLINE;}
a {TEXT-DECORATION:none}
.vlrbt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vrbt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vlbt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vlrt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;}
.vlrb {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;}
.vlr {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;}
.vbt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vrb {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;}
.vrt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vlb {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;}
.vlt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.vl {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-LEFT-WIDTH:1px;BORDER-LEFT-STYLE:solid;BORDER-LEFT-COLOR:#C0C0C0;}
.vr {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-RIGHT-WIDTH:1px;BORDER-RIGHT-STYLE:solid;BORDER-RIGHT-COLOR:#C0C0C0;}
.vb {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-BOTTOM-WIDTH:1px;BORDER-BOTTOM-STYLE:solid;BORDER-BOTTOM-COLOR:#C0C0C0;}
.vt {FONT-FAMILY:Tahoma;FONT-SIZE:10px;BORDER-TOP-WIDTH:1px;BORDER-TOP-STYLE:solid;BORDER-TOP-COLOR:#C0C0C0;}
.v {FONT-FAMILY:Tahoma;FONT-SIZE:10px;}
.myframe {FONT-FAMILY:Tahoma;FONT-SIZE:10px;PADDING-RIGHT:10px;PADDING-LEFT:10px;PADDING-BOTTOM:0px;PADDING-TOP:0px;}
.myframe SPAN.CTOP {MARGIN:0px -10px}
.myframe SPAN.CBOT {MARGIN:0px -10px}
SPAN.CTOP {DISPLAY:BLOCK;FONT-SIZE:1px;LINE-HEIGHT:1px;BACKGROUND-REPEAT:no-repeat;HEIGHT:5px}
SPAN.CBOT {DISPLAY:BLOCK;FONT-SIZE:1px;LINE-HEIGHT:1px;BACKGROUND-REPEAT:no-repeat;HEIGHT:5px}
SPAN.CTOP SPAN {DISPLAY:BLOCK;FONT-SIZE:1px;LINE-HEIGHT:1px;BACKGROUND-REPEAT:no-repeat;HEIGHT:5px}
SPAN.CBOT SPAN {DISPLAY:BLOCK;FONT-SIZE:1px;LINE-HEIGHT:1px;BACKGROUND-REPEAT:no-repeat;HEIGHT:5px}
SPAN.CTOP {BACKGROUND-POSITION:0px 0px;BACKGROUND-IMAGE:none;MARGIN:0px -5px}
SPAN.CTOP SPAN {BACKGROUND-POSITION:100% 0px;BACKGROUND-IMAGE:none}
SPAN.CBOT {CLEAR:both;BACKGROUND-POSITION:0px 100%;BACKGROUND-IMAGE:none;MARGIN:0px -5px}
SPAN.CBOT SPAN {BACKGROUND-POSITION:100% 100%;BACKGROUND-IMAGE:none}
SPAN.CTOP {BACKGROUND-IMAGE:URL(IMG/C1.PNG)}
SPAN.CTOP SPAN {BACKGROUND-IMAGE:URL(IMG/C2.PNG)}
SPAN.CBOT {BACKGROUND-IMAGE:URL(IMG/C3.PNG)}
SPAN.CBOT SPAN {BACKGROUND-IMAGE:URL(IMG/C4.PNG)}
-->
</style>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#000080" vlink="#000080" alink="#000080" leftmargin="10" topmargin="10">
<table align=center width=1000 bgcolor=#000080 cellpadding=0 cellspacing=0 border=0><tr><td align=left><a href=/><img src=img/top.jpg border=0 width=800 height=65></a></td></tr></table>
<table align=center width=1000 border=0 cellpadding=5 cellspacing=0 style="font-family:tahoma;font-size:10px;"><tr>
<td width=1 valign=top align=center class=vlrbt>
<a target=_blank href=http://www.elmark.com.pl/products/advantech/grupa.php?grupa=1><img src=img/elmark.gif width=200 height=66 border=0 alt="Elmark Automatyka Sp. z o.o."></a><br>
<img src=img/blank.gif width=200 height=5><table cellpadding=3 cellspacing=0 width=200 style="font-family:tahoma;font-size:10px;">
<tr><td bgcolor=#000080><b><font color=#FFFFFF>Menu...</font></b></td></tr>
</table>
<table cellpadding=3 cellspacing=0 width=200 class=vlrb>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=0>Strona główna</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=1>O nas: Elmark Automatyka Sp. z o.o.</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=http://www.elmark.com.pl/forum/ target=_blank>Nasze forum</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=2>Inne/ciekawe strony www</a></td></tr>
</table>
<img src=img/blank.gif width=200 height=5><table cellpadding=3 cellspacing=0 width=200 style="font-family:tahoma;font-size:10px;">
<tr><td bgcolor=#000080><b><font color=#FFFFFF>Artykuły...</font></b></td></tr>
</table>
<table cellpadding=3 cellspacing=0 width=200 class=vlrb>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=101>P2P i GCL w serii ADAM-6000</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=102>Seria EKI-122X - konwertery Modbus</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=103>WIRE-CHIP, JAZZ i moduły ADAM</a></td></tr>
</table>
<img src=img/blank.gif width=200 height=5><table cellpadding=3 cellspacing=0 width=200 style="font-family:tahoma;font-size:10px;">
<tr><td bgcolor=#000080><b><font color=#FFFFFF>O czym warto wiedzieć...</font></b></td></tr>
</table>
<table cellpadding=3 cellspacing=0 width=200 class=vlrb>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=201>Protokół ADAM-ASCII</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=202>Protokół Modbus</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=203>Implementacja Modbus/RTU</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=204>Implementacja Modbus/TCP</a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=205>Wyjścia przekaźnikowe</a></td></tr>
<tr><td bgcolor=#FFFF9F>Seria ADAM-6000 i język PHP</td></tr>
</table>
<img src=img/blank.gif width=200 height=5><table cellpadding=3 cellspacing=0 width=200 style="font-family:tahoma;font-size:10px;">
<tr><td bgcolor=#000080><b><font color=#FFFFFF>Najpopularniejsze modele...</font></b></td></tr>
</table>
<table cellpadding=3 cellspacing=0 width=200 class=vlrb>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=301>ADAM-4520<font color=#BBBBBB> Optoizolowany<br>konwerter RS-232/422/485</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=302>ADAM-4017+<br><font color=#BBBBBB>Wejścia analogowe (RS-485)</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=303>ADAM-4055<br><font color=#BBBBBB>We/wy cyfrowe (RS-485)</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=304>ADAM-5000/TCP<br><font color=#BBBBBB>Kaseta Modbus/TCP</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=305>ADAM-6017<br><font color=#BBBBBB>Wejścia analogowe</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=306>ADAM-6060<br><font color=#BBBBBB>We/wy cyfrowe (przekaźnikowe)</font></a></td></tr>
<tr><td bgcolor=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=307>USB-4711A<font color=#BBBBBB> Uniwersalny<br>moduł pomiarowy AI/AO/DI/DO</font></a></td></tr>
</table>
</td>
<td valign=top align=center class=vrbt>
<table width=100% cellpadding=20 cellspacing=0 border=0 style="font-family:tahoma;font-size:12px;">
	<tr>
	<td> 
	<div class="myframe" style="FONT-SIZE:14px;BACKGROUND-COLOR:#EBF3F8;COLOR:#000080;">
	<span class="ctop"><span></span></span>
	<b>Moduły ADAM-6000 w naszej serwerowni</b><br>Czyli maksymalnie uproszczona obsługa Modbus/TCP z poziomu języka PHP
	<span class="cbot"><span></span></span>
	</div>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Dzięki wbudowanej komunikacji w oparciu o łącze sieciowe <b>Ethernet</b> i zaimplementowanemu protokołowi <b>Modbus/TCP</b> moduły serii
	ADAM-6000 mają bardzo szeroki zakres zastosowań. Na potrzeby niniejszego krótkiego artykułu rozważmy np. możliwości ich zastosowania
	w prostym układzie monitorowania szafy serwerowej. Z dużym prawdopodobieństwem założyć możemy, iż przynajmniej jeden z naszych serwerów
	jest serwerem www (na potrzeby internetu lub intranetu) z zainstalowanym modułem <b>PHP</b>. W sytuacji takiej nie musimy już szukać
	żadnego dodatkowego oprogramowania służącego do prostej obsługi modułów serii ADAM-6000 - możemy to zorganizować we własnym zakresie.
	I to na dodatek przy stosunkowo niskim nakładzie pracy!
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Podstawowym parametrem, który powinniśmy monitorować jest oczywiście temperatura. Najważniejszą będzie tu oczywiście temperatura
	panująca wewnątrz naszej szafy serwerowej, opcjonalnie monitorować możemy także temperaturę otoczenia panującą w pomieszczeniu, w którym
	szafa została umieszczona. Do tego celu zastosować możemy jeden z modułów specjalizowanych do pomiaru temperatury, np:<br>
	<br>
	&#8226; <b>ADAM-6015</b> - przeznaczony do bezpośredniej współpracy czujnikami oporowymi (RTD),<br>
	&#8226; <b>ADAM-6018</b> - przeznaczony do bezpośredniej współpracy z czujnikami termoelektrycznymi (termoparami).<br>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Wykorzystać możemy także uniwersalny moduł wejść analogowych <b>ADAM-6017</b>. Wadą takiego rozwiązania będzie oczywiście konieczność
	zastosowania dodatkowego przetwornika temperatury z wyjściem w standardzie napięciowym (np. 0&divide;10V) lub prądowym (np. 4&divide;20mA).
	Jednak rozwiązanie takie będzie też miało pewną zaletę: do modułu podłączyć będziemy mogli przetwornik dowolnej wielkości fizycznej, co
	okazać się może bardzo pomocne np. w przypadku, gdy dodatkowo zechcemy monitorować poziom wilgotności, zadymienia itp.
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Dla włączonego w sieć i odpowiednio skonfigurowanego modułu musimy sobie teraz napisać funckję pozwalającą na odczyt wartości danego
	wejścia analogowego. Skorzystamy oczywiście z zaimplementowanej w moduł PHP obsługi gniazd. Jedyne co musimy zrobić to:<br>
	<br>
	&#8226; nawiązać połączenie TCP na porcie 502 z naszym modułem,<br>
	&#8226; wysłać do niego odpowiednią ramkę z zapytaniem w protokole Modbus/TCP,<br>
	&#8226; odebrać odpowiedź z modułu,<br>
	&#8226; z uzyskanej ramki Modbus/TCP wyekstrahować wartość rejestru i przeliczyć ją na wartość fizyczną.<br>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	W momencie, gdy chcemy to zrobić w możliwie najprostszy sposób nie musimy się oczywiście dokładnie &quot;wgryzać&quot; w całą
	specyfikację protokołu. Skorzystamy po prostu z funkcji 0x04 - czyli <b>Read Input Registers</b>. Przy założeniu, że za każdym
	razem odczytywać będziemy tylko jeden (odpowiedni) rejestr przyjąć możemy praktycznie stałą strukturę naszego zapytania, w którym
	zmianiał się będzie tylko jeden bajt - wskazujący na numer rejestru w module ADAM. Pozostałe bajty (czyli zawartość pól
	Transaction Identifier, Protocol Identifier, Length Field, Unit Identifier, Function Code i Quantity of Input Registers) będą
	miały zawsze tę samą wartość. Nasze zapytanie Modbus/TCP będzie więc zawierało następujące wartości:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>00</td>
	<td class=vrbt>00</td>
	<td class=vrbt>00</td>
	<td class=vrbt>00</td>
	<td class=vrbt>00</td>
	<td class=vrbt>06</td>
	<td class=vrbt>01</td>
	<td class=vrbt>04</td>
	<td class=vrbt>00</td>
	<td class=vrbt bgcolor=#F0F0F0><b>numer kanału</b></td>
	<td class=vrbt>00</td>
	<td class=vrbt>01</td>
	</tr></table>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Dla modułu <b>ADAM-6017</b> odczytywać będziemy mogli w ten sposób wartości z kanałów 0&divide;7, co odpowiadało będzie odczytom rejestrów 40001&divide;40008.
	Po wysłaniu zapytania musimy odebrać i przynajmniej pobieżnie przeanalizować odpowiedź modułu. W tym momencie także możemy przyjąć pewne
	uproszczenie: prawidłowa odpowiedź na zapytanie o wartość pojedynczego 16-o bitowego rejestru (wliczając także nagłówek MBAP Header) powinna mieć
	długość 11 bajtów, a zawartość odczytywanego rejestru reprezentowana jest przez ostatnie dwa bajty. Teraz pozostaje nam już tylko
	przeliczenie otrzymanej w ten sposób wartości na rzeczywistą wartość wielkości fizycznej. Dla modułów serii ADAM będzie to liniowa zależność
	pomiędzy zakresem 0&divide;65535 zwracanym przez rejestr, a ustawionym przy konfiguracji modułu zakresem pomiarowym (np. -10&divide;10V). Na
	tej podstawie obliczyć więc możemy np. wartość zmierzonego przez moduł napięcia, a na podstawie charakterystyki podłączonego do modułu
	przetwornika możemy już obliczyć wartość rzeczywistą mierzonej wielkości fizycznej (temperatury, wilgotności, itp). Nasza <b><u>bardzo prosta</u></b>
	funkcja może więc mieć następującą strukturę:<br>
	<br>
	<div class="myframe" style="FONT-SIZE:12px;BACKGROUND-COLOR:#DCDCDC;COLOR:#000000;">
	<span class="ctop"><span></span></span>
	function <b>MTCPReadAnalogInput</b>($H,$Ch,$R1,$R2)<br>
	{<br>
	$fp=@fsockopen($H,502,$errno,$errstr,1);<br>
	$value="ERR";<br>
	if ($fp)<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(4).chr(0).chr($Ch).chr(0).chr(1);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fwrite($fp,$Query,strlen($Query));<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_socket_blocking($fp,true);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stream_set_timeout($fp,0,20000);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Answer=fread($fp,255);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose($fp);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strlen($Answer)==11) $value=sprintf("%.3f",(ord($Answer[9])*256+ord($Answer[10]))/65535*($R2-$R1)+$R1);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
	return $value;<br>
	}<br>
	<span class="cbot"><span></span></span>
	</div>
	<br>
	gdzie:<br>
	<br>
	&#8226; <b>$H</b> to adres IP naszego modułu pomiarowego ADAM-6017,<br>
	&#8226; <b>$Ch</b> to numer kanału pomiarowego (0&divide;7),<br>
	&#8226; <b>$R1</b> to dolna wartość zakresu pomiarowego (np. -10V),<br>
	&#8226; <b>$R2</b> to górna wartość zakresu pomiarowego (np. +10V),<br>
	&#8226; w przypadku wystąpienia błędu (brak połączenia, brak lub błędna odpowiedź) zwracana jest wartość &quot;ERR&quot;.<br>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Nasz hipotetyczny monitoring szafy serwerowej rozszerzyć możemy także o sygnały dyskretne pozwalające np. na detekcję i rejestrację sygnału otwarcia szafy,
	sprawdzenie stanu czujnika przeciwpożarowego itp. W tym celu wykorzystać możemy np. moduł <b>ADAM-6060</b> wyposażony w 6 wejść cyfrowych
	i 6 wyjść przekaźnikowych. Do odczytu stanu poszczególnych wejść skorzystamy z funkcji 0x01 - <b>Read Coils</b>. Struktura naszej funkcji
	będzie bardzo zbliżona. Za jej pomocą będziemy mogli odczytać stan wejść 0&divide;5. Stan danego wejścia cyfrowego reprezentowany będzie przez
	odpowiedni bit w ostatnim bajcie otrzymanej 10-o bajtowej odpowiedzi z modułu, który ostatecznie będzie naszym wynikiem:<br>
	<br>
	<div class="myframe" style="FONT-SIZE:12px;BACKGROUND-COLOR:#DCDCDC;COLOR:#000000;">
	<span class="ctop"><span></span></span>
	function <b>MTCPReadDiscreteInput</b>($H,$Ch)<br>
	{<br>
	$fp=@fsockopen($H,502,$errno,$errstr,1);<br>
	$value="ERR";<br>
	if ($fp)<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(1).chr(0).chr(0).chr(0).chr(6);<br>
    	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fwrite($fp,$Query,strlen($Query));<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_socket_blocking($fp,true);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stream_set_timeout($fp,0,20000);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Answer=fread($fp,255);<br>
    	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose($fp);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strlen($Answer)==10) $value=(ord($Answer[9])&(1<<$Ch))>>$Ch;<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
	return $value;<br>
	}<br>
	<span class="cbot"><span></span></span>
	</div>
	<br>
	gdzie:<br>
	<br>
	&#8226; <b>$H</b> to adres IP naszego modułu pomiarowego ADAM-6060,<br>
	&#8226; <b>$Ch</b> to numer kanału wejściowego (0&divide;5),<br>
	&#8226; zwracana jest wartość 0 lub 1,<br>
	&#8226; w przypadku wystąpienia błędu (brak połączenia, brak lub błędna odpowiedź) zwracana jest wartość &quot;ERR&quot;.<br>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	W przypadku zaproponowanego modułu <b>ADAM-6060</b> wykorzystać możemy także jego wyjścia cyfrowe. Pozwolą nam np. na załączenie
	wentylatora - w przypadku przekroczenia temperatury granicznej, lub np. na załączenie jakiegoś urządzenia alarmowego w przypadku wykrycia
	aktywnego sygnału z czujki przeciwpożarowej. W tym celu skorzystamy z funkcji 0x05 - <b>Write Single Coil</b>. Parametrami naszej
	funkcji będą: po raz kolejny - numer kanału (0&divide;5; co tutaj odpowiada rejestrom 00017&divide;00022), oraz dodatkowo zapisywany stan
	dla danego wyjścia (0 lub 1):<br>
	<br>
	<div class="myframe" style="FONT-SIZE:12px;BACKGROUND-COLOR:#DCDCDC;COLOR:#000000;">
	<span class="ctop"><span></span></span>
	function <b>MTCPWriteDiscreteOutput</b>($H,$Ch,$S)<br>
	{<br>
	$fp=@fsockopen($H,502,$errno,$errstr,1);<br>
	$value="ERR";<br>
	if ($fp)<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Query=chr(0).chr(0).chr(0).chr(0).chr(0).chr(6).chr(1).chr(5).chr(0).chr(16+$Ch).chr($S*255).chr(0);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fwrite($fp,$Query,strlen($Query));<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set_socket_blocking($fp,true);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stream_set_timeout($fp,0,20000);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Answer=fread($fp,255);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose($fp);<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((strlen($Answer)==12)&&(ord($Answer[10])==($S*255))) $value="OK";<br>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
	return $value;<br>
	}<br>
	<span class="cbot"><span></span></span>
	</div>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Przedstawione powyżej bardzo proste funkcje (w miarę możliwości i czasu do ewentualnego dopracowania; szczególnie jeśli chodzi o bardziej
	wnikliwą kontrolę prawidłowości otrzymywanych danych) mogą stanowić szkielet naszego prostego skryptu wykonywanego cyklicznie (np. z wykorzystaniem
	cron'a) przez serwer, służącego do monitorowania serwerowni. Dodatkowo:
	<ul>
	<li>W przypadku szybkozmiennych sygnałów cyfrowych i przy wykonywaniu skryptu z jakąś ściśle określoną, ale niestety ograniczoną częstotliwością
	musimy się liczyć z tym, że nie każdą chwilową zmianę sygnału wychwycimy. W takim przypadku skorzystać możemy np. z trybu &quot;<b>Low to high latch</b>&quot;
	lub &quot;<b>High to low latch</b>&quot;, lub nawet z trybu licznikowego (<b>Counter</b>). Wymaga to odpowiedniej konfiguracji modułu oraz oczywiście
	dopisania nowych funkcji korzystających z odpowiednich rejestrów (odczyt zawartości licznika, kasowanie statusu latch) przypisanych do tych
	trybów pracy. Będzie to na pewno konieczne rozwiązanie przy monitorowaniu czujnika otwarcia szafy.
	<br>
	<br>
	<li>Dzięki zastosowaniu konwerterów serii EKI-122X (&quot;Modbus TCP/RTU Data Gateways&quot;) zamiast modułów serii ADAM-6000 wykorzystać
	możemy także moduły serii ADAM-4000, wyposażone w obsługę protokołu Modbus/RTU.
	<br>
	<br>
	<li>No i oczwiście nie musimy ograniczać się tylko do naszego hipotetycznego monitoringu serwerowni. Korzystając z modułów ADAM i modułu PHP
	zintergowanego z serwerem www możemy pokusić się o zbudowanie całkowicie we własnym zakresie układu &quot;małej automatyki&quot; z dostępem za
	pośrednictwem przeglądarki internetowej...
	</ul>

	
	</td>
	</tr>
</table>
<br><div align=left class="myframe" style="WIDTH:738px;FONT-SIZE:11px;BACKGROUND-COLOR:#EBF3F8;COLOR:#000080;">
<span class="ctop"><span></span></span>
<b>Jeśli masz jakieś uwagi - możesz dodać swój komentarz do tej strony.</b><br>
<font color=#9EC5DE>Możesz go dopisać anonimowo - ale oczywiście lepiej by było, gdyby czytający wiedzieli kto jest jego autorem.
W przypadku wykrycia treści niedozwolonych lub nic konkretnego do tematu nie wnoszących, wpis może być w późniejszym czasie usunięty (ocenzurowany) przez administratora.</font><br>
<br><table cellpadding=2 cellspacing=0 border=0><form name=fn1 method=post>
<input type=hidden name=fv0 value="206">
<input type=hidden name=fv5 value="a6a7f82cf390ee5c9a3da0f29bce9e2f">
<tr valign=middle><td class=v width=90><b>Autor:</b></td><td>&nbsp;&nbsp;&nbsp;<input maxlength=30 class=vlrbt type=text name=fv1 value="" style="width:200px;BACKGROUND-COLOR:#FFFFFF;"></td><td rowspan=2>&nbsp;</td><td rowspan=2><img src=img/sesssecimg.php width=140 height=35 style="BORDER-WIDTH:1px;BORDER-STYLE:dotted;BORDER-COLOR:#C0C0C0;"></td></tr>
<tr valign=middle><td class=v><b>Firma:</b></td><td>&nbsp;&nbsp;&nbsp;<input maxlength=30 class=vlrbt type=text name=fv2 value="" style="width:200px;BACKGROUND-COLOR:#FFFFFF;"></td></tr>
<tr valign=middle><td class=v><b>Twój e-mail:</b></td><td>&nbsp;&nbsp;&nbsp;<input maxlength=30 class=vlrbt type=text name=fv3 value="" style="width:200px;BACKGROUND-COLOR:#FFFFFF;"></td><td class=v width=90><b>Kod z obrazka</b>:</td><td><input maxlength=8 class=vlrbt type=text name=fv6 style="width:100px;BACKGROUND-COLOR:#FFFFFF;"></td></tr>
<tr valign=top><td class=v><b>Komentarz:</b></td><td colspan=3>&nbsp;&nbsp;&nbsp;<textarea maxlength=30 class=vlrbt name=fv4 style="width:620px;height:100px;BACKGROUND-COLOR:#FFFFFF;"></textarea></td></tr>
<tr valign=top><td class=v colspan=4><input class=vlrbt type=button onClick="javascript:WriteComment()"value=Wyślij style="WIDTH:70px;"></td></tr>
</form>
</table><span class="cbot"><span></span></span>
</div><table cellpadding=0 cellspacing=0><tr><td><img src=img/blank.gif width=10 height=3 border=0></tr></td></table>
<script language="JavaScript" type="text/javascript">
<!--
function WriteComment()
{
if (document.fn1.fv6.value.length!=8) {alert('Przepisz kod zabezpieczający - w postaci ośmiocyfrowej liczby - z umieszczonego w formularzu obrazka.');return;};
if (isNaN(document.fn1.fv6.value)) {alert('Kod zabezpieczający jest ośmiocyfrową liczbą - więc może się składać tylko z cyfr.');return;};
if (document.fn1.fv6.value<0) {alert('Kod zabezpieczający jest ośmiocyfrową liczbą większą od 0.');return;};
if (document.fn1.fv4.value.length<15) {alert('Jakiś komentarz wpisać musisz - przyjmijmy, że będzie to minimum 15 znaków.');return;};
if (document.fn1.fv4.value.length>1024) {alert('Długość komentarza nie może przekaczać 1024 znaków!');return;};
document.fn1.submit();
}
// -->
</script>
</td>
</tr></table><br><br>
</body>
</html>

