КРАТКИЙ СПРАВОЧНИК ПО КОМАНДАМ MODBUS ОТ IARDUINO.RU:

ТАБЛИЦЫ РЕГИСТРОВ:
Регистры флагов   «Discrete Coils»   , или регистры цифровых   выходов «DO» - предназначены для чтения и записи (размер 1  бит).
Дискретные входы  «Discrete Inputs»  , или регистры цифровых   входов  «DI» - предназначены только для чтения   (размер 1  бит).
Регистры хранения «Holding Registers», или регистры аналоговых выходов «AO» - предназначены для чтения и записи (размер 16 бит).
Регистры ввода    «Input Registers»  , или регистры аналоговых входов  «AI» - предназначены только для чтения   (размер 16 бит).

КОМАНДЫ:
0x01 (  1) - Read Coil Status.              Чтение значений из нескольких регистров «DO».
0x02 (  2) - Read Discrete Inputs.          Чтение значений из нескольких регистров «DI».
0x03 (  3) - Read Holding Registers.        Чтение значений из нескольких регистров «AO».
0x04 (  4) - Read Input Registers.          Чтение значений из нескольких регистров «AI».
0x05 (  5) - Force Single Coil.             Запись значения в один регистр флагов   «DO».
0x06 (  6) - Preset Single Register.        Запись значения в один регистр хранения «AO».
0x07 (  7) - Read Exception Status.         Чтение сигналов состояния.
0x08 (  8) - Diagnostic.                    Диагностика.
0x09 (  9) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x0A ( 10) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x0B ( 11) - Get Com Event Counter.         Чтение счетчика событий.
0x0C ( 12) - Get Com Event Log.             Чтение журнала событий.
0x0D ( 13) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x0E ( 14) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x0F ( 15) - Force Multiple Coils.          Запись значений в несколько регистров флагов   «DO».
0x10 ( 16) - Preset Multiple Registers.     Запись значений в несколько регистров хранения «AO».
0x11 ( 17) - Report Slave ID.               Чтение информации об устройстве.
0x12 ( 18) - Get Name.                      Чтение названия устройства iArduino. Команда не стандартизирована.
0x14 ( 20) - Read File Record.              Чтение из файла.
0x15 ( 21) - Write File Record.             Запись в файл.
0x16 ( 22) - Mask Write Register.           Запись значения в один регистр хранения «AO» с масками "И" и "ИЛИ". REG = (REG & И) | (ИЛИ & ~И)
0x17 ( 23) - Read/Write Multiple registers. Чтение/запись нескольких регистров хранения «AO».
0x18 ( 24) - Read FIFO Queue.               Чтение данных из буфера FIFO.
0x2B ( 43) - Encapsulated Interface Transport.
0x41-0x48   (65-72)                         Пользовательские команды.
0x64-0x6E   (100-110)                       Пользовательские команды.
0x29 ( 41) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x2A ( 42) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x5A ( 90) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x5B ( 91) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x7D (125) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x7E (126) -                                Команда не стандартизирована, но уже используется в различных устройствах.
0x7F (127) -                                Команда не стандартизирована, но уже используется в различных устройствах.

ПАКЕТ:
╔══════════════════════════════════════════════════════════════════════════════════╗
║                                 ADU (до 256 байт):                               ║
╟──────────┬───────────────────────────────────────────────────────────┬───────────╢
║          │                      PDU (до 253 байт):                   │           ║
║  АДРЕС   ├──────────┬────────────────────────────────────────────────┤ ПРОВЕРКА  ║
║ SlaveID  │ КОМАНДА  │                   ДАННЫЕ                       │  CRC-16   ║
║ (1 байт) │ (1 байт) │               (до 252 байт)                    │ (2 байта) ║
║          │          │         кол байт зависит от команды            │  мл байт  ║
║ 0, 1-247 │  1-127   │                                                │  первым.  ║
╚══════════╧══════════╧════════════════════════════════════════════════╧═══════════╝

ТАБЛИЦЫ С ПАКЕТАМИ ЗАПРОСОВ (СЛЕВА) И ОТВЕТОВ (СПРАВА):

0x01 = Чтение значений из нескольких регистров «DO».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════╦═══╤═══╤═══════╤════════════════════════════════╤════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│             DATA               │CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────────────────┼────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ║КолБайт║(1)│(1)│  (1)  │       sumBYTE (кратно 1)       │(2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    ║Индекс:║[0]│[1]│  [2]  │          [3:3+sumBYTE]         │    ║ sumBYTE - Количество байт DATA в ответе.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────────────────┼────╢ DATA    - Данные ответа.
║Пример:║01 │01 │ 0004 │ 0014 │7DC4 ║    ║Пример:║01 │01 │  03   │0bBA987654-0bJIHGFEDC-0b0000NMLK│XXXX║ В примере запрошены данные из 0x0014 регистров «DO», начиная с адреса 0x0004.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    ╚═══════╩═══╧═══╧═══════╧════════════════════════════════╧════╝ Получено 0x03 байта DATA. В первом байте биты регистров DO[4]-DO[B], во втором биты DO[C]-DO[J=13], в третьем байте не заполненные биты равны 0.

0x02 = Чтение значений из нескольких регистров «DI».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════╦═══╤═══╤═══════╤═════════════════════╤════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│        DATA         │CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼─────────────────────┼────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ║КолБайт║(1)│(1)│  (1)  │ sumBYTE  (кратно 1) │(2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    ║Индекс:║[0]│[1]│  [2]  │    [3:3+sumBYTE]    │    ║ sumBYTE - Количество байт DATA в ответе.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼─────────────────────┼────╢ DATA    - Данные ответа.
║Пример:║01 │02 │ 0005 │ 000B │29CC ║    ║Пример:║01 │02 │  02   │0bCBA98765-0b00000FED│XXXX║ В примере запрошены данные из 0x000B регистров «DI», начиная с адреса 0x0005.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    ╚═══════╩═══╧═══╧═══════╧═════════════════════╧════╝ Получено 0x02 байта DATA. В первом байте биты регистров DI[5]-DI[C], во втором биты DI[D]-DI[F] и не заполненные биты равны 0.

0x03 = Чтение значений из нескольких регистров «AO».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════╦═══╤═══╤═══════╤════════════════════╤════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│        DATA        │CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────┼────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ║КолБайт║(1)│(1)│  (1)  │ sumBYTE (кратно 2) │(2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    ║Индекс:║[0]│[1]│  [2]  │    [3:3+sumBYTE]   │    ║ sumBYTE - Количество байт DATA в ответе.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────┼────╢ DATA    - Данные ответа.
║Пример:║01 │03 │ 0005 │ 0003 │15CA ║    ║Пример:║01 │03 │  06   │ AO[5] AO[6] AO[7]  │XXXX║ В примере запрошены данные из 0x0003 регистров «AO», начиная с адреса 0x0005.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    ╚═══════╩═══╧═══╧═══════╧════════════════════╧════╝ Получено 0x06 байт DATA. Первые 2 байта содержат данные регистра AO[5], следующие 2 байта AO[6], следующие 2 байта AO[7]

0x04 = Чтение значений из нескольких регистров «AI».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════╦═══╤═══╤═══════╤═══════════════════════════════╤════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│             DATA              │CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼───────────────────────────────┼────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ║КолБайт║(1)│(1)│  (1)  │       sumBYTE (кратно 2)      │(2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    ║Индекс:║[0]│[1]│  [2]  │         [3:3+sumBYTE]         │    ║ sumBYTE - Количество байт DATA в ответе.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼───────┼───────────────────────────────┼────╢ DATA    - Данные ответа.
║Пример:║01 │04 │ 0000 │ 0005 │3009 ║    ║Пример:║01 │04 │  0A   │ AI[0] AI[1] AI[2] AI[3] AI[4] │XXXX║ В примере запрошены данные из 0x0005 регистров «AI», начиная с адреса 0x0000.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    ╚═══════╩═══╧═══╧═══════╧═══════════════════════════════╧════╝ Получено 0x0A байт DATA. Первые 2 байта содержат данные регистра AI[0], следующие 2 байта AI[1] и т.д.

0x05 = Запись значения в один регистр флагов «DO».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════════════════════════════════════════════════╗
║  ADU: ║ID │COM│adrREG│ DATA │ CRC ║ -> ║ Ответ на запрос записи является его полной копией ║
╟───────╫───┼───┼──────┼──────┼─────╢    ╚═══════════════════════════════════════════════════╝
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ID     - Адрес модуля SlaveID.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    COM    - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢    adrREG - Адрес регистра.
║Пример:║01 │05 │ 0000 │ FF00 │8C3A ║    DATA   - Данные для записи. Поле может принимать значение 0x0000 (сброс регистра в 0) или 0xFF00 (установка регистра в 1). Каждый регистр «DO» содержит всего 1 бит.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    В примере выполнена установка единственного бита регистра DO[0x0000].

0x06 = Запись значения в один регистр хранения «AO».
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════════════════════════════════════════════════╗
║  ADU: ║ID │COM│adrREG│ DATA │ CRC ║ -> ║ Ответ на запрос записи является его полной копией ║
╟───────╫───┼───┼──────┼──────┼─────╢    ╚═══════════════════════════════════════════════════╝
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ID     - Адрес модуля SlaveID.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    COM    - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢    adrREG - Адрес регистра.
║Пример:║01 │06 │ 0000 │ ABCD │376F ║    DATA   - Данные для записи.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    В примере выполнена запись значения 0xABCD в регистр AO[0x0000].

0x07 = Чтение сигналов состояния (битов состояния статусных выходов).
╔═══════╦═══╤═══╤═════╗    ╔═══════╦═══╤═══╤════╤═════╗ ID   - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ CRC ║    ║  ADU: ║ID │COM│DATA│ CRC ║ COM  - Номер команды.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼────┼─────╢ DATA - байт ответа содержит биты состояний 8 статусных выходов.
║КолБайт║(1)│(1)│ (2) ║    ║КолБайт║(1)│(1)│(1) │ (2) ║
║Индекс:║[0]│[1]│[2:3]║    ║Индекс:║[0]│[1]│[2] │[3:4]║ Состояния обычных выходов доступны в регистрах «DO» (Discrete Coils).
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼────┼─────╢ Но эти регистры позволяют как читать так и менять состояния выходов.
║Пример:║01 │07 │41E2 ║    ║Пример:║01 │07 │ XX │XXXX ║ Состояние статусных выходов доступно только для чтения данной командой.
╚═══════╩═══╧═══╧═════╝    ╚═══════╩═══╧═══╧════╧═════╝

0x08 = Диагностика.
╔═══════╦═══╤═══╤══════╤══════╤═════╗    ╔═══════╦═══╤═══╤══════╤══════╤═════╗ ID   - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ FUNC │ DATA │ CRC ║    ║  ADU: ║ID │COM│ FUNC │ DATA │ CRC ║ COM  - Номер команды.
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢ FUNC - Номер функции.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║    ║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║ DATA - Два байта данных. Тип данных зависит от номера функции.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║    ║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║
╟───────╫───┼───┼──────┼──────┼─────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢
║Пример:║01 │08 │ 0001 │ FF00 │41E7 ║    ║Пример:║01 │0B │ 0001 │ FF00 │41E7 ║ В примере запрошен сброс всех счётчиков, чистка журнала событий, выход из режима Listen Only Mode и выполнение диагностики.
╚═══════╩═══╧═══╧══════╧══════╧═════╝    ╚═══════╩═══╧═══╧══════╧══════╧═════╝
FUNC:
0000: Return Query Data             Возврат запроса (ответ идентичен запросу). Значение DATA может быть любым.
0001: Restart Communication Option  Сначала отвечаем, потом выполняем сброс всех счётчиков, выход из режима Listen Only Mode и выполняем диагностику. Если DATA в запросе равно 0xFF00, то очищается журнал событий.
0002: Return Diagnostic Register    Значение DATA в ответе содержит биты двухбайтного регистра диагностики (каждый бит информирует о ошибке).
0003: Change ASCII Input Delimiter  Смена разделителя символов. Принимаем DATA=XX00, где символ XX заменит символ \n в конце пакетов ModBus ASCII.
0004: Listen Only Mode              Включение режима "Только прослушивание". Модуль должен игнорировать любые запросы, кроме Restart.
000A: Clear Cnt and Diagnostic Reg  Сброс всех счетчиков и регистра диагностики.
000B: Return Bus Message Cnt        Значение DATA в ответе содержит значение счётчика общего количества обнаруженных запросов на шине.
000C: Return Bus CRC Cnt            Значение DATA в ответе содержит значение счётчика количества запросов с ошибками CRC.
000D: Return Bus Exeption Error Cnt Значение DATA в ответе содержит значение счётчика количества отправленных сообщений об ошибках.
000E: Return Slave Message Cnt      Значение DATA в ответе содержит значение счётчика количества адресованных устройству запросов.
000F: Return Slave No Response Cnt  Значение DATA в ответе содержит значение счётчика количества запросов которые остались без ответа.
0010: Return Slave NAK Cnt          Значение DATA в ответе содержит значение счётчика количества отправленных сообщений об ошибках CODE_ERR_NAK.
0011: Return Slave Busy Cnt         Значение DATA в ответе содержит значение счётчика количества отправленных сообщений о «занятости» устройства CODE_ERR_BUSY.
0012: Return Bus Char. Overrun Cnt  Значение DATA в ответе содержит значение счётчика количества ошибок переполнения приема символов.
0013: Return Bus Char. Overrun Cnt  Значение DATA в ответе содержит значение счётчика количества ошибок переполнения приема символов.
0014: Clear Overrun Cnt and Flag    Сброс счётчика ошибок переполнения приема символов.
0015: Get/Clear Modbus+ Statistic   Запрос и сброс статистики Modbus Plus.

0x0B = Чтение счётчика событий (счётчика успешно выполненных запросов).
╔═══════╦═══╤═══╤═════╗    ╔═══════╦═══╤═══╤═════╤════════╤═════╗ ID       - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ CRC ║    ║  ADU: ║ID │COM│STATE│EventCNT│ CRC ║ COM      - Номер команды.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼─────┼────────┼─────╢ STATE    - Слово состояния:  FFFF - занят выполнением предыдущей команды, 0000 - сводобен.
║КолБайт║(1)│(1)│ (2) ║    ║КолБайт║(1)│(1)│ (2) │  (2)   │ (2) ║ EventCNT - Счётчик событий: Увеличивается после успешного выполнения любого запроса, кроме 0x0B.
║Индекс:║[0]│[1]│[2:3]║    ║Индекс:║[0]│[1]│[2:3]│ [4:5]  │[6:7]║
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼─────┼────────┼─────╢
║Пример:║01 │0B │41E7 ║    ║Пример:║01 │0B │FFFF │  0001  │XXXX ║ В примере модуль ответил, что он занят выполнением предыдущей команды, а значение счётчика событий равно 0x0001.
╚═══════╩═══╧═══╧═════╝    ╚═══════╩═══╧═══╧═════╧════════╧═════╝

0x0C = Чтение журнала событий.
╔═══════╦═══╤═══╤═════╗    ╔═══════╦═══╤═══╤═══════╤═════╤════════╤════════╤═════════════╤═════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│STATE│EventCNT│QueryCNT│    EVENTS   │ CRC ║ COM     - Номер команды.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼─────┼────────┼────────┼─────────────┼─────╢ sumBYTE  - Количество байт в полях STATE+EventCNT+QueryCNT+EVENTS.
║КолБайт║(1)│(1)│ (2) ║    ║КолБайт║(1)│(1)│  (1)  │ (2) │  (2)   │  (2)   │  (кратно 1) │ (2) ║ STATE    - Слово состояния:   FFFF - занят выполнением предыдущей команды, 0000 - сводобен.
║Индекс:║[0]│[1]│[2:3]║    ║Индекс:║[0]│[1]│  [2]  │[3:4]│ [5:6]  │ [7:8]  │[9:3+sumBYTE]│     ║ EventCNT - Счётчика событий:  Увеличивается после успешного выполнения любого запроса, кроме 0x0B.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼─────┼────────┼────────┼─────────────┼─────╢ QueryCNT - Счётчик сообщений: Увеличивается после получения любого запроса.
║Пример:║01 │0C │0025 ║    ║Пример:║01 │0C │  XX   │0000 │  0001  │  0001  │   EVENTS[]  │XXXX ║ EVENTS   - Журнал событий:    Содержит до 64 байт (приём запроса, обработка сообщения, выполнение перезагрузки, включение режима Listen Only Mode).
╚═══════╩═══╧═══╧═════╝    ╚═══════╩═══╧═══╧═══════╧═════╧════════╧════════╧═════════════╧═════╝
Типы байтов в журнале событий:
0x00        - Байт выполнения перезагрузки.
0x04        - Байт включения режима Listen Only Mode.
0x80...0xFF - Байт приёма запроса
              0 бит не используется.
              1 бит указывает на коммуникационную ошибку при принятии запроса.
              2 бит не используется.
              3 бит не используется.
              4 бит указывает на переполнение данных в запросе.
              5 бит указывает на то, что модуль находится в режиме "Только прослушивание" (Listen Only Mode).
              6 бит указывает на то, что получен широковещательный запрос (запрос с SlaveID==0).
              7 бит установлен в 1.
0x40...0x7F - Байт обработки сообщений
              0 бит указывает на наличие ошибки адреса регистра, команды или данных.
              1 бит указывает на наличие ошибки не определённой битом 0.
              2 бит указывает на занятость ведомого.
              3 бит указывает на программную ошибку.
              4 бит указывает на истечение Timeout для ответа.
              5 бит указывает на успех обработки сообщения.
              6 бит установлен в 1.
              7 бит сброшен в 0.
0x01...0x03 - Резерв.
0x05...0x3F - Резерв.

0x0F = Запись значений в несколько регистров флагов «DO».
╔═══════╦═══╤═══╤══════╤══════╤═══════╤════════════════════════════════╤════╗    ╔═══════╦═══╤═══╤══════╤══════╤═════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│sumBYTE│             DATA               │CRC ║    ║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼───────┼────────────────────────────────┼────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │  (1)  │        sumBYTE (кратно 1)      │(2) ║    ║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │  [6]  │          [7:7+sumBYTE]         │    ║    ║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║ sumBYTE - Количество байт DATA.
╟───────╫───┼───┼──────┼──────┼───────┼────────────────────────────────┼────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢ DATA    - Байты содержащие биты для записи в регистры «DO».
║Пример:║01 │0F │ 0000 │ 0014 │  03   │0b76543210-0bFEDCBA98-0b0000JIHG│XXXX║    ║Пример:║01 │0F │ 0000 │ 0014 │55C4 ║ В примере осуществляется запись в 0x0014 регистров «DO», начиная с адреса 0x0000.
╚═══════╩═══╧═══╧══════╧══════╧═══════╧════════════════════════════════╧════╝    ╚═══════╩═══╧═══╧══════╧══════╧═════╝ В первом байте DATA биты регистров DO[0]-DO[7], во втором биты DO[8]-DO[F], в третьем биты оставшихся 4 регистров, а не заполненные биты равны 0.

0x10 = Запись значений в несколько регистров хранения «AO».
╔═══════╦═══╤═══╤══════╤══════╤═══════╤═════════════════════════╤════╗    ╔═══════╦═══╤═══╤══════╤══════╤═════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│sumBYTE│           DATA          │CRC ║    ║  ADU: ║ID │COM│adrREG│sumREG│ CRC ║ COM     - Номер команды.
╟───────╫───┼───┼──────┼──────┼───────┼─────────────────────────┼────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢ adrREG  - Адрес первого регистра.
║КолБайт║(1)│(1)│ (2)  │ (2)  │  (1)  │    sumBYTE (кратно 2)   │(2) ║    ║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2) ║ sumREG  - Количество регистров.
║Индекс:║[0]│[1]│[2:3] │[4:5] │  [6]  │      [7:7+sumBYTE]      │    ║    ║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7]║ sumBYTE - Количество байт DATA.
╟───────╫───┼───┼──────┼──────┼───────┼─────────────────────────┼────╢ -> ╟───────╫───┼───┼──────┼──────┼─────╢ DATA    - Данные для записи в регистры «AO».
║Пример:║01 │10 │ 0003 │ 0004 │  08   │ AO[3] AO[4] AO[5] AO[6] │XXXX║    ║Пример:║01 │10 │ 0003 │ 0004 │31CA ║ В примере осуществляется запись в 0x0004 регистра «AO», начиная с адреса 0x0003.
╚═══════╩═══╧═══╧══════╧══════╧═══════╧═════════════════════════╧════╝    ╚═══════╩═══╧═══╧══════╧══════╧═════╝ Первые два байта DATA запишутся в регистр AO[3], вторые два байта в регистр AO[4] и т.д.

0x11 = Чтение информации об устройстве.
╔═══════╦═══╤═══╤═════╗    ╔═══════╦═══╤═══╤═══════╤═══╤════╤════════╤═══════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│ID*│WORK│  DATA  │  CRC  ║ COM     - Номер команды.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼───┼────┼────────┼───────╢ sumBYTE - Количество байт в полях ID*+WORK+DATA.
║КолБайт║(1)│(1)│ (2) ║    ║КолБайт║(1)│(1)│  (1)  │(1)│(1) │  (D)   │  (2)  ║ ID*     - Идентификатор линейки устройств. Линейка устройств iArduino имеет идентификатор 0x77.
║Индекс:║[0]│[1]│[2:3]║    ║Индекс:║[0]│[1]│  [2]  │[3]│[4] │ [5:XX] │       ║ WORK    - Индикатор пуска: 00=OFF, FF=ON.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼───┼────┼────────┼───────╢ DATA    - Добавочная информация. Размер зависит от устройства.
║Пример:║01 │11 │C02C ║    ║Пример:║01 │11 │       │77 │ FF │        │ XXXX  ║ В примере модуль ответил что его идентификатор равен 0x77 и устройство включено 0xFF.
╚═══════╩═══╧═══╧═════╝    ╚═══════╩═══╧═══╧═══════╧═══╧════╧════════╧═══════╝ 
Поле DATA для устройств iarduino состоит из 13 байт:
1  Адрес модуля SlaveID. Позволяет определить адрес модуля послав широковещательный запрос.
2  Идентификатор устройства.
3  Версия прошивки текщего устройства.
4  Старший байт Флагов состояния устройства (регистр диагностики).
5  Младший байт Флагов состояния устройства (регистр диагностики).
6  Количество регистров DO.
7  Количество регистров DI.
8  Количество регистров AO.
9  Количество регистров AI.
A  Старший байт задержки до ответного пакета ModBus RTU в мкс.
B  Средний байт задержки до ответного пакета ModBus RTU в мкс.
C  Средний байт задержки до ответного пакета ModBus RTU в мкс.
D  Младший байт задержки до ответного пакета ModBus RTU в мкс.

0x12 = Чтение названия устройства iArduino.
╔═══════╦═══╤═══╤═════╗    ╔═══════╦═══╤═══╤═══════╤══════════════════╤═══════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│       NAME       │  CRC  ║ COM     - Номер команды.
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼──────────────────┼───────╢ sumBYTE - Количество байт в поле NAME.
║КолБайт║(1)│(1)│ (2) ║    ║КолБайт║(1)│(1)│  (1)  │       (X)        │  (2)  ║ NAME    - Байты названия модуля в кодировке UTF-8.
║Индекс:║[0]│[1]│[2:3]║    ║Индекс:║[0]│[1]│  [2]  │       [3]        │       ║ 
╟───────╫───┼───┼─────╢ -> ╟───────╫───┼───┼───────┼──────────────────┼───────╢ Команда 0x12 не документирована, перед её использованием необходимо убедиться, что модуль
║Пример:║01 │12 │802D ║    ║Пример:║01 │12 │  1F   │pH-метр с дисплеем│ XXXX  ║ принадлежит к линейке устройств iArduino, воспользовавшись командой 0x11.
╚═══════╩═══╧═══╧═════╝    ╚═══════╩═══╧═══╧═══════╧══════════════════╧═══════╝ 

0x14 = Чтение из файла.
╔═══════╦═══╤═══╤═══════╤═══════════════════════════════════════════════════╤═════╗    ╔═══════╦═══╤═══╤═══════╤═════════════════════════════════════════════╤═════╗
║       ║   │   │       │                       FILES                       │     ║    ║       ║   │   │       │                    FILES                    │     ║ FILES   - Содержит от 1 до 10 блоков для каждого файла.
║  ADU: ║ID │COM│sumBYTE│┌────┬───┬──────┬──────┐   ┌────┬───┬──────┬──────┐│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│┌───┬────┬──────────┐   ┌───┬────┬──────────┐│ CRC ║ sumBYTE - Количество всех байт в поле FILES.
║       ║   │   │       ││TYPE│ № │adrREG│sumREG│   │TYPE│ № │adrREG│sumREG││     ║    ║       ║   │   │       ││SUM│TYPE│   DATA   │   │SUM│TYPE│   DATA   ││     ║ SUM     - Количество байт в блоке после байта SUM.
╟───────╫───┼───┼───────┤├────┼───┼──────┼──────┤...├────┼───┼──────┼──────┤├─────╢ -> ╟───────╫───┼───┼───────┤├───┼────┼──────────┤...├───┼────┼──────────┤├─────╢ TYPE    - Тип ссылки = 06
║КолБайт║(1)│(1)│  (1)  ││(1) │(2)│ (2)  │  (2) │   │(1) │(2)│ (2)  │  (2) ││ (2) ║    ║КолБайт║(1)│(1)│  (1)  ││(1)│(1) │(кратно 2)│   │(1)│(1) │(кратно 2)││ (2) ║ №       - Номер файла 0001...000A.
║Индекс:║[0]│[1]│  [2]  │└────┴───┴──────┴──────┘   └────┴───┴──────┴──────┘│     ║    ║Индекс:║[0]│[1]│  [2]  │└───┴────┴──────────┘   └───┴────┴──────────┘│     ║ adrREG  - Адрес первого регистра файла.
╟───────╫───┼───┼───────┼───────────────────────────────────────────────────┼─────╢ -> ╟───────╫───┼───┼───────┼─────────────────────────────────────────────┼─────╢ sumREG  - Количество читаемых регистров файла.
║Пример:║01 │14 │  0E   │ 06  0004  0001   0002       06 0003  0009   0001  │B4FC ║    ║Пример:║01 │14 │  0A   │ 05   06   F[1] F[2]     03   06     F[9]    │XXXX ║ DATA    - Массив двухбайтных данных F[X] прочитанный из файла.
╚═══════╩═══╧═══╧═══════╧═══════════════════════════════════════════════════╧═════╝    ╚═══════╩═══╧═══╧═══════╧═════════════════════════════════════════════╧═════╝

0x15 = Запись в файл
╔═══════╦═══╤═══╤═══════╤═════════════════════════════════════════════════════════════════════════════╤═════╗    ╔═══════════════════════════════════════════════════╗
║       ║   │   │       │                                      FILES                                  │     ║ -> ║ Ответ на запрос записи является его полной копией ║
║  ADU: ║ID │COM│sumBYTE│┌────┬───┬──────┬──────┬──────────────┐   ┌────┬───┬──────┬──────┬──────────┐│ CRC ║    ╚═══════════════════════════════════════════════════╝
║       ║   │   │       ││TYPE│ № │adrREG│sumREG│     DATA     │   │TYPE│ № │adrREG│sumREG│   DATA   ││     ║    FILES   - Содержит от 1 до 10 блоков для каждого файла.
╟───────╫───┼───┼───────┤├────┼───┼──────┼──────┼──────────────┤...├────┼───┼──────┼──────┼──────────┤├─────╢    sumBYTE - Количество всех байт в поле FILES.
║КолБайт║(1)│(1)│  (1)  ││(1) │(2)│ (2)  │  (2) │  (кратно 2)  │   │(1) │(2)│ (2)  │  (2) │(кратно 2)││ (2) ║    TYPE    - Тип ссылки = 06
║Индекс:║[0]│[1]│  [2]  │└────┴───┴──────┴──────┴──────────────┘   └────┴───┴──────┴──────┴──────────┘│     ║    №       - Номер файла 0001...000A.
╟───────╫───┼───┼───────┼─────────────────────────────────────────────────────────────────────────────┼─────╢    adrREG  - Адрес первого регистра файла.
║Пример:║01 │15 │  18   │ 06  0004  0007   0003  F[7] F[8] F[9]      06 0003  0005   0002   F[5] F[6] │XXXX ║    sumREG  - Количество записываемых регистров файла.
╚═══════╩═══╧═══╧═══════╧═════════════════════════════════════════════════════════════════════════════╧═════╝    DATA    - Массив двухбайтных данных F[X] для записи в файл.

0x16 = Запись значения в один регистр хранения «AO» с масками "И" и "ИЛИ"
╔═══════╦═══╤═══╤══════╤══════╤══════╤═════╗    ╔═══════════════════════════════════════════════════╗
║  ADU: ║ID │COM│adrREG│ AND  │  OR  │ CRC ║ -> ║ Ответ на запрос записи является его полной копией ║
╟───────╫───┼───┼──────┼──────┼──────┼─────╢    ╚═══════════════════════════════════════════════════╝
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2)  │ (2) ║    COM    - Номер команды.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7] │[8:9]║    adrREG - Адрес регистра.
╟───────╫───┼───┼──────┼──────┼──────┼─────╢    AND    - Маска запрещает менять биты (1-оставить без изменений, 0-взять бит из маски OR).
║Пример:║01 │16 │ 0004 │ 00F2 │ 0025 │67EE ║    OR     - Маска содержит биты для записи в регистр.
╚═══════╩═══╧═══╧══════╧══════╧══════╧═════╝    В примере AND=0b0000000011110010, OR=0b0000000000100101 => AO[0004]=0b00000000----01-1.    REG = (REG & AND) | (OR & ~AND)

0x17 = Чтение/запись нескольких регистров AO.
╔═══════╦═══╤═══╤══════╤══════╤══════╤══════╤═══════╤═══════════════════╤═════╗    ╔═══════╦═══╤═══╤═══════╤════════════════════╤════╗ ID                 - Адрес модуля SlaveID.
║  ADU: ║ID │COM│adrREG│sumREG│adrREG│sumREG│sumBYTE│        DATA       │ CRC ║    ║  ADU: ║ID │COM│sumBYTE│        DATA        │CRC ║ COM                - Номер команды.
║       ║   │   │ Read │ Read │Write │Write │ Write │        Write      │     ║    ║       ║   │   │ Read  │        Read        │    ║ adrREG  Read/Write - Адрес первого регистра для чтения/записи.
╟───────╫───┼───┼──────┼──────┼──────┼──────┼───────┼───────────────────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────┼────╢ sumREG  Read/Write - Количество регистров для чтения/записи.
║КолБайт║(1)│(1)│ (2)  │ (2)  │ (2)  │ (2)  │  (1)  │ sumBYTE (кратно 2)│ (2) ║    ║КолБайт║(1)│(1)│  (1)  │ sumBYTE (кратно 2) │(2) ║ sumBYTE Read/Write - Количество байт в поле DATA для чтения/записи.
║Индекс:║[0]│[1]│[2:3] │[4:5] │[6:7] │[8:9] │  [A]  │   [B:B+sumBYTE]   │     ║    ║Индекс:║[0]│[1]│  [2]  │    [3:3+sumBYTE]   │    ║ DATA    Read/Write - Байты данных для чтения/записи.
╟───────╫───┼───┼──────┼──────┼──────┼──────┼───────┼───────────────────┼─────╢ -> ╟───────╫───┼───┼───────┼────────────────────┼────╢ 
║Пример:║01 │17 │ 0004 │ 0006 │ 000C │ 0003 │  06   │ AO[C] AO[D] AO[E] │XXXX ║    ║Пример:║01 │17 │  0C   │       AO[4:9]      │XXXX║ В примере запрошены данные из 0x0006 регистров «AO», начиная с адреса 0x0004. Получено 0x0С байт DATA Read из регистров AO[4]-AO[9].
╚═══════╩═══╧═══╧══════╧══════╧══════╧══════╧═══════╧═══════════════════╧═════╝    ╚═══════╩═══╧═══╧═══════╧════════════════════╧════╝ В примере осуществляется запись в 0x0003 регистра «AO», начиная с адреса 0x000С, поле DATA Write содержит 0x06 байт для регистров AO[C]-AO[E].

0x18 = Чтение данных из буфера FIFO.
╔═══════╦═══╤═══╤═══════╤═════╗    ╔═══════╦═══╤═══╤═══════╤═══════╤═══════════════╤════╗ ID      - Адрес модуля SlaveID.
║  ADU: ║ID │COM│ardFIFO│ CRC ║    ║  ADU: ║ID │COM│sumBYTE│sumFIFO│     DATA      │CRC ║ COM     - Номер команды.
╟───────╫───┼───┼───────┼─────╢ -> ╟───────╫───┼───┼───────┼───────┼───────────────┼────╢ ardFIFO - Адрес указателя FIFO.
║КолБайт║(1)│(1)│  (2)  │ (2) ║    ║КолБайт║(1)│(1)│  (2)  │  (2)  │  (кратно 2)   │(2) ║ sumBYTE - Количество байт в поле sumFIFO+DATA.
║Индекс:║[0]│[1]│ [2:3] │[4:5]║    ║Индекс:║[0]│[1]│ [2:3] │ [4:5] │[6:6+sumFIFO*2]│    ║ sumFIFO - Счетчик FIFO (счётчик регистров в очереди).
╟───────╫───┼───┼───────┼─────╢ -> ╟───────╫───┼───┼───────┼───────┼───────────────┼────╢ DATA    - Массив двухбайтных данных FIFO.
║Пример:║01 │18 │ 04DE  │0347 ║    ║Пример:║01 │18 │ 000A  │ 0003  │   FIFO[0:3]   │XXXX║
╚═══════╩═══╧═══╧═══════╧═════╝    ╚═══════╩═══╧═══╧═══════╧═══════╧═══════════════╧════╝

АДРЕС МОДУЛЯ:
Модули на шине ModBus имеют уникальный адрес SlaveID от 1 до 247.
Модули отвечают на все адресованные им запросы, если они не находятся в режиме Listen Only Mode "Только прослушивание".
Запрос отправленный с адресом 0 является широковещательным. Такой запрос выполняют все модули, но не отвечают на него.
Модули iarduino отвечают на широковещательный запрос с командой 0x11 = Чтение информации об устройстве.

НОМЕР КОМАНДЫ:
Все запросы к модулям сожержат номер команды COM. Старший бит байта команды всегда сброшен в 0, по этому значения команд лежат в диапазоне от 1 до 127.
Ответы от модулей содержат номер команды на которую они отвечают.

ОТВЕТЫ ОШИБОК:
Если модуль обнаружил ошибку в запросе, или не может обработать сообщение, он отправляет ответ с кодом ошибки.
В ответе с кодом ошибки указывается номер команды с установленным старшим битом, по этому значения команд лежат в диапазоне от 129 до 255.

╔═══════╦═══╤═══╤═════╤═════╗
║  ADU: ║ID │COM│ERROR│ CRC ║ ID    - Адрес модуля SlaveID.
╟───────╫───┼───┼─────┼─────╢ COM   - Номер команды на которую отправляется ответ с установленным старшим битом (0x05|0b10000000=0x85).
║КолБайт║(1)│(1)│ (1) │ (2) ║ ERROR - Код ошибки.
║Индекс:║[0]│[1]│ [2] │ (2) ║
╟───────╫───┼───┼─────┼─────╢
║Пример:║01 │85 │ 03  │0347 ║ В примере модуль сообщает что полученный запрос с командой 0x05 не выполнен по причине обнаружения ошибки 0x03 (ошибочные данные).
╚═══════╩═══╧═══╧═════╧═════╝
ERROR:
0x01  ILLEGAL FUNCTION                         Ошибка команды. Номер команды или функции в запросе неизвестен модулю или не может быть обработан.
0x02  ILLEGAL DATA ADDRESS                     Ошибка адреса. Адрес регистра в запросе лежит за пределами диапазона.
0x03  ILLEGAL DATA VALUE                       Ошибка данных. Недопустимое значение в поле данных запроса.
0x04  SLAVE DEVICE FAILURE                     Иная ошибка. Любая невосстановимая ошибка кроме первых трёх.
0x05  ACKNOWLEDGE                              Запрос принят, но на обработку требуется время. Предупреждение для мастера.
0x06  SLAVE DEVICE BUSY                        Ведомый занят, запрос проигнорирован. Повторите запрос позже.
0x07                                           Невозможно выполнить запрос с командами 0xD или 0xE.
0x08  MEMORY PARITY ERROR                      Ошибка чтения/записи файла.
0x0A  GATEWAY PATH UNAVAILABLE                 Шлюз неправильно настроен или перегружен запросами.
0x0B  GATEWAY TARGET DEVICE FAILED TO RESPOND  Slave устройства нет в сети или от него нет ответа. Интересно, кто отправляет такую ошибку ))).

РЕГИСТРЫ ОБЩИЕ ДЛЯ ВСЕЙ ЛИНЕЙКИ IARDUINO:

Регистр  DO[0x0100]        устанавливается после подтверждения смены адреса модуля SlaveID.
Регистры DO[0x0101-0x01F7] запрещают менять адрес модуля SlaveID в режиме выбора случайного адреса.
                           если DO[0x01AB]==1, то модуль не выберет адрес 0xAB в режиме выбора случайного адреса.
                           если DO[0x01CD]==1 и текущий адрес SlaveID==0xCD, то модуль не будет менять свой адрес в режиме выбора случайного адреса.
Регистры AO[0x010X]        подтверждают изменение адреса, скорости, типа протокола modbus. При чтени возвращают 0x0000.
Регистры AO[0x011X]        позволяют менять адрес на шине, скорость шины, тип протокола modbus. При чтени возвращают 0xYYXX, где YY - случайное число, XX - текущий адрес, скорость или тип.
Регистр  AO[0x0120]        хранит любое пользовательское значение в энергонезависимой памяти. Значение по умолчанию 0x0000. При записи нового значения модуль будет занят в течении 50 мс.

Смена адреса:
Запись AO[0x0110]=0x0000   приведёт к смене SlaveID временно (до отключения питания), на случайное число (режим выбора случайного адреса).
Запись AO[0x0110]=0x00XX   приведёт к смене SlaveID временно (до отключения питания). XX-новый адрес: 1...247.
Запись AO[0x0110]=0xFFXX   приведёт к смене SlaveID с сохранением в Flash память.     XX-новый адрес: 1...247.
Запись AO[0x0100]=0xF0A5   подтверждает смену адреса. Если подтверждается смена адреса с сохранением в Flash память, то модуль будет занят в течении 50 мс.
                           Если смену адреса не подтвердить в течении 2 секунд после его записи в AO[0x0110], модуль вернёт прежний адрес.

Смена скорости шины:
Запись AO[0x0111]=0x00XX   приведёт к смене скорости временно (до отключения питания). XX-новая скорость/2400: 1=2400, 2=4800, 4=9600, 8=19200, 16=38400, 24=57600, 48=115200.
Запись AO[0x0111]=0xFFXX   приведёт к смене скорости с сохранением в Flash память.     XX-новая скорость/2400: 1=2400, 2=4800, 4=9600, 8=19200, 16=38400, 24=57600, 48=115200.
Запись AO[0x0101]=0xF0A5   подтверждает смену скорости. Если подтверждается смена скорости с сохранением в Flash память, то модуль будет занят в течении 50 мс.
                           Если смену скорости не подтвердить в течении 2 секунд после её записи в AO[0x0111], модуль вернёт прежнюю скорость.

Смена типа протокола:
Запись AO[0x0112]=0x00XX   приведёт к смене типа протокола modbus временно (до отключения питания). XX-может принимать одно из двух значений: 00-MODBUS_RTU, FF-MODBUS_ASCII.
Запись AO[0x0112]=0xFFXX   приведёт к смене типа протокола modbus с сохранением в Flash память.     XX-может принимать одно из двух значений: 00-MODBUS_RTU, FF-MODBUS_ASCII.
Запись AO[0x0102]=0xF0A5   подтверждает смену типа протокола modbus. Если подтверждается смена типа протокола modbus с сохранением в Flash память, то модуль будет занят в течении 50 мс.
                           Если смену типа протокола modbus не подтвердить в течении 2 секунд после её записи в AO[0x0112], модуль вернёт прежний тип протокола modbus.
