{{ wiki:comm:modbus_logo.png?200|Modbus logo}} ====== MODBUS ====== en: Modicon bus {{tag>busz modbus}} A Modbus protokoll kialakulása szorosan összefonódott az első PLC születésével. Az első PLC, a[[plc_basic#tortenet|"Modicon 084"]] 1969-ben kezdte meg első ciklusait, és rá egy évre, szükségszerűen létrehozták a Modbus-t. Az eredeti Modbus (eddigi ismereteim szerint) egy meglehetősen elbonyolított, de nyílt protokoll volt. Az eltelt több évtized azt bizonyítja, hogy a Modbus-t azért rendesen eltalálták a szerzői, bár, ez a protokoll már nem az, az 1970-es (más források szerint 1979-es) cucc.\\ Ezt jellemzően finoman úgy lehet megfogalmazni, hogy ez egy **De-facto-standard**, azaz, igen széles körben alkalmazott kommunikációs rendszer, amit ellenben mindenki úgy használ, ahogy akar. Vannak ugyan kötött szabályai, de a legtöbb gyártó ezeket meglehetősen tágan értelmezi.\\ \\ Ezáltal, ha két Modbus-osnak definiált, de nem egy gyártótól származó eszközt kíván összekötni, a dolgot még véletlenül se bagatellizálja el, és a kommunikáció kipróbálása nélkül **ne** adjon rá árajánlatot (a fájdalmas tapasztalatok beszélnek belőlem). A Modbus egy olyan protokoll, mint a világ háta mögötti, ember még soha nem járta madártelepek szigetei. A guano évről-évre rakódik le rajtuk, egyszerű rétegződéssel. Próbáljuk meg első körben valahogy az OSI modellbe bepasszírozni ezt a protokollt. (A neten eddig ahány besorolás - annyiféle besorolás felállással találkoztam.). ===== Modbus OSI modell ===== ^OSI-szint^^^Modbus TCP^^Modbus RTU / ASCII^TCP/IP-szint^| | 7 |Alkalmazási\\ réteg\\ (Application)| Modbus Application Protokoll (MBAP) |||alkalmazási réteg\\ (application layer)|4| | 6 |Megjelenítési\\ réteg\\ (Presentation)| ||| | 5 |Viszonylati réteg\\ (Session)| | 4 |Forgalmazási\\ réteg\\ (Transport)| [[bus_ethernet#tcp|TCP]] || |forgalmazási réteg\\ (transport layer)|3| | 3 |Hálózati\\ Réteg\\ (Network)| [[bus_ethernet#ipv4|IPv4]]\\ [[bus_ethernet#ipv6|IPv6]]\\ || |Internet réteg\\ (Internet layer)|2| | 2 |Adatkapcsolati\\ réteg\\ (Data Link)| LLC/MAC | [[#modbus_rtu_ascii|RTU]] (binary encoding) | [[#modbus_rtu_ascii|RTU]] (binary encoding)\\ [[#modbus_rtu_ascii|ASCII]] (ASCII encoding) |adatkapcsolati réteg\\ (host to network layer)|1| | 1 |Fizikai\\ réteg\\ (Physical)| [[bus_ethernet#ethernet|IEEE 802.3 Ethernet]] \\ 10Base2 \\ 10Base-T \\ 100Base-TX \\ 1000Base-TX \\ [[bus_fiber_optic|száloptika]] | [[bus_rs232|RS232 (V.24)]],\\ [[bus_rs485|RS485]] | A klasszikus Modbus jellemzően a már jól megszokott [[bus_rs|RS]]-ek nyakába ül, sokat nem bajlódik a fizikai réteg definíciójával. A Modbus voltaképpen csak a legfelső - alkalmazási réteget definiálja, ez a MBAP (MODBUS Application Protocol). Ez - elvileg - minden esetben egységes, de persze tudjuk, hogy a gyakorlat szinte mindig mást mutat. A TCP/IP világa sok változást nem hozott a protokollban, így a megszokott MBAP itt a [[bus_ethernet|TCP]]-re települt. A fejezet további részében a három, "alap" Modbus protokoll és ezek háttere kerül ismertetésre: * Modbus ASCII * Modbus RTU * Modbus TCP ===== Modbus kommunikáció ===== {{ wiki:comm:modbus1.png |Modbus communication}} A Modbus egy monomaster hálózatot vagy pont-pont kapcsolatot feltételez. Mindkét esetben egy master és legalább egy slave szükséges a kommunikációhoz. A Modbus RTU csak egy master egység jelenlétét teszi lehetővé. ==== Multimaster ==== A Modbus hálózaton egyszerre több master is jelen lehet (multimaster), de ez esetben ún. multimaster-gateway-t kell beiktatnunk a kummunikációs hálózatba, és a masterek csak Modbus TCP-re lehetnek felfűzve: {{ :hu:arduino:modbus_multimaster.png |Modbus Multimaster}} RTU/ASCII: A slave-ek száma nem haladhatja meg a 246-ot, címzésük az 1..247-es tartományban történhet. A gyakorlat szerint egy szegmensben 32 állomás lehet, és csak repeater-ekkel bővíthető a hálózat. A 0. címmel broadcast üzeneteket lehet küldeni, amennyiben ez a művelet logikai szinten nincs korlátozva. A master jellemzően az 1. címet szokta megkapni.  A [[bus_ethernet|TCP]] esetén az RTU-t telepítették a TCP-re, így az ethernetes hálózatok összes előnyét sikerült beágyazni a Modbusba. Mivel az etherneten az állomások címe nagyságrendekkel magasabb, mint az RTU/ASCII-nél, így ennek a korlátját a Modbus-ban definiált 1 bájtos címe jelenti (itt is marad az 1..247 korlát). ==== Modbus adatmodell ==== ^elsődleges táblák^objekt típusa^írás/olvasás^leírás| |**Discretes Input**\\ (egyedi input)|Single bit|Read-Only|ez a típus az I/O rendszer általi eléréshez használható| |**Coils**\\ (talán tekercsek?)|Single bit|Read-Write|ennek a típusnak az adatai applikációs programmal kezelhetők - változtathatók| |**Input Registers**\\ (input regiszterek)|16-bit word|Read-Only|ez a típus az I/O rendszer általi eléréshez használható| |**Holding Registers**\\ (megfogott regiszterek)|16-bit word|Read-Write|ennek a típusnak az adatai applikációs programmal kezelhetők - változtathatók| A fenti táblázat egy - 1979-es, igazán útkereső kommunikációs koncepció világlátását tükrözi, az elnevezésekben. A lényeg az objektum típusa oszlopból és az írás / olvasás tulajdonságból jön le. Van bites és szavas elérés, és van csak olvasás és írás/olvasás lehetőség. Ennyi. ==== MBAP ==== en: Modbus Application Protokoll Az MBAP voltaképpen maga a Modbus protokoll. Az [[#modbus_osi|OSI-Modell]] meghatározása szerint ez az Alkalmazási réteg szintjén található, csakhogy a Modbus voltaképpen nem is nagyon áll másból. A rend kedvéért az [[#modbus_rtu_ascii|ASCII / RTU]] encoding-ot felpakolták az adatkapcsolati rétegbe, de a protokoll többi megvalósítását az [[bus_rs|RS]]-ek és a [[bus_ethernet|TCP]] vállalják át. ==== ADU/PDU ==== A telegramok a (klasszikus) ASCII / RTU esetében a lenti ábrán látható tagolásban kerülnek továbbításra. A TCP esetében a PDU-n kívül eső részek kezelését a TCP protokoll veszi át, így ott már csak a PDU marad meg. {{ :wiki:comm:modbus_adu.png |Modbus ADU/PDU}} A klasszikus Modbus a telegramokban két szerkezeti tagolást különböztet meg: === ADU : Applikációs adategység === en: Application Data Unit Applikációs szempontból magába foglalja az összes adatrészt, így a címet és a CFC-t vagy LFC-t is. === PDU: Protokoll adategység === en: Protocol Data Unit Csak a funkciókódot és az adatot foglalja magába. A PDU az átviteli protokolltól független rész, melyet az MBAP generál az alkalmazási réteg szintjén. Lásd [[#modbus_osi|OSI modell]]. Abból a tényből következően, hogy a PDU-beli címzésre 2 bájt áll rendelkezésre, a tárterületek címzésének a felső határa 65536. == PDU-k felépítése == A Modbus kommunikáció kérdés - válasz típusú kommunikációra épül.  A telegramok tartalmuk szerint az alábbi három csoportba oszthatók: ^PDU típusa^leírása| |kérdés\\ (**request** : kérés, kérelem)|Minden esetben tartalmazza a funkciókódot, majd jellemzően utalás található benne a kezdőcímre és a lekérdezés hosszára.| |válasz\\ (**response**: felelet, válasz)|A funkciókód megegyezik a kérdés funkciókódjával, ha a művelet a megszólított fél oldalán probléma nélkül végrehajtható. Jellemzően megadja a válasz hosszát és tartalmát.| |hiba\\ (**error**)|Ha a megszólított fél oldalán hiba merül fel, ezzel a tartalommal válaszol a kérdésre. A funkciókód mezőben a funkciókód + 0x80 választ ad, és az adatmezőben a probláma okát próbálja felfedni. Ez az un. exception code, ennek értéke 01, 02, 03 vagy 04 lehet.| A PDU-k kiértékelése a fogadó oldalon az alábbi folyamatábra szerint zajlik: {{wiki:comm:modbus_folyamatabra.png?366x531|Modbus PDU check (flow chart)}}  ==== Modbus exception kódok ==== ^kód^megnevezés^jelentése| |01|ILLEGAL FUNCTION|Az elküldött telegram funkciókódja szerinti művelet az adott állomáson nem hajtható végre. Legtöbb esetben például olyan kód megy el a célállomásra, ami csak az újabb (vagy csak a régebbi) egységeken hajtható végre. Eltérő konfigurálás miatt is előfordulhat az elutasítás.| |02|ILLEGAL DATA ADDRESS|Az adott egységen a megadott címtartományban a művelet nem hajtható végre. Jellemzően ebben az esetben címtartományból kicímzések esetén fordul elő ez a hiba. Ha a rendelkezésre álló regiszterek száma például 50, és a 46.-tól címzünk 5 regisztert, előcsalhatjuk a hibát.| |03|ILLEGAL DATA VALUE|A kérdés telegramban szerepelő adat pontatlan, a célállomás számára nem értelmezhető.| |04|SLAVE DEVICE FAILURE|A célállomás - visszaállíthatatlan hibára hivatkozva - elutasítja a művelet végrehajtását.| |05|ACKNOWLEDGE|Jellemően parancsvégrehajtás esetén szokott felbukkanni.\\ A célállomás fogadta a telegramot és a végrehajtását is megkezdte, de jellemzően időtúllépés miatt elküld egy ilyen tartalmú telegramot. A célállomás a művelet lezártával küld(het) egy "Poll Program Complete" üzenetet.| |06|SLAVE DEVICE BUSY|Jellemzően parancsvégrehajtás esetén szokott felbukkanni.\\ A célállomás jelzi a hívó félnek, hogy folyamatban levő végrehajtás miatt nem tud új telegramot fogadni. A telegram küldését a későbbiekben ismételni kell ennek a válasznak az esetén.| |08|MEMORY PARITY ERROR|A művelet végrehajtása közben a célállomás belefutott egy memória paritáshibába, és ezt muszáj közölnie a hívó féllel.| |0A|GATEWAY PATH UNAVAILABLE|Jellemzően azokban az esetekben lép fel, ha az okos rendszergazda elkonfigurálja a [[bus_units#gateway|gatway]]-t, vagy egyszerűen túlterhelt az.| |0B|GATEWAY TARGET DEVICE FAILED TO RESPOND|Az adott állomás lehullott a hálózatról, ezért nem érhető el.| ==== Modbus funkciós kódok ==== === Modbus funkciós kódok cím szerinti felosztása === {{wiki:comm:modbus_kodkat.png?260x297|Modbus functionscodes sequences}}=== Modbus funkciós kódok csoportosítása === ^kód csoportosítása^^^kód leírása^kód^al-kód| |data access\\ \\ adatelérés|bit access\\ \\ bites elérés|Physical Discrete Inputs\\ \\ egyedi fizikai címek|read discrete inputs\\ egyedi inputok olvasása| 02\\ | | |Internal Bits Or Physical coils\\ \\ belső bit vagy fizikai coil|read coils\\ coil-ek olvasása| 01 | | |Write Single Coil\\ egyedi coil írása| 05 | | |Write Multiple Coils\\ többszörös coil írás| 15 | | |16 bits access\\ \\ szavas elérés|Physical Input Registers\\ \\ Internal Registers\\ Or\\ Physical Output Registers\\ \\ fizikai input regiszter\\ \\ belső regiszter\\ vagy\\ fizikai kimeneti regiszter|Read Input Register\\ input regiszter olvasása| 04 | | |Read Holding Registers\\ megfogott regiszterek olvasása| 03 | | |Write Single Register\\ egyedi regiszter írása| 06 | | |Write Multiple Registers\\ többszörös regiszterek írása| 16 | | |Read/Write Multiple Registers\\ többszörös regiszter írás / olvasás| 23 | | |Mask Write Register\\ maszkolt regiszter írás| 22 | | |Read FIFO queue\\ FIFO lekérdezés| 24 | | |File record access\\ \\ fájlrekord elérés||Read File record\\ fájlrekord olvasása| 20 | | |Write File record\\ fájlrekord írása| 21 | | |Diagnostics\\ \\ diagnosztika|||Read Exception status\\ hibakód olvasása| 07 | | |Diagnostic\\ diagnosztika| 08 |00 - 18, 20| |Get Com event counter| 11 | | |Get Com Event Log| 12 | | |Report Slave ID| 17 | | |Read device Identification| 43 |14| |Other\\ \\ egyéb|||Encapsulated Interface Transport| 43 |13, 14| |CANopen General Reference| 43 |13| ==== Modbus funkciós kódok leírása ==== Azért ezt a dokumentumot lusta vagyok lefordítani (meg minek is). Tehát ezek leírása itt található: [[http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf|Modbus_Application_Protocol_V1_1b (pdf)]] ==== Egy példa ==== A Read Coil (0x01) eljárással szeretnénk kiolvasni a 19 - 37 output mezők tartalmát. === Request (lekérés) === ^[[#adu_pdu|PDU]]^PDU tartalma^mező hossza^értéke vagy\\ határértéke^példa| |funkciókód|funkciókód|1 bájt|0x01|0x01| |adat|kezdőcím|2 bájt|0x0000 - 0xFFFF|0x00 (HI) 0x12 (LO)| |coil darabszáma|2 bájt|1 - 2000 (0x7D0)|0x00 (HI) 0x13 (LO)| === Response (válasz) === ^[[#adu_pdu|PDU]]^PDU tartalma^mező hossza^értéke vagy\\ határértéke^példa| |funkciókód|funkciókód|1 bájt|0x01|0x01| |adat|bájok száma|1 bájt|n|0x03| |coil-ok státusza\\ (bájtokban)|n bájt|n = n vagy n+1|0xAB\\ 0xCD\\ 0xEF| === Error (hiba) === ^[[#adu_pdu|PDU]]^PDU tartalma^mező hossza^értéke vagy\\ határértéke^példa| |funkciókód|funkciókód|1 bájt|funkciókód + 0x80|0x81| |adat|Exception code|1 bájt|01, 02, 03 vagy 04|0x01| ===== Modbus RTU / ASCII ===== ^ ^Modbus / ASCII^^Modbus / RTU^| ^**Karakterek** |ASCII **0**...**9** és **A**..**F** ||Bináris **0**...**255** || ^**Hibaellenőrzés** |**LRC** (Longitudinal Redundancy Check) ||**CRC** (Cyclic Redundancy Check) || ^Keret kezdet |kettőspont karakter '**:**' ||3.5 karakternyi szünet || ^**Keret vég** |sor vége / új sor karakterek CR/LF ||3.5 karakternyi szünet || ^**Gap-ok az üzenetben** |1 sec ||1.5 karakter || | | ^**Start bit** |**1**||**1**|| ^**Adat bitek** |**7**||**8**|| ^**Paritás** |even / odd|none|even / odd|none| ^**Stop bitek** |**1**|**2**|**1**|**2**| A paritásról, start és stop bitekről bővebben az [[bus_rs232|RS232]] fejezetben olvashat. Az átvitel sebessége (meg az összes egyéb jellemzője) az alkalmazott RS technikától függ, ezek összevetését [[bus_rs#osszehasonlitas|itt találja meg]]. ==== telegramok felépítése ==== A telegramok felépítése az ASCII/RTU esetén - néhány kisebb eltéréstől eltekintve - alapvetően azonos. ^Mező neve^[[#adu_pdu|ADU / PDU]]^Leírás| ^Start-of-frame (SOF)|-|Az adatátvitel megkezdését jelző bájt vagy bájtsorozat.| ^cím|ADU|0: broadcast, 1..247: állomáscím| ^funkciókód|ADU/PDU|ezeknek leírását a funkciókód fejezetben találja meg. Eredetileg ezek egységes rendszert képeznek.\\ 0: érvénytelen funkciókód\\ 1..127: szabadon használható funkciókódok\\ 128..255: fenntartott funkciókódok| ^adatok|ADU/PDU|a funkciókód által meghatározott adatok. Az adatmező hosszát is a funkciókód határozza meg.| ^LR/CR ellenőrzés|ADU|A telegram tartalmának ellenőrzőkódja.| ==== Modbus ASCII telegram-formátum ==== en: American Standard Code for Information Interchange A protokoll ASCII formában viszi át az információt, így előnye, hogy terminálon keresztül az átvitt adatsor egyszerűen olvasható, hátránya (az RTU-hoz képest) hogy kevésbé hatékony. ^SOF^cím^funkciókód^adatok^LR-ellenőrzés^stop| |kettőspont karakter (:)|2 karakter|2 karakter|n karakter|2 karakter|2 karakter (CRLF)| ==== Modbus RTU telegram-formátum ==== en: Remote Terminal Unit, de: entfernte Terminaleinheit A protokoll az információkat bineáris formában továbbítja, így hatékonyabb átviteli forma, mint az ASCII. A Modbus TCP ennek az átvitelnek a TCP-re adoptált változata. ^SOF^cím^funkciókód^adatok^CR-ellenőrzés^stop| |Várakozási idő\\ (min. 3,5 karakter)|8 bit|8 bit|n*8 bit|16 bit|Várakozási idő\\ (min. 1,5 karakter)| ===== Modbus TCP telegram-formátum ===== A Modbus TCP a fent már leírt Modbus RTU TCP-re ültetett változata, mely értelemszerűen ethernetet használ az átvitelhez és a [[bus_ethernet#tcpip|TCP/IP keretezési követelményei]]nek felel meg. Az állomások száma nincs korlátozva, az átvitel sebességét a kiépített hálózat határozza meg. ^tranzakció-szám^protokoll-kód^átvitelre kerülő bájtok száma^cím^funkciókód^adatok| |2 byte|2 byte\\ (mindig 0x0000)|2 byte (n+2)|1 byte|1 byte|n byte|