<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Protokół Modbus/RTU w modułach pomiarowych ADAM</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=#FFFF9F>Implementacja Modbus/RTU</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=#F4F4F4 onmouseover="this.style.backgroundColor='#CADCEB'" onmouseout="this.style.backgroundColor='#F4F4F4'"><a href=206>Seria ADAM-6000 i język PHP</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>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>Protokół Modbus/RTU</b><br>Czyli komunikacja na łączu szeregowym RS-485
	<span class="cbot"><span></span></span>
	</div>
	<br>
	Przesyłane w obydwie strony wiadomości zorganizowane są w postaci ramek o czterech ściśle określonych polach:<br>
	<br>
	<table cellpadding=5 cellspacing=0>
	<tr align=middle style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;">
	<td class=vlrbt>ADDRESS</td>
	<td class=vrbt>FUNCTION  CODE</td>
	<td class=vrbt>DATA</td>
	<td class=vrbt>CHECKSUM</td>
	</tr>
	</table>
	<br>
	W implementacji RTU dla zapytania mamy:<br>
	<br>
	&#8226; <b>ADDRESS</b> [1 bajt] - określa do którego urządzenia wpiętego w sieć (tu RS-485) adresowane jest zapytanie<br>
	&#8226; <b>FUNCTION CODE</b> [1 bajt] - określa kod funkcji/zapytania<br>
	&#8226; <b>DATA</b> [różnej długości] - przekazuje parametry wejściowe wywoływanej funkcji<br>
	&#8226; <b>CHECKSUM</b> [2 bajty] - stanowi sumę kontrolną<br>
	<br>
	Dla odpowiedzi:<br>
	<br>
	&#8226; <b>ADDRESS</b> [1 bajt] - określa adres urządzenia slave odpowiadającego na zapytanie<br>
	&#8226; <b>FUNCTION CODE</b> [1 bajt] - określa kod funkcji/zapytania z zapytania<br>
	&#8226; <b>DATA</b> [różnej długości] - przekazuje parametry wynikowe funkcji<br>
	&#8226; <b>CHECKSUM</b> [2 bajty] - stanowi sumę kontrolną<br>
	<br>
	Najczęściej wykorzystywane funkcje (spośród wielu dostępnych ściśle zdefiniowanych w standardzie) przedstawiono w poniższej tabeli:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr align=middle style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;">
	<td width=100 class=vlrbt>Function code</td>
	<td width=200 class=vrbt>Function description</td>
	</tr>
	<tr><td class=vlrb>0x01</td><td class=vrb>Read Coils</td></tr>
	<tr><td class=vlrb>0x02</td><td class=vrb>Read Discrete Inputs</td></tr>
	<tr><td class=vlrb>0x03</td><td class=vrb>Read Holding Registers</td></tr>
	<tr><td class=vlrb>0x04</td><td class=vrb>Read Input Registers</td></tr>
	<tr><td class=vlrb>0x05</td><td class=vrb>Write Single Coil</td></tr>
	<tr><td class=vlrb>0x06</td><td class=vrb>Write Single Register</td></tr>
	<tr><td class=vlrb>0x08</td><td class=vrb>Loopback Diagnostic</td></tr>
	<tr><td class=vlrb>0x0F</td><td class=vrb>Write Multiple Coils</td></tr>
	<tr><td class=vlrb>0x10</td><td class=vrb>Write Multiple Registers</td></tr>
	</table>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Oprócz znajomości kodów i struktury poszczególnych funkcji Modbus potrzebne są nam jeszcze adresy rejestrów. W przypadku modułów
	pomiarowych serii ADAM możemy je znaleźć w dokumentacji lub odczytać za pomocą ADAM.NET Utility. Dla najpopularniejszych modułów
	serii ADAM-4000 - czyli modułu wejść analogowych ADAM-4017+ i modułu we/wy cyfrowych ADAM-4055 będą to następujące wartości:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td align=center style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=3 class=vlrbt>ADAM-4017+</td><td align=center class=v>&nbsp;</td><td align=center style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=3 class=vlrbt>ADAM-4055</td></tr>
	<tr><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Analog Inputs</td><td align=center class=v>&nbsp;</td><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Digital Inputs</td></tr>
	<tr><td width=60 align=center class=vlrb>40001</td><td width=60 align=center class=vrb>AI-0</td><td width=60 align=center class=vrb>R</td><td width=40 align=center class=v>&nbsp;</td><td width=60 align=center class=vlrb>00001</td><td width=60 align=center class=vrb>DI-0</td><td width=60 align=center class=vrb>R</td></tr>
	<tr><td align=center class=vlrb>40002</td><td align=center class=vrb>AI-1</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>00003</td><td align=center class=vrb>DI-1</td><td align=center class=vrb>R</td></tr>
	<tr><td align=center class=vlrb>...</td><td align=center class=vrb>...</td><td align=center class=vrb>...</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>...</td><td align=center class=vrb>?</td><td align=center class=vrb>...</td></tr>
	<tr><td align=center class=vlrb>40008</td><td align=center class=vrb>AI-7</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>00008</td><td align=center class=vrb>DI-7</td><td align=center class=vrb>R</td></tr>
	<tr><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Analog Inputs Types</td><td align=center class=v>&nbsp;</td><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Digital Outputs</td></tr>
	<tr><td align=center class=vlrb>40201</td><td align=center class=vrb>AI-0 typ</td><td align=center class=vrb>R/W</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>00017</td><td align=center class=vrb>DO-0</td><td align=center class=vrb>R/W</td></tr>
	<tr><td align=center class=vlrb>40202</td><td align=center class=vrb>AI-1 typ</td><td align=center class=vrb>R/W</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>00018</td><td align=center class=vrb>DO-1</td><td align=center class=vrb>R/W</td></tr>
	<tr><td align=center class=vlrb>...</td><td align=center class=vrb>...</td><td align=center class=vrb>...</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>...</td><td align=center class=vrb>?</td><td align=center class=vrb>...</td></tr>
	<tr><td align=center class=vlrb>40208</td><td align=center class=vrb>AI-7 typ</td><td align=center class=vrb>R/W</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>00024</td><td align=center class=vrb>DO-7</td><td align=center class=vrb>R/W</td></tr>
	<tr><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Module Info</td><td align=center class=v>&nbsp;</td><td align=center bgcolor=#F0F0F0 colspan=3 class=vlrb>Module Info</td></tr>
	<tr><td align=center class=vlrb>40211</td><td align=center class=vrb>Name-1</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>40211</td><td align=center class=vrb>Name-1</td><td align=center class=vrb>R</td></tr>
	<tr><td align=center class=vlrb>40212</td><td align=center class=vrb>Name-2</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>40212</td><td align=center class=vrb>Name-2</td><td align=center class=vrb>R</td></tr>
	<tr><td align=center class=vlrb>40213</td><td align=center class=vrb>Firmware-1</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>40213</td><td align=center class=vrb>Firmware-1</td><td align=center class=vrb>R</td></tr>
	<tr><td align=center class=vlrb>40214</td><td align=center class=vrb>Firmware-2</td><td align=center class=vrb>R</td><td align=center class=v>&nbsp;</td><td align=center class=vlrb>40214</td><td align=center class=vrb>Firmware-2</td><td align=center class=vrb>R</td></tr>
	</table>
	<br>
	<hr size=1>
	Korzystając z tych informacji możemy już budować strukturę naszych zapytań Modbus/RTU. Na początek skorzystamy z funkcji 0x04 -
	<b>Read input Registers</b>. Struktura jej zapytań i stosownych odpowiedzi, zgodnie ze standardem Modbus wygląda następująco:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Read input Registers - struktura zapytania</b></td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x04</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Starting Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Quantity of Input Registers (N)</td><td class=vrb>2 bajty</td><td class=vrb>0x0001-0x007D</td></tr>
	</table>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Read input Registers - struktura odpowiedzi</td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x04</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Byte Count</td><td class=vrb>1 bajt</td><td class=vrb>2xN</td></tr>
	<tr><td class=vrb>Input Registers</td><td class=vrb>Nx2 bajtów</td><td class=vrb>-</td></tr>
	</table>
	<br>
	Przykładowe transakcje będą więc wyglądały następująco:<br>
	<br>
	&#8226; Odczyt nazwy urządzenia i wersji firmware dla modułu <b>ADAM-4017+</b>:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>01</td><td class=vrbt>04</td><td class=vrbt>00-D2</td><td class=vrbt>00-04</td><td class=vrbt>E4-30</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>01</td><td class=vrbt>04</td><td class=vrbt>08</td><td class=vrbt bgcolor=#F0F0F0>40-17-50-00-A2-02-00-00</td><td class=vrbt>C9-14</td>
	</tr></table>
	<br>
	&#8226; Odczyt wartości wejścia analogowego AI-0 dla modułu <b>ADAM-4017+</b>:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>01</td><td class=vrbt>04</td><td class=vrbt>00-00</td><td class=vrbt>00-01</td><td class=vrbt>31-CA</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>01</td><td class=vrbt>04</td><td class=vrbt>02</td><td class=vrbt bgcolor=#F0F0F0>E5-F9</td><td class=vrbt>33-E2</td>
	</tr></table>
	<br>
	<hr size=1>
	Do ustawienia pojedynczego wyjścia cyfrowego skorzystamy z funkcji 0x05 - <b>Write Single Coil</b>:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Write Single Coil - struktura zapytania</b></td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x05</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Output Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Output Value</td><td class=vrb>2 bajty</td><td class=vrb>0x0000 / 0xFF00</td></tr>
	</table>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Write Single Coil - struktura odpowiedzi</td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x05</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Output Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Output Value</td><td class=vrb>2 bajty</td><td class=vrb>0x0000 / 0xFF00</td></tr>
	</table>
	<br>
	Przykładowe transakcje - włączenie i wyłączenie wyjścia cyfrowego DO-0 w module <b>ADAM-4055</b> - będą więc wyglądały następująco:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>02</td><td class=vrbt>05</td><td class=vrbt>00-10</td><td class=vrbt>FF-00</td><td class=vrbt>8D-CC</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>02</td><td class=vrbt>05</td><td class=vrbt>00-00</td><td class=vrbt bgcolor=#F0F0F0>FF-00</td><td class=vrbt>8C-09</td>
	</tr></table>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>02</td><td class=vrbt>05</td><td class=vrbt>00-10</td><td class=vrbt>00-00</td><td class=vrbt>CC-3C</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>02</td><td class=vrbt>05</td><td class=vrbt>00-00</td><td class=vrbt bgcolor=#F0F0F0>00-00</td><td class=vrbt>CD-F9</td>
	</tr></table>
	<br>
	<hr size=1>
	Do ustawienia kilku wyjść cyfrowych (jedną transakcją) skorzystamy funkcji 0x0F - <b>Write Multiple Coils</b>:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Write Multiple Coils - struktura zapytania</b></td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x0F</td></tr>
	<tr><td class=vlrb rowspan=4 width=80>DATA</td><td class=vrb width=200>Starting Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Quantity of Outputs</td><td class=vrb>2 bajty</td><td class=vrb>0x0001-0x07B0</td></tr>
	<tr><td class=vrb>Byte Count</td><td class=vrb>1 bajt</td><td class=vrb>N</td></tr>
	<tr><td class=vrb>Outputs Value</td><td class=vrb>N bajtów</td><td class=vrb>-</td></tr>
	</table>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Write Multiple Coils - struktura odpowiedzi</td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x0F</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Starting Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Quantity of Outputs</td><td class=vrb>2 bajty</td><td class=vrb>0x0001-0x07B0</td></tr>
	</table>
	<br>
	Przykładowe transakcje - włączenie i wyłączenie wszystkich wyjść cyfrowych w module <b>ADAM-4055</b> - będą więc wyglądały następująco:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>02</td><td class=vrbt>0F</td><td class=vrbt>00-10</td><td class=vrbt>00-08</td><td class=vrbt>01</td><td class=vrbt>FF</td><td class=vrbt>3F-03</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>02</td><td class=vrbt>0F</td><td class=vrbt>00-00</td><td class=vrbt>00-08</td><td class=vrbt>54-3E</td>
	</tr></table>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>02</td><td class=vrbt>0F</td><td class=vrbt>00-10</td><td class=vrbt>00-08</td><td class=vrbt>01</td><td class=vrbt>00</td><td class=vrbt>7F-43</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>02</td><td class=vrbt>0F</td><td class=vrbt>00-00</td><td class=vrbt>00-08</td><td class=vrbt>54-3E</td>
	</tr></table>
	<br>
	<hr size=1>
	Do odczytu stanu wejść cyfrowych skorzystamy z funkcji 0x02 - <b>Read Discrete Inputs</b>:<br>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Read Discrete Inputs - struktura zapytania</b></td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x02</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Starting Address</td><td class=vrb>2 bajty</td><td class=vrb>0x0000-0xFFFF</td></tr>
	<tr><td class=vrb>Quantity of Inputs</td><td class=vrb>2 bajty</td><td class=vrb>0x0001-0x007D</td></tr>
	</table>
	<br>
	<table cellpadding=2 cellspacing=0>
	<tr><td class=vlrbt style="BACKGROUND-COLOR:#FFFF9F;COLOR:#000000;FONT-WEIGHT:bold;" colspan=4>Read Discrete Inputs - struktura odpowiedzi</td></tr>
	<tr><td class=vlrb colspan=2>FUNCTION CODE</td><td class=vrb width=60>1 bajt</td><td class=vrb width=100>0x02</td></tr>
	<tr><td class=vlrb rowspan=2 width=80>DATA</td><td class=vrb width=200>Byte Count</td><td class=vrb>1 bajt</td><td class=vrb>N</td></tr>
	<tr><td class=vrb>Inputs Status</td><td class=vrb>N bajtów</td><td class=vrb>-</td></tr>
	</table>
	<br>
	Przykładowa transakcja - odczyt stanu wszystkich wejść cyfrowych w module <b>ADAM-4055</b> - będzie więc wyglądała następująco:<br>
	<br>
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>02</td><td class=vrbt>02</td><td class=vrbt>00-00</td><td class=vrbt>00-08</td><td class=vrbt>79-FF</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>02</td><td class=vrbt>02</td><td class=vrbt>01</td><td class=vrbt bgcolor=#F0F0F0>AA</td><td class=vrbt>21-B3</td>
	</tr></table>
	<br>
	<hr size=1>
	<br>
	<div class="myframe" style="FONT-SIZE:12px;BACKGROUND-COLOR:#DCDCDC;COLOR:#000000;">
	<span class="ctop"><span></span></span>
	<b>UWAGA</b>: W przedtawionych wyżej przykładach, w każdej z komend (zgodnie ze standardem Modbus) występują dwa kończące bajty
	reprezentujące sumę kontrolną <b>CRC</b>. Do jej wygenerowania (algorytm jest bardziej złożony niż np. w przypadku protokołu ADAM-ASCII)
	skorzystać możemy np. z poniższej funkcji (Pascal/Delph):<br>
	<br>
	procedure <b>GenerateModbusCRC</b>(var modbus_command:string);<br>
	var CRC:word;<br>
	bajt,bit:byte;<br>
    	LSB:byte;<br>
	begin<br>
	&nbsp;&nbsp;CRC:=$FFFF;<br>
	&nbsp;&nbsp;for bajt:=1 to length(modbus_command) do<br>
		&nbsp;&nbsp;&nbsp;&nbsp;begin<br>
		&nbsp;&nbsp;&nbsp;&nbsp;CRC:=CRC xor ord(modbus_command[bajt]);<br>
		&nbsp;&nbsp;&nbsp;&nbsp;for bit:=1 to 8 do<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LSB:=CRC and $0001;<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if LSB=1 then CRC:=CRC-1;<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CRC:=CRC shr 1;<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if LSB=1 then CRC:=CRC xor $A001;<br>
			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
		&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
	&nbsp;&nbsp;modbus_command:=modbus_command+chr(CRC and $00FF)+chr((CRC and $FF00) shr 8);<br>
	end;<br>
	<span class="cbot"><span></span></span>
	</div>
	<p align=justify>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
	Na podstawie przedstawionych powyżej danych i przykładów (oraz oczywiście po sięgnięciu do dokumentacji protokołu Modbus) możemy jak widać
	we własnym zakresie - od podstaw - zorganizować komunikację naszej aplikacji z modułami pomiarowymi ADAM - w oparciu o bezpośrednią obsługę
	łącza szeregowego. Nie jest to sprawa trywialna - trzeba pamiętać o pewnych dodatkowych, nie opisanych wyżej właściwościach protokołu Modbus,
	oraz - co bardzo ważne - odpowiednio zaimplementować obsługę błędów. Na szczęście nie zawsze jesteśmy do tego zmuszeni - z pomocą przychodzi
	nam zazwyczaj implementacja protokołu w systemach <b>SCADA/HMI</b>, plus szeroka dostępność serwerów <b>OPC</b> (pozycja taka występuje
	także w ofercie Advantech). Jednakże znajomość struktury tegoż protokołu będzię zapewne pomocna także i w takim przypadku...
	<br>
	<br>
	<div class="myframe" style="WIDTH:120px;FONT-SIZE:12px;BACKGROUND-COLOR:#EBF3F8;">
	<span class="ctop"><span></span></span>
	<a href=204><b>Ciąg dalszy...</b></a>
	<span class="cbot"><span></span></span>
	</div>
	</td>
	</tr>
</table>

	<!--
	Szablon transakcji
	<table cellpadding=2 cellspacing=0><tr>
	<td class=vlrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td>
	<td class=v width=20 align=center> -> </td>
	<td class=vlrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</td><td class=vrbt>?</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="203">
<input type=hidden name=fv5 value="ffc37a37b31275d91186058e1d5b9890">
<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>

