Używamy plików cookies (tzw. ciasteczka) by spersonalizować treść i ogłoszenia oraz by analizować ruch na stronie.  W sposób automatyczny dzielimy się informacjami o Twoim użyciu tego portalu z dostawcami ogłoszeń, którzy mogą połączyć te informacje z informacjami, które im udzieliłaś/łeś lub, które sami zebrali. Korzystanie z witryny bez zmiany ustawień dotyczących cookies oznacza, że będą one zamieszczane w Państwa urządzeniu końcowym.  Możecie Państwo dokonać w każdym czasie zmiany ustawień dotyczących cookies zmieniając opcje przeglądarki.

Wstęp do MODBUSa

Gdy zrozumie się już jak wygląda pamięć sterownika i jak można adresować zmienne, by ich wartości były przechowywane w konkretnie określonym miejscu (-->poprzedni artykuł), można zabrać się za poznanie protokołu MODBUS. MODBUS jest obecnie przemysłowym standardem wykorzystywanym do komunikowania się z najróżniejszymi urządzeniami.  Potencjalne wykorzystania to np. połączenie sterownika z pulpitem HMI, połączenie z modułem 1-wire, połączenie sterownika z komputerem PC itd.

UWAGA! Wszystko, co tu znajdziecie jest amatorską próbą objęcia tematu prostym umysłem.  Znawców rzeczy proszę o wyrozumiałość.  Niestety żaden 'profesjonalny' opis nie był dla mnie do przebrnięcia dopóki sam wszystkiego nie poskładałem z wielu przypadkowych kawałków.  

Komunikacja w MODBUSie odbywa się poprzez wykonywanie tzw. funkcji.  Funkcje wymiany danych można dla uproszczenia podzielić wg dwóch kryteriów: czy dotyczą zmiennych typu BIT (BOOL) lub WORD oraz czy można zmieniać ich wartość lub jedynie odczytywać.  

Poniższa tabela przedstawia główne funkcje (FC_) wg powyższego podziału:

  Read/Write Read only
BIT/BOOL

FC1 - Read Coil
FC5 - Write Coil
FC15 - Write Multiple Coils

 FC2 - Read Discrete Input
WORD

FC3 - Read Holding Register
FC6 - Write Single Register
FC16 - Write Multiple Registers
FC23 - Read/Write multiple registers

FC4 - Read Input Registers


Powiem szczerze, nie bardzo przemawiają do mnie nazwy.  Nie wiem, czemu coil, discrete input, register... Najważniejsze jest dla mnie, że by odczytać pojedynczy bit mogę wykorzystać FC1 lub FC2, aby zapisać bit - FC5 lub FC15; dla zmiennych typu WORD wykorzystać trzeba FC3, FC4 lub FC23 do odczytu i FC6, FC16 lub FC23 do zapisu.  Kropka.

Dla podkreślenia - MODBUS służy do odczytywania i ew. modyfikacji konkretnych obszarów pamięci sterownika.  Nie obsługuje poleceń typu "wyłącz światło" lub "podaj temperaturę".  Aby zrobić powyższe, trzeba zmodyfikować lub odczytać jakąś konkretną komórkę pamięci.  Jaką?  O tym poniżej.

Pozostaje teraz zrozumieć, jak adresy protokołu MODBUS mają się do adresów w pamięci sterownika.  W instrukcji sterownika znajduje się cały dział zatytułowany "MODBUS Register Mapping".  Można tam znaleźć tabele mapujące adresy: oddzielnie dla funkcji odczytujących pojedyncze bity i osobno dla tych, odczytujące słowa:

 Oto tabela do odczytywania/zapisu pojedynczych bitów (funkcje FC1 i FC2). Dla wejść i wyjść - trzeba znać ich kolejny numer, a nie adres w pamięci:

Adres MODBUS [dec] Zakres pamięci Opis
0...511

Obszar fizycznych wejść

Pierwsze 512 wejść cyfrowych
512...1023

Obszar fizycznych wyjść

Pierwsze 512 wyjść cyfrowych
12288...32767

%MX0...%MX1279.15

NOVRAM
8 kB retain memory

 Dla odczytywania danych typu WORD (funkcje FC3 i FC4):

Adres MODBUS  [dec] Zakres pamięci Opis
0...255

%IW0...%IW255

Obszar fizycznych wejść
512...767

%QW0...%QW255

Obszar fizycznych wyjść
12288...24575

%MW0...%MW12287

NOVRAM 
8 kB retain memory

A więc:

  • dla odczytania stanu wejścia 0 należy funkcją FC1 lub FC2 odczytać adres 0
  • dla odczytania stanu wyjścia 3 należy funkcją FC1 lub FC2 odczytać adres 514
  • aby odczytać wartość zmiennej typu BOOL przechowywanej pod adresem %MX0.3 należy funkcją FC1 lub FC2 odczytać adres 12291,
  • aby odczytać pierwsze słowo z tablicy wejść sterownika należy funkcją FC3 lub FC4 odczytać adres 0
  • aby odczytać pierwsze słowo z tablicy wyjść sterownika należy funkcją FC3 lub FC4 odczytać adres 512
  • aby odczytać wartość zmiennej przechowywanej pod adresem %MW0 należy funkcją FC3 lub FC4 odczytać adres 12288,

Z zapisywaniem (Funkcje FC5 i FC6) jest bardzo podobnie, z tym że wejścia sterownika są read-only.  

Omówmy więc konkretny przykład.  Oto stan mojego sterownika:

Modbus 11 Modbus 1 204

Konieczne jest zaznaczenie, że wejście IN4 jest 4. fizycznym wejściem sterownika a OUT 3 3. fizycznym wyjściem.  Tak odległe adresy w pamięci (%IX11.2 i QX3.2) są konsekwencją występowania innych modułów zajmujących pierwsze obszary pamięci (czujniki analogowe, moduł RS232).

Przykładowe zapytania:

MODBUS WAGO WebServer Odpowiedź
FC2 3 (czwarte wejście)

READPI?ADR=IX11.3&FORMAT=%x

TRUE
FC1 514 (trzecie wyjście)

READPI?ADR=QX3.2&FORMAT=%x

TRUE
FC4 11

READPI?ADR1=IW11&FORMAT=%d

8
(00000000 00001000)

FC5 515

READPI?ADR1=QW3&FORMAT=%d

204
(00000000 11001100)

Jak to wszystko sprawdzić?  Jedną z możliwości jest wykorzystanie biblioteki phpmodbus dostępnej pod https://code.google.com/p/phpmodbus/.  Integruje ona funkcje MODBUSa w języku PHP.

Bez znajomości samego protokołu można pobierać/wysyłać dane do sterownika.  Oto przykład odczytujące dane z adresu 515 (ostatni przykład z powyższej tabeli):

<?php

require_once dirname(__FILE__) . '/Phpmodbus/ModbusMaster.php';

// Create Modbus object
$modbus = new ModbusMaster("192.168.1.3", "UDP");

try {
    // FC 1
    $recData = $modbus->readMultipleRegisters(0, 515, 1);
}
catch (Exception $e) {
    // Print error information if any
    echo $modbus;
    echo $e;
    exit;
}

// Print read data
echo "Data:";
var_dump($recData);

Wykonanie skryptu zwraca:

Data:
array(2) { [0]=> int(0) [1]=> int(204) }

Co oznaczają te liczby?  Odczytaliśmy słowo składające się z dwój bajtów.  Pierwszy równy jest 0, drugi to 204.  204 w systemie dwójkowym to  11001100.  Czytając od tyłu mamy więc: 2 pierwsze bity false, 2 kolejne TRUE (czyli %QX3.2 i %QX3.3), 2 kolejne false i 2 kolejne true. Wszystko się zgadza.

Teraz pozostaje mi znaleźć jakieś urządzenie do integracji i przygotować skrypty PHP, które posłużyłyby jako pośrednik między stroną www a sterownikiem.  Warto by sprawdzić, czy odpytywanie sterownika przez wbudowany webserwer (komendami READPI) jest szybsze niż komunikacja z pośrednictwem serwera na RaspberryPi, który odpytywałby sterownik po MODBUSie.