Эмулирует до 30 независимых Modbus RTU slave устройств на одном последовательном порту.
Каждое устройство отвечает на FC03 (Read Holding Registers) — 20 регистров.
Значения регистров могут быть:
- Из файла — текстовый файл, обновляемый внешним скриптом (реальные данные датчиков: I2C, 1-Wire, sysfs и т.д.)
- Случайные — случайные
uint16значения (тестирование шины, проверка таймаутов мастера)
Работает на Linux (x86_64, aarch64) и Windows (x64).
Создан для встраиваемых систем — один статический бинарь, без зависимостей, без записи на SD карту (tmpfs).
modbus_slave/
├── bin/
│ ├── modbus_slave # Linux x86_64 бинарь
│ ├── modbus_slave_aarch64 # Linux aarch64 статический бинарь (NAPI2, RK3568, RPi)
│ └── modbus_slave.exe # Windows x64 бинарь
├── service/
│ └── modbus_slave.service # systemd unit файл
└── src/
├── modbus_core.h # Платформонезависимая логика Modbus
├── modbus_slave.c # Linux платформа (termios, fork, syslog)
└── modbus_slave_win.c # Windows платформа (Win32 API)
gcc -O2 -Wall -o bin/modbus_slave src/modbus_slave.caarch64-linux-gnu-gcc -O2 -Wall -static -o bin/modbus_slave_aarch64 src/modbus_slave.cx86_64-w64-mingw32-gcc -O2 -Wall -o bin/modbus_slave.exe src/modbus_slave_win.cgcc -O2 -Wall -o modbus_slave.exe src/modbus_slave_win.ccl /O2 src\modbus_slave_win.cmodbus_slave -p <порт> -b <скорость> [-a <n>] [-o <режим>] [-f <id>:<файл>] [-t <сек>] [-d]
modbus_slave -k
modbus_slave -s
modbus_slave.exe -p <порт> -b <скорость> [-a <n>] [-o <режим>] [-f <id>:<файл>] [-t <сек>] [-bg]
modbus_slave.exe -k
modbus_slave.exe -s
| Опция | Описание |
|---|---|
-p <порт> |
Последовательный порт. Linux: /dev/ttyUSB0, /dev/ttyS7. Windows: COM3, \\.\COM10 |
-b <скорость> |
Скорость: 1200..921600 |
-a <n> |
Количество slave устройств: 1..30 (по умолчанию 1). ID назначаются 1..n |
-o <режим> |
Параметры порта: 8N1 8E1 8O1 7E1 8N2 (по умолчанию 8N1) |
-f <id>:<файл> |
Привязать файл регистров к slave <id>. Можно указывать несколько раз. Slave без -f использует случайные значения |
-t <сек> |
Максимальный возраст файла в секундах (по умолчанию 10). Устаревший файл → нули. -t 0 отключает проверку |
-d |
(Linux) Запустить как демон. Логи → syslog |
-bg |
(Windows) Запустить в фоне. Логи → C:\temp\modbus_slave.log |
-k |
Остановить запущенный демон / фоновый процесс |
-s |
Показать статус демона |
Одно целое число без знака (0..65535) на строку, до 20 строк.
Недостающие строки → значение регистра 0.
Файл отсутствует → все регистры 0.
Пример /tmp/sensor1.dat:
4523
1013
0
0
0
0
0
0
0
0
4523 = 45.23 °C (соглашение: температура × 100)
printf "4523\n1013\n" > /tmp/s1.tmp && mv /tmp/s1.tmp /tmp/s1.datecho 4523 > C:\temp\s1.tmp
echo 1013 >> C:\temp\s1.tmp
move /Y C:\temp\s1.tmp C:\temp\s1.dat# сервер
./modbus_slave -p /dev/ttyUSB0 -b 115200
# клиент
mbpoll -m rtu -b 115200 -P none -a 1 -r 1 -c 20 /dev/ttyUSB0# сервер
./modbus_slave -p /dev/ttyUSB0 -b 115200 -a 5
# клиент — опрос датчика с ID 3
mbpoll -m rtu -b 115200 -P none -a 3 -r 1 -c 20 /dev/ttyUSB0# сервер — датчики 1,2 из файлов; датчики 3,4,5 случайные
./modbus_slave -p /dev/ttyUSB0 -b 115200 -a 5 \
-f 1:/tmp/cpu.dat \
-f 2:/tmp/time.dat
# клиент
mbpoll -m rtu -b 115200 -P none -a 1 -r 1 -c 20 /dev/ttyUSB0# сервер
./modbus_slave -d -p /dev/ttyS7 -b 115200 -a 10 \
-f 1:/tmp/cpu.dat \
-t 15
# клиент (с PC через RS-485 адаптер)
mbpoll -m rtu -b 115200 -P none -a 1 -r 1 -c 20 /dev/ttyUSB0
# логи
journalctl -t modbus_slave -f# сервер
modbus_slave.exe -p COM4 -b 115200 -a 3 -f 1:C:\temp\s1.dat -f 2:C:\temp\s2.dat
# клиент
mbpoll -m rtu -b 115200 -P none -a 1 -r 1 -c 20 COM4modbus_slave.exe -bg -p COM4 -b 115200 -a 3 -f 1:C:\temp\s1.dat
modbus_slave.exe -s
modbus_slave.exe -kСтатистика выводится каждые 60 секунд с меткой времени, счётчиком за интервал и разбивкой по каждому датчику с указанием источника данных:
[2026-03-31 14:25:00] stats: slaves=3 interval_ok=180 interval_err=0 total_ok=3600 total_err=0
id=1 ok=60 src=file/tmp/cpu.dat
id=2 ok=60 src=file/tmp/time.dat
id=3 ok=60 src=random
Если файл регистров устарел (не обновлялся дольше -t секунд):
file /tmp/cpu.dat is stale (45s > 10s), returning zeros
chmod +x scripts/cpu_temp_to_modbus.sh
./scripts/cpu_temp_to_modbus.sh /tmp/cpu.dat 5 &Читает из /sys/class/thermal/thermal_zone*/temp.
Значение в регистре: °C × 100 (например 4523 = 45.23 °C).
chmod +x scripts/time_to_modbus.sh
./scripts/time_to_modbus.sh /tmp/time.dat 1 &| Регистр | Значение | Диапазон |
|---|---|---|
| 0 | Часы | 0..23 |
| 1 | Минуты | 0..59 |
| 2 | Секунды | 0..59 |
| 3 | День | 1..31 |
| 4 | Месяц | 1..12 |
| 5 | Год | 2025.. |
| 6 | День недели | 1=Пн..7=Вс |
| 7..19 | Резерв | 0 |
sudo cp bin/modbus_slave /usr/local/bin/
sudo cp service/modbus_slave.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable modbus_slave
sudo systemctl start modbus_slaveОтредактируй /etc/systemd/system/modbus_slave.service — укажи нужный порт, скорость и файлы -f.
# Просмотр логов
journalctl -u modbus_slave -fЕсли скрипт-источник данных упал, файл регистров перестаёт обновляться.
Без защиты мастер будет бесконечно читать устаревшие значения.
С параметром -t 10 (по умолчанию): если файл не обновлялся более 10 секунд,
все его регистры возвращают ноль — неисправность сразу видна мастеру.
file /tmp/cpu.dat is stale (45s > 10s), returning zeros
Отключить: -t 0 (если файлы обновляются редко).
| Параметр | Значение |
|---|---|
| Протокол | Modbus RTU |
| Поддерживаемые FC | FC03 — Read Holding Registers |
| Количество регистров | 20 на slave (адреса 0..19) |
| Максимум устройств | 30 (ID 1..30) |
| Разделитель фреймов | 10 мс тишина между символами |
| CRC | CRC16 (полином 0xA001) |
| Платформа | ОС | Примечание |
|---|---|---|
| x86_64 | Ubuntu 24 | разработка / тестирование |
| aarch64 | Armbian (NAPI2 / RK3568J) | основная цель |
| x64 | Windows 10/11 | через MinGW |
Проект разработан командой NAPI Lab и в первую очередь
тестируется на промышленных одноплатных компьютерах NAPI на базе Rockchip SoC.
Если вы ищете надёжную аппаратную платформу для запуска modbus_slave в production —
посмотрите линейку плат NAPI:
👉 github.com/napilab/napi-boards
- NAPI2 — RK3568J, RS-485 на борту, Armbian
- NAPI-C — RK3308, компактный, промышленного класса
Dmitrii Novikov (@dmnovikov)
NAPI Lab
Claude (Anthropic)
ИИ-ассистент и соавтор — архитектура, код, документация
MIT