1. Вступ

MB2HAL — це універсальний компонент HAL, що не працює в реальному часі, для зв’язку з одним або кількома пристроями Modbus. Наразі існує два варіанти зв’язку з пристроєм Modbus:

  1. Один із варіантів — створити компонент HAL як драйвер, див. VFD Modbus.

  2. Іншим варіантом є використання Classic Ladder з вбудованим Modbus, див. ClassicLadder.

  3. Тепер є третій варіант, який складається з "загального" драйвера, налаштованого текстовим файлом, він називається MB2HAL.

Чому варто обрати MB2HAL? Розгляньте можливість використання MB2HAL, якщо:

  • Вам потрібно написати новий драйвер, і ви нічого не знаєте про програмування.

  • Для керування з’єднаннями Modbus потрібно використовувати "лише" Classic Ladder.

  • Вам потрібно виявити та налаштувати перші транзакції Modbus. MB2HAL має рівні налагодження для полегшення низькорівневого налагодження протоколу.

  • У вас є більше одного пристрою для підключення. MB2HAL дуже ефективно управляє декількома пристроями, транзакціями та посиланнями. В даний час я контролюю два двоосьові драйвери за допомогою порту Rs232, драйвер VFD за допомогою іншого порту Rs232 та віддалений ввід/вивід за допомогою TCP/IP.

  • Вам потрібен протокол для підключення вашого Arduino до HAL. Перегляньте доданий зразок файлу конфігурації, ескізу та бібліотеки для Arduino Modbus.

2. Застосування

  1. Створіть конфігураційний файл з наведеного нижче прикладу

    1. Встановити назву компонента (необов’язково)

      Отримати HAL_MODULE_NAME=mymodule (за замовчуванням HAL_MODULE_NAME=mb2hal)

    2. Завантажити компонент Modbus HAL, що не працює в режимі реального часу

  2. Назва компонента за замовчуванням: loadusr -W mb2hal config=config_file.ini

  3. Назва користувацького компонента: loadusr -Wn mymodule mb2hal config=config_file.ini

3. Опції

3.1. Розділ ініціалізації

[MB2HAL_INIT]

Значення Тип Обов’язково Опис

INIT_DEBUG

Ціле число

Ні

Рівень налагодження ініціалізації та розбору INI-файлів.
0 = беззвучно
1 = повідомлення про помилки (за замовчуванням)
2 = повідомлення про підтвердження OK
3 = повідомлення про налагодження
4 = максимальна кількість повідомлень про налагодження (лише в транзакціях)

ВЕРСІЯ

Рядок

Ні

Номер версії у форматі N.N[NN]. За замовчуванням — 1.0.

HAL_MODULE_NAME

Рядок

Ні

Назва модуля (компонента) HAL. За замовчуванням — «mb2hal».

SLOWDOWN

Float

Ні

Вставте затримку «FLOAT секунд» між транзакціями, щоб уникнути великої кількості записів у журналі та полегшити налагодження. Корисно при використанні DEBUG=3 (НЕ INIT_DEBUG=3). Це впливає на ВСІ транзакції. Для нормальної роботи використовуйте «0.0».

TOTAL_TRANSACTIONS

Ціле число

Так

Загальна кількість транзакцій Modbus. Максимальної кількості немає..

3.2. Розділи транзакцій

Для кожної транзакції необхідний один розділ транзакції, починаючи з [TRANSACTION_00] і послідовно збільшуючи номер. Якщо є нове посилання (не транзакція), ви повинні вказати ОБОВ’ЯЗКОВІ параметри вперше. Попередження: будь-які НЕОБОВ’ЯЗКОВІ параметри, які не вказані, копіюються з попередньої транзакції.

Значення Тип Обов’язково Опис

LINK_TYPE

Рядок

Так

Ви повинні вказати посилання "serial" або "tcp" для першої транзакції. Якщо не вказано посилання попередньої транзакції, наступні транзакції використовуватимуть його.

TCP_IP

IP-адреса

Якщо LINK_TYPE=tcp

IP-адреса веденого пристрою Modbus. Ігнорується, якщо LINK_TYPE=serial.

TCP_PORT

Ціле число

Ні

TCP-порт веденого пристрою Modbus. За замовчуванням 502. Ігнорується, якщо LINK_TYPE=serial.

SERIAL_PORT

Рядок

Якщо LINK_TYPE=serial

Послідовний порт. Наприклад, "/dev/ttyS0". Ігнорується, якщо LINK_TYPE=tcp.

SERIAL_BAUD

Ціле число

Якщо LINK_TYPE=serial

Швидкість передачі даних. Ігнорується, якщо LINK_TYPE=tcp.

SERIAL_BITS

Ціле число

Якщо LINK_TYPE=serial

Біти даних. Один з 5, 6, 7, 8. Ігнорується, якщо LINK_TYPE=tcp.

SERIAL_PARITY

Рядок

Якщо LINK_TYPE=serial

Парність даних. Одне з: парне, непарне, жодного. Ігнорується, якщо LINK_TYPE=tcp.

SERIAL_STOP

Ціле число

Якщо LINK_TYPE=serial

Стоп-біти. Один з 1, 2. Ігнорується, якщо LINK_TYPE=tcp.

SERIAL_DELAY_MS

Ціле число

Якщо LINK_TYPE=serial

Затримка послідовного порту між транзакціями лише цього розділу. У мс. За замовчуванням 0. Ігнорується, якщо LINK_TYPE=tcp.

MB_SLAVE_ID

Ціле число

Так

Номер веденого пристрою Modbus.

FIRST_ELEMENT

Ціле число

Так

Адреса першого елемента.

NELEMENTS

Ціле число

Якщо не вказано PIN_NAMES

Кількість елементів. Вказувати одночасно NELEMENTS та PIN_NAMES є помилкою. Назви контактів будуть послідовними номерами, наприклад, mb2hal.plcin.01.

PIN_NAMES

Список

Якщо не вказано NELEMENTS

Список імен елементів. Ці імена будуть використовуватися для імен контактів, наприклад mb2hal.plcin.cycle_start.
ПРИМІТКА: У списку не повинно бути пробілів. Приклад: PIN_NAMES=cycle_start,stop,feed_hold

MB_TX_CODE

Рядок

Так

Код функції транзакції Modbus (див. посилання: специфікації):

• fnct_01_read_coils
• fnct_02_read_discrete_inputs
• fnct_03_read_holding_registers
• fnct_04_read_input_registers
• fnct_05_write_single_coil
• fnct_06_write_single_register
• fnct_15_write_multiple_coils
• fnct_16_write_multiple_registers

MB_RESPONSE_TIMEOUT_MS

Ціле число

Ні

Тайм-аут відповіді для цієї транзакції. У мс. За замовчуванням 500 мс. Це час очікування першого байта перед виникненням помилки.

MB_BYTE_TIMEOUT_MS

Ціле число

Ні

Тайм-аут байта для цієї транзакції. У мс. За замовчуванням 500 мс. Це час очікування від байта до байта, перш ніж виникне помилка.

HAL_TX_NAME

Рядок

Ні

Замість номера транзакції використовуйте ім’я. Приклад: mb2hal.00.01 може стати mb2hal.plcin.01. Ім’я не повинно перевищувати 28 символів. ПРИМІТКА: при використанні імен будьте обережні, щоб не створити дві транзакції з однаковим ім’ям.

MAX_UPDATE_RATE

Float

Ні

Максимальна частота оновлення в Гц. За замовчуванням встановлено значення 0,0 (0,0 = як тільки з’явиться можливість = нескінченно). ПРИМІТКА: Це максимальна частота, фактична частота може бути нижчою. Якщо ви хочете обчислити її в мс, використовуйте (1000 / required_ms). Приклад: 100 мс = MAX_UPDATE_RATE=10.0, оскільки 1000,0 мс / 100,0 мс = 10,0 Гц.

НАЛАГОДЖЕННЯ

Рядок

Ні

Рівень налагодження лише для цієї транзакції. Див. параметр INIT_DEBUG вище.

3.3. Коди помилок

Під час налагодження транзакцій зверніть увагу, що повернене значення "ret[]" відповідає:

Винятки протоколу Modbus:

  • 0x01 - ILLEGAL_FUNCTION - код FUNCTION, отриманий у запиті, є недозволеним або недійсним.

  • 0x02 - ILLEGAL_DATA_ADDRESS - адреса даних, отримана в запиті, не є допустимою адресою для ведомого пристрою або є недійсною.

  • 0x03 - ILLEGAL_DATA_VALUE - значення, що міститься в полі запиту даних, не є допустимим або недійсним.

  • 0x04 - SLAVE_DEVICE_FAILURE - ЗБІЙ ПІДЛЕЖЕНОГО (або ГОЛОВНОГО) пристрою, що неможливо відновити, під час спроби виконання запитуваної дії.

  • 0x04 - SERVER_FAILURE - (див. вище).

  • 0x05 - ПІДТВЕРДЖЕННЯ - Ця відповідь повертається для ЗАПОБІГАННЯ ЧАСУ ОЧИЩЕННЯ (PREVENT A TIMEOUT) у головному пристрої. Для обробки запиту у веденому пристрої потрібен тривалий час.

  • 0x06 - SLAVE_DEVICE_BUSY - Ведений пристрій (або сервер) ЗАЙНЯТИЙ. Повторіть запит пізніше.

  • 0x06 - SERVER_BUSY - (див. вище).

  • 0x07 - NEGATIVE_ACKNOWLEDGE - Невдалий запит на програмування з використанням коду функції 13 або 14.

  • 0x08 - MEMORY_PARITY_ERROR - Помилка парності SLAVE в ПАМ’ЯТІ.

  • 0x0A (-10) - GATEWAY_PROBLEM_PATH - Шлях(и) шлюзу недоступні.

  • 0x0B (-11) - GATEWAY_PROBLEM_TARGET - Цільовий пристрій не відповів (згенеровано головним, а не ведомим пристроєм).

Програма або з’єднання:

  • 0x0C (-12) - COMM_TIME_OUT

  • 0x0D (-13) - PORT_SOCKET_FAILURE

  • 0x0E (-14) - SELECT_FAILURE

  • 0x0F (-15) - TOO_MANY_DATAS

  • 0x10 (-16) - INVALID_CRC

  • 0x11 (-17) - INVALID_EXCEPTION_CODE

4. Приклад конфігураційного файлу

Натисніть тут для завантаження.

#This .INI file is also the HELP, MANUAL and HOW-TO file for mb2hal.

#Load the Modbus HAL userspace module as the examples below,
#change to match your own HAL_MODULE_NAME and INI file name
#Using HAL_MODULE_NAME=mb2hal or nothing (default): loadusr -W mb2hal config=config_file.ini
#Using HAL_MODULE_NAME=mymodule: loadusr -Wn mymodule mb2hal config=config_file.ini

# ++++++++++++++++++++++++
# Common section
# ++++++++++++++++++++++++
[MB2HAL_INIT]

#OPTIONAL: Debug level of init and INI file parsing.
# 0 = silent.
# 1 = error messages (default).
# 2 = OK confirmation messages.
# 3 = debugging messages.
# 4 = maximum debugging messages (only in transactions).
INIT_DEBUG=3

#OPTIONAL: Set to 1.1 to enable the new functions:
# - fnct_01_read_coils
# - fnct_05_write_single_coil
# - changed pin names (see https://linuxcnc.org/docs/2.9/html/drivers/mb2hal.html#_pins).
VERSION=1.1

#OPTIONAL: HAL module (component) name. Defaults to "mb2hal".
HAL_MODULE_NAME=mb2hal

#OPTIONAL: Insert a delay of "FLOAT seconds" between transactions in order
#to not to have a lot of logging and facilitate the debugging.
#Useful when using DEBUG=3 (NOT INIT_DEBUG=3)
#It affects ALL transactions.
#Use "0.0" for normal activity.
SLOWDOWN=0.0

#REQUIRED: The number of total Modbus transactions. There is no maximum.
TOTAL_TRANSACTIONS=9

# ++++++++++++++++++++++++
# Transactions
# ++++++++++++++++++++++++
#One transaction section is required per transaction, starting at 00 and counting up sequentially.
#If there is a new link (not transaction), you must provide the REQUIRED parameters 1st time.
#Warning: Any OPTIONAL parameter not specified are copied from the previous transaction.
[TRANSACTION_00]

#REQUIRED: You must specify either a "serial" or "tcp" link for the first transaction.
#Later transaction will use the previous transaction link if not specified.
LINK_TYPE=tcp

#if LINK_TYPE=tcp then REQUIRED (only 1st time): The Modbus slave device ip address.
#if LINK_TYPE=serial then IGNORED
TCP_IP=192.168.2.10

#if LINK_TYPE=tcp then OPTIONAL.
#if LINK_TYPE=serial then IGNORED
#The Modbus slave device tcp port. Defaults to 502.
TCP_PORT=502

#if LINK_TYPE=serial then REQUIRED (only 1st time).
#if LINK_TYPE=tcp then IGNORED
#The serial port.
SERIAL_PORT=/dev/ttyS0

#if LINK_TYPE=serial then REQUIRED (only 1st time).
#if LINK_TYPE=tcp then IGNORED
#The baud rate.
SERIAL_BAUD=115200

#if LINK_TYPE=serial then REQUIRED (only 1st time).
#if LINK_TYPE=tcp then IGNORED
#Data bits. One of 5,6,7,8.
SERIAL_BITS=8

#if LINK_TYPE=serial then REQUIRED (only 1st time).
#if LINK_TYPE=tcp then IGNORED
#Data parity. One of: even, odd, none.
SERIAL_PARITY=none

#if LINK_TYPE=serial then REQUIRED (only 1st time).
#if LINK_TYPE=tcp then IGNORED
#Stop bits. One of 1, 2.
SERIAL_STOP=2

#if LINK_TYPE=serial then OPTIONAL:
#if LINK_TYPE=tcp then IGNORED
#Serial port delay between for this transaction only.
#In ms. Defaults to 0.
SERIAL_DELAY_MS=10

#REQUIRED (only 1st time).
#Modbus slave number.
MB_SLAVE_ID=1

#REQUIRED: The first element address (decimal integer).
FIRST_ELEMENT=0

#REQUIRED unless PIN_NAMES is specified: The number of elements.
#It is an error to specify both NELEMENTS and PIN_NAMES
#The pin names will be sequential numbers e.g mb2hal.plcin.01
#NELEMENTS=4

#REQUIRED unless NELEMENTS is specified: A list of element names.
#these names will be used for the pin names, e.g mb2hal.plcin.cycle_start
#NOTE: there must be no white space characters in the list
PIN_NAMES=cycle_start,stop,feed_hold

#REQUIRED: Modbus transaction function code (see www.modbus.org specifications).
#    fnct_01_read_coils               (01 = 0x01) (new in 1.1)
#    fnct_02_read_discrete_inputs     (02 = 0x02)
#    fnct_03_read_holding_registers   (03 = 0x03)
#    fnct_04_read_input_registers     (04 = 0x04)
#    fnct_05_write_single_coil        (05 = 0x05) (new in 1.1)
#    fnct_06_write_single_register    (06 = 0x06)
#    fnct_15_write_multiple_coils     (15 = 0x0F)
#    fnct_16_write_multiple_registers (16 = 0x10)
#
# Created pins:
# fnct_01_read_coils:
# fnct_02_read_discrete_inputs:
#     mb2hal.m.n.bit     (output)
#     mb2hal.m.n.bit-inv (output)
# fnct_03_read_holding_registers:
# fnct_04_read_input_registers:
#     mb2hal.m.n.float   (output)
#     mb2hal.m.n.int     (output)
# fnct_05_write_single_coil:
#     mb2hal.m.n.bit     (input)
#         NELEMENTS needs to be 1 or PIN_NAMES must contain just one name.
# fnct_06_write_single_register:
#     mb2hal.m.n.float   (input)
#     mb2hal.m.n.int     (input)
#     NELEMENTS needs to be 1 or PIN_NAMES must contain just one name.
#     Both pin values are added and limited to 65535 (UINT16_MAX). Normally use one and let the other open (read as 0).
# fnct_15_write_multiple_coils:
#     mb2hal.m.n.bit     (input)
# fnct_16_write_multiple_registers:
#     mb2hal.m.n.float   (input)
#     mb2hal.m.n.int     (input)
#     Both pin values are added and limited to 65535 (UINT16_MAX). Normally use one and let the other open (read as 0).
#
# m = HAL_TX_NAME or transaction number if not set, n = element number (NELEMENTS) or name from PIN_NAMES
# Example: mb2hal.00.01.<type> (transaction=00, second register=01 (00 is the first one))
#          mb2hal.TxName.01.<type> (HAL_TX_NAME=TxName, second register=01 (00 is the first one))
MB_TX_CODE=fnct_03_read_holding_registers

#OPTIONAL: Response timeout for this transaction. In INTEGER ms. Defaults to 500 ms.
#This is how much to wait for 1st byte before raise an error.
MB_RESPONSE_TIMEOUT_MS=500

#OPTIONAL: Byte timeout for this transaction. In INTEGER ms. Defaults to 500 ms.
#This is how much to wait from byte to byte before raise an error.
MB_BYTE_TIMEOUT_MS=500

#OPTIONAL: Instead of giving the transaction number, use a name.
#Example: mb2hal.00.01 could become mb2hal.plcin.01
#The name must not exceed 28 characters.
#NOTE: when using names be careful that you dont end up with two transactions
#using the same name.
HAL_TX_NAME=remoteIOcfg

#OPTIONAL: Maximum update rate in HZ. Defaults to 0.0 (0.0 = as soon as available = infinite).
#NOTE: This is a maximum rate and the actual rate may be lower.
#If you want to calculate it in ms use (1000 / required_ms).
#Example: 100 ms = MAX_UPDATE_RATE=10.0, because 1000.0 ms / 100.0 ms = 10.0 Hz
MAX_UPDATE_RATE=0.0

#OPTIONAL: Debug level for this transaction only.
#See INIT_DEBUG parameter above.
DEBUG=2

#While DEBUGGING transactions note the returned "ret[]" value correspond to:
#/* Modbus protocol exceptions */
#ILLEGAL_FUNCTION        -0x01 the FUNCTION code received in the query is not allowed or invalid.
#ILLEGAL_DATA_ADDRESS    -0x02 the DATA ADDRESS received in the query is not an allowable address for the slave or is invalid.
#ILLEGAL_DATA_VALUE      -0x03 a VALUE contained in the data query field is not an allowable value or is invalid.
#SLAVE_DEVICE_FAILURE    -0x04 SLAVE (or MASTER) device unrecoverable FAILURE while attempting to perform the requested action.
#SERVER_FAILURE          -0x04 (see above).
#ACKNOWLEDGE             -0x05 This response is returned to PREVENT A TIMEOUT in the master.
#                              A long duration of time is required to process the request in the slave.
#SLAVE_DEVICE_BUSY       -0x06 The slave (or server) is BUSY. Retrasmit the request later.
#SERVER_BUSY             -0x06 (see above).
#NEGATIVE_ACKNOWLEDGE    -0x07 Unsuccessful programming request using function code 13 or 14.
#MEMORY_PARITY_ERROR     -0x08 SLAVE parity error in MEMORY.
#GATEWAY_PROBLEM_PATH    -0x0A (-10) Gateway path(s) not available.
#GATEWAY_PROBLEM_TARGET  -0x0B (-11) The target device failed to respond (generated by master, not slave).
#/* Program or connection */
#COMM_TIME_OUT           -0x0C (-12)
#PORT_SOCKET_FAILURE     -0x0D (-13)
#SELECT_FAILURE          -0x0E (-14)
#TOO_MANY_DATAS          -0x0F (-15)
#INVALID_CRC             -0x10 (-16)
#INVALID_EXCEPTION_CODE  -0x11 (-17)

[TRANSACTION_01]
MB_TX_CODE=fnct_01_read_coils
FIRST_ELEMENT=1024
NELEMENTS=24
HAL_TX_NAME=remoteIOin
MAX_UPDATE_RATE=0.0
DEBUG=1

[TRANSACTION_02]
MB_TX_CODE=fnct_02_read_discrete_inputs
FIRST_ELEMENT=1280
NELEMENTS=8
HAL_TX_NAME=readStatus
MAX_UPDATE_RATE=0.0

[TRANSACTION_03]
MB_TX_CODE=fnct_05_write_single_coil
FIRST_ELEMENT=100
NELEMENTS=1
HAL_TX_NAME=setEnableout
MAX_UPDATE_RATE=0.0

[TRANSACTION_04]
MB_TX_CODE=fnct_15_write_multiple_coils
FIRST_ELEMENT=150
NELEMENTS=10
HAL_TX_NAME=remoteIOout
MAX_UPDATE_RATE=0.0

[TRANSACTION_05]
LINK_TYPE=serial
SERIAL_PORT=/dev/ttyS0
SERIAL_BAUD=115200
SERIAL_BITS=8
SERIAL_PARITY=none
SERIAL_STOP=2
SERIAL_DELAY_MS=50
MB_SLAVE_ID=1
MB_TX_CODE=fnct_03_read_holding_registers
FIRST_ELEMENT=1
NELEMENTS=2
HAL_TX_NAME=XDrive01
MAX_UPDATE_RATE=0.0
DEBUG=1

[TRANSACTION_06]
MB_TX_CODE=fnct_04_read_input_registers
FIRST_ELEMENT=12
NELEMENTS=3
HAL_TX_NAME=XDrive02
MAX_UPDATE_RATE=10.0
DEBUG=1

[TRANSACTION_07]
MB_TX_CODE=fnct_06_write_single_register
FIRST_ELEMENT=20
NELEMENTS=1
HAL_TX_NAME=XDrive03
MAX_UPDATE_RATE=0.0
DEBUG=1

[TRANSACTION_08]
MB_TX_CODE=fnct_16_write_multiple_registers
FIRST_ELEMENT=55
NELEMENTS=8
HAL_TX_NAME=XDrive04
MAX_UPDATE_RATE=10.0
DEBUG=1

5. Піни

Note

Жовтий = Нове в MB2HAL 1.1 (LinuxCNC 2.9). Щоб використовувати ці нові функції, потрібно встановити VERSION = 1.1.

m = Значення HAL_TX_NAME, якщо встановлено, або номер транзакції
n = Номер елемента (NELEMENTS) або назва з PIN_NAMES

Приклад:

  • mb2hal.00.01.int (TRANSACTION_00, другий регістр)

  • mb2hal.readStatus.01.bit (HAL_TX_NAME=readStatus, first bit)

5.1. fnct_01_read_coils

  • mb2hal.m.n.bit bit out

  • mb2hal.m.n.bit-inv bit out

5.2. fnct_02_read_discrete_inputs

  • mb2hal.m.n.bit bit out

  • mb2hal.m.n.bit-inv bit out

5.3. fnct_03_read_holding_registers

  • mb2hal.m.n.float float out

  • mb2hal.m.n.int s32 out

5.4. fnct_04_read_input_registers

  • mb2hal.m.n.float float out

  • mb2hal.m.n.int s32 out

5.5. fnct_05_write_single_coil

  • mb2hal.m.n.bit bit in

NELEMENTS має бути 1, або PIN_NAMES має містити лише одне ім’я.

5.6. fnct_06_write_single_register

  • mb2hal.m.n.float float in

  • mb2hal.m.n.int s32 in

NELEMENTS має дорівнювати 1, або PIN_NAMES має містити лише одну назву. Обидва значення виводів додаються та обмежені значенням 65535 (UINT16_MAX). Використовуйте одне, а інше розмикайте (читайте як 0).

5.7. fnct_15_write_multiple_coils

  • mb2hal.m.n.bit bit in

5.8. fnct_16_write_multiple_registers

  • mb2hal.m.n.float float in

  • mb2hal.m.n.int s32 in

Обидва значення виводів додаються та обмежені значенням 65535 (UINT16_MAX). Використовуйте один, а інший розімкнутий (зчитується як 0).