pre-alpha

This commit is contained in:
Edward Emelianov 2025-07-11 11:13:40 +03:00
parent 01abbf4a25
commit c35f38ccd6
14 changed files with 1253 additions and 0 deletions

59
modbus_params/Makefile Normal file
View File

@ -0,0 +1,59 @@
# run `make DEF=...` to add extra defines
PROGRAM := modbus_par
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
LDFLAGS += -lusefull_macros -lmodbus
SRCS := $(wildcard *.c)
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
OBJDIR := mk
CFLAGS += -O2 -Wall -Wextra -Wno-trampolines
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o))
DEPS := $(OBJS:.o=.d)
TARGFILE := $(OBJDIR)/TARGET
CC = gcc
#TARGET := RELEASE
ifeq ($(shell test -e $(TARGFILE) && echo -n yes),yes)
TARGET := $(file < $(TARGFILE))
else
TARGET := RELEASE
endif
ifeq ($(TARGET), DEBUG)
.DEFAULT_GOAL := debug
endif
release: CFLAGS += -flto
release: LDFLAGS += -flto
release: $(PROGRAM)
debug: CFLAGS += -DEBUG -Werror
debug: TARGET := DEBUG
debug: $(PROGRAM)
$(TARGFILE): $(OBJDIR)
@echo -e "\t\tTARGET: $(TARGET)"
@echo "$(TARGET)" > $(TARGFILE)
$(PROGRAM) : $(TARGFILE) $(OBJS)
@echo -e "\t\tLD $(PROGRAM)"
$(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM)
$(OBJDIR):
@mkdir $(OBJDIR)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
$(OBJDIR)/%.o: %.c
@echo -e "\t\tCC $<"
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
clean:
@echo -e "\t\tCLEAN"
@rm -rf $(OBJDIR) 2>/dev/null || true
xclean: clean
@rm -f $(PROGRAM)
.PHONY: clean xclean

18
modbus_params/Readme Normal file
View File

@ -0,0 +1,18 @@
modbus_par: reading/writing/dumping modbus registers using `dictionary`
-D, --dictionary=arg file with dictionary (format: code register value writeable)
-O, --outdic=arg output dictionary for full device dump by input dictionary registers
-R, --readc registers (by keycodes, checked by dictionary) to read; multiply parameter
-W, --writec write new value to register by keycode (format: keycode=val); multiply parameter
-b, --baudrate=arg modbus baudrate (default: 9600)
-d, --device=arg modbus device (default: /dev/ttyUSB0)
-h, --help show this help
-k, --dumpkey dump entry with this keycode; multiply parameter
-o, --outfile=arg file with parameter's dump
-r, --readr registers (by address) to read; multiply parameter
-s, --slave=arg slave ID (default: 1)
-t, --dumptime=arg dumping time interval (seconds, default: 0.1)
-v, --verbose verbose level (each -v adds 1)
-w, --writer write new value to register (format: reg=val); multiply parameter

View File

@ -0,0 +1,522 @@
# awk '{printf "%s\t%s\t%s\t0\t# ", $1, $2, $3; $1=""; $2=""; $3=""; print $0}' orig > dictionary.dic
F00.00 61440 1 0 # Управление двигателем (V/F)
F00.01 61441 0 0 # Выбор задания команды ПУСК [0-с клавиатуры; 3,4 Modbus RTU]
F00.02 61442 0 0 # Тип связи [0 - MODbus RTU]
F00.03 61443 5000 0 # Максимальная частота для П.Ч. х100, Гц [от F00.04 до 500.00 Гц] (750 rpm)
F00.04 61444 5000 0 # Верхний предел рабочей частоты х100, Гц [F00.05 - F00.03] (610 rpm)
F00.05 61445 0 0 # Минимальная частота х100, Гц [от 0.00 до F00.04 Гц]
F00.06 61446 0 0 # Источник частоты А от … [0 — 9] [9 Modbus RTU]
F00.07 61447 0 0 # Источник частоты B от … [0 — 9] (3)
F00.08 61448 0 0 # Задание частоты по каналу B [0 макс.частота; 1-частота канала A]
F00.09 61449 1000 0 # Максимальная частота по каналу В х10 в % (100 rpm)
F00.10 61450 0 0 # Комбинированный режим регулирования [от 0 до 5] (0 => только А)
F00.11 61451 5000 0 # Частота комбинированного режима х100, Гц [от 0.00 до F00.03] (600 rpm)
F00.12 61452 100 0 # Время разгона 1 х 10, сек. (30s)
F00.13 61453 100 0 # Время торможения 1 х 10, сек. (30s)
F00.14 61454 0 0 # Направление вращения [от 0 CW; 1 CCW; 2 запрет CCW]
F00.15 61455 50 0 # Несущая частота модуляции 1 х 10 [от 2.0 до 10.0 кГц] (5 kHz)
F00.16 61456 0 0 # Отслеживание скорости [от 0 до 2]
F00.17 61457 0 0 # Автонастройка двигателя [0 off;1 on with run; 2 - on without run;]
F00.18 61458 0 0 # Сброс параметров [от 0 до 3; 0 - без сброса]
F01.00 61696 0 0 # Тип запуска: 0 — запуск со стартовой частоты; 1 — запуск после торможения; 2 — запуск с поиском скорости
F01.01 61697 50 0 # Стартовая частота х100, [от 0 до 10 Гц] (7,5/101.48 = 0,074 rpm каток)
F01.02 61698 0 0 # Время удержания стартовой частоты х10, [от 0.0 до 100.0 сек.] (тест 1 с.)
F01.03 61699 0 0 # Ток торможения перед стартом х10, % [от 00 до 150.0%]
F01.04 61700 0 0 # Время торможения перед стартом х10, сек. [от 0.0 до 100.0 сек]
F01.05 61701 0 0 # Тип разгона/торможения [0 — линейный; 1 — S кривая;]
F01.06 61702 300 0 # Стартовая фаза S-кривой х10, % [от 0.0 — 50.0% времени разг./торм.]
F01.07 61703 300 0 # Конечная фаза S-кривой х10, % [от 0.0 — 50.0% времени разг./торм.]
F01.08 61704 0 0 # Метод остановки [0 — замедление до остан.; 1 — свободн. выбег]
F01.09 61705 0 0 # Частота включения торможения постоянным током х100, Гц
F01.10 61706 0 0 # Время ожидания торможения постоянным током х10, сек. [0 до100]
F01.11 61707 0 0 # Постоянный ток торможения во время остановки х10, % [0 до100]
F01.12 61708 0 0 # Время торможения пост. током во время остановки х10, сек.
F01.13 61709 0 0 # Время бездействия между сменой направлений вращения х10, сек.
F01.14 61710 50 0 # Частота остановки х10, Гц
F01.15 61711 0 0 # Зарезервировано
F01.16 61712 0 0 # Зарезервировано
F01.17 61713 0 0 # Перезапуск с клемм после включения [0 — не действ. 1 - действует]
F01.18 61714 0 0 # Перезапуск после потери напряжения [0 — запрет; 1 - перезапуск]
F01.19 61715 10 0 # Задержка перезапуска х10, сек. [0.0 до 6000.0] (Только если F1.18 = 1)
F01.20 61716 0 0 # Зарезервировано
F01.21 61717 0 0 # Действие, если выходная частота меньше минимальной; 0 — работа на мин.частоте; 1 - остановка; 2 - работа на нулевой скорости вращения.
F01.22 61718 5000 0 # Задание частоты при работе в пожарном режиме (х100), Гц.
F02.00 61952 0 0 # Тип нагрузки [0 — тип G; 1 тип P;]
F02.01 61953 0 0 # Тип двигателя [0 - АСИНХРОННЫЙ]
F02.02 61954 15 0 # Мощность двигателя х10, кВт (5.5 кВт)
F02.03 61955 380 0 # Напряжение двигателя, В [0 — 1000.0] (380 В)
F02.04 61956 65 0 # Номинальный ток х10, А (14.8А)
F02.05 61957 5000 0 # Номинальная частота для двигателя х100, Гц
F02.06 61958 1450 0 # Номинальные обороты двигателя по паспорту, об/мин
F02.07 61959 1414 0 # Сопротивление статора х100, Ом (Значение после автонастройки!)
F02.08 61960 1264 0 # Сопротивление ротора х100, Ом (Значение после автонастройки!)
F02.09 61961 67 0 # Индуктивность рассеивания х10, мГн (Значение после автонастройки!)
F02.10 61962 956 0 # Индуктивность двигателя х10, мГн (Значение после автонастройки!)
F02.11 61963 33 0 # Ток холостого хода х10, А (Значение после автонастройки!)
F02.12 61964 880 0 # Зарезервировано
F02.13 61965 810 0 # Зарезервировано
F02.14 61966 750 0 # Зарезервировано
F02.15 61967 0 0 # Выбор типа энкодера
F02.16 61968 1024 0 # Число импульсов энкодера на оборот
F02.17 61969 0 0 # Последовательность фаз энкодера ABZ
F02.18 61970 1 0 # Количество пар полюсов резольвера
F02.19 61971 1 0 # Зарезервировано
F02.20 61972 3 0 # Зарезервировано
F02.21 61973 3 0 # Зарезервировано
F02.22 61974 10 0 # Зарезервировано
F02.23 61975 10 0 # Зарезервировано
F02.24 61976 1000 0 # Зарезервировано
F02.25 61977 1 0 # Защита от перегрузки [0 — не действует; 1 — действует;]
F02.26 61978 1000 0 # Коэффициент защиты от перегрузки х10, % [F02.26 x F02.04]
F03.00 62208 30 0 # Пропорциональный коэффициент контура скорости 1
F03.01 62209 50 0 # Время интегрирования контура скорости 1 х1000, сек
F03.02 62210 500 0 # Пороговое значение низкой скорости х100, Гц
F03.03 62211 20 0 # Пропорциональный коэффициент контура скорости 2
F03.04 62212 100 0 # Время интегрирования контура скорости 2 х1000, сек
F03.05 62213 1000 0 # Пороговое значение высокой скорости 2 х100, Гц
F03.06 62214 15 0 # Коэффициент фильтрации обратной связи х100, сек
F03.07 62215 0 0 # Пропорциональный коэффициент контура тока 1
F03.08 62216 0 0 # Время интегрирования контура тока 1
F03.09 62217 0 0 # Пропорциональный коэффициент контура тока 2
F03.10 62218 0 0 # Время интегрирования контура тока 2
F03.11 62219 0 0 # Выбор канала ограничения крутящего момента
F03.12 62220 0 0 # Выбор канала ограничения момента торможения
F03.13 62221 1500 0 # Цифровое задание крутящего момента х10, %
F03.14 62222 1500 0 # Цифровое задание момента торможения х10, %
F03.15 62223 100 0 # Коэффициент ограничения момента
F03.16 62224 100 0 # Коэффициент компенсации скольжения, %
F04.00 62464 0 0 # Выбор кривой V/F (линейная х-ка)
F04.01 62465 0 0 # Усиление момента х10, %
F04.02 62466 200 0 # Частота усиления момента х10, % ((300rpm/750rpm)*100)*10%
F04.03 62467 0 0 # V/F частота 1 х100, Гц
F04.04 62468 0 0 # V/F напряжение 1 х10, %
F04.05 62469 0 0 # V/F частота 2 х100, Гц
F04.06 62470 0 0 # V/F напряжение 2 х10, %
F04.07 62471 0 0 # V/F частота 3 х100, Гц
F04.08 62472 0 0 # V/F напряжение 3 х10, %
F04.09 62473 100 0 # Компенсация скольжения х10, %
F04.10 62474 2 0 # Контроль вибрации при низкой частоте
F04.11 62475 2 0 # Контроль вибрации при высокой частоте
F04.12 62476 3000 0 # Порог контроля вибрации х100, Гц
F04.13 62477 0 0 # Выбор кривой V/F Мотор 2
F04.14 62478 0 0 # Усиление момента х10, %
F04.15 62479 200 0 # Частота усиления момента х10, %
F04.16 62480 0 0 # V/F частота 1 х100, Гц
F04.17 62481 0 0 # V/F напряжение 1 х10, %
F04.18 62482 0 0 # V/F частота 2 х100, Гц
F04.19 62483 0 0 # V/F напряжение 2 х10, %
F04.20 62484 0 0 # V/F частота 3 х100, Гц
F04.21 62485 0 0 # V/F напряжение 3 х10, %
F04.22 62486 1000 0 # Компенсация скольжения х10, %
F04.23 62487 2 0 # Контроль вибрации при низкой частоте
F04.24 62488 2 0 # Контроль вибрации при высокой частоте
F04.25 62489 3000 0 # Порог контроля вибрации х100, Гц
F04.26 62490 0 0 # Энергосбережение
F04.27 62491 0 0 # Установка напряжения
F04.28 62492 1000 0 # Задание с клавиатуры х10, %
F04.29 62493 50 0 # Время повышения напряжения х10, сек.
F04.30 62494 50 0 # Время понижения напряжения х10, сек.
F04.31 62495 1000 0 # Максимальное выходное напряжение х10, %
F04.32 62496 0 0 # Минимальное выходное напряжение х10, %
F04.33 62497 1 0 # Выбор функции АВР
F04.34 62498 400 0 # Зарезервировано
F05.00 62720 0 0 # Выбор клеммы DI5
F05.01 62721 1 0 # Клемма DI1
F05.02 62722 4 0 # Клемма DI2
F05.03 62723 7 0 # Клемма DI3
F05.04 62724 0 0 # Клемма DI4
F05.05 62725 0 0 # Клемма DI5 (дискретный)
F05.06 62726 0 0 # Клемма DI6
F05.07 62727 0 0 # Клемма DI7 (опционально)
F05.08 62728 0 0 # Клемма DI8 (опционально)
F05.09 62729 0 0 # Выбор полярности входных клемм
F05.10 62730 10 0 # Фильтр дребезга входных клемм х1000, сек.
F05.11 62731 0 0 # Настройка управления входных клемм
F05.12 62732 0 0 # Настройка подключения входных клемм
F05.13 62733 0 0 # Задержка включения клеммы DI1 х1000, сек.
F05.14 62734 0 0 # Задержка выключения клеммы DI1 х1000, сек.
F05.15 62735 0 0 # Задержка включения клеммы DI2 х1000, сек.
F05.16 62736 0 0 # Задержка выключения клеммы DI2 х1000, сек.
F05.17 62737 0 0 # Задержка включения клеммы DI3 х1000, сек.
F05.18 62738 0 0 # Задержка выключения клеммы DI3 х1000, сек.
F05.19 62739 0 0 # Задержка включения клеммы DI4 х1000, сек.
F05.20 62740 0 0 # Задержка выключения клеммы DI4 х1000, сек.
F05.21 62741 0 0 # Задержка включения клеммы DI5 х1000, сек.
F05.22 62742 0 0 # Задержка выключения клеммы DI5 х1000, сек.
F05.23 62743 0 0 # Задержка включения клеммы DI6 х1000, сек.
F05.24 62744 0 0 # Задержка выключения клеммы DI6 х1000, сек.
F05.25 62745 0 0 # Задержка включения клеммы DI7 х1000, сек.
F05.26 62746 0 0 # Задержка выключения клеммы DI7 х1000, сек.
F05.27 62747 0 0 # Задержка включения клеммы DI8 х1000, сек.
F05.28 62748 0 0 # Задержка выключения клеммы DI8 х1000, сек.
F05.29 62749 0 0 # Зарезервировано
F05.30 62750 0 0 # Нижний предел частоты DI5 х100, КГц
F05.31 62751 0 0 # Настройка нижнего предела частоты DI5 х10, %
F05.32 62752 5000 0 # Верхний предел частоты DI5 х100, КГц
F05.33 62753 1000 0 # Настройка верхнего предела частоты DI5 х10, %
F05.34 62754 100 0 # Время фильтрации DI5 х1000, сек.
F05.35 62755 0 0 # Режим работы клеммы пожарного режима
F06.00 62976 0 0 # Конфигурация клеммы HDO1
F06.01 62977 0 0 # Функция клеммы DO1
F06.02 62978 0 0 # Функция клеммы HDO1
F06.03 62979 1 0 # Функция реле Т1
F06.04 62980 5 0 # Функция реле Т2
F06.05 62981 0 0 # Выбор полярности выходных клемм
F06.06 62982 0 0 # Задержка включения клеммы DO1 х1000, сек.
F06.07 62983 0 0 # Задержка выключения клеммы DO1 х1000, сек.
F06.08 62984 0 0 # Задержка включения клеммы НDO1 х1000, сек.
F06.09 62985 0 0 # Задержка выключения клеммы НDO1 х1000, сек.
F06.10 62986 0 0 # Задержка включения реле Т1 х1000, сек.
F06.11 62987 0 0 # Задержка выключения реле Т1 х1000, сек.
F06.12 62988 0 0 # Задержка включения реле Т2 х1000, сек.
F06.13 62989 0 0 # Задержка выключения реле Т2 х1000, сек.
F06.14 62990 0 0 # Выход АО1
F06.15 62991 0 0 # Выход АО2
F06.16 62992 0 0 # Выход HDO1 (высокоскоростной выход)
F06.17 62993 0 0 # Нижний предел АО1 х10. %
F06.18 62994 200 0 # Значение нижнего предела АО1 х100, В
F06.19 62995 1000 0 # Верхний предел АО1 х10, %
F06.20 62996 1000 0 # Значение верхнего предела АО1 х100, В
F06.21 62997 0 0 # Время фильтрации выхода АО1 х1000, сек.
F06.22 62998 0 0 # Нижний предел АО2 х10, %
F06.23 62999 0 0 # Значение нижнего предела АО2 х100, В
F06.24 63000 1000 0 # Верхний предел АО2 х10, %
F06.25 63001 1000 0 # Значение верхнего предела АО2 х100, В
F06.26 63002 0 0 # Время фильтрации выхода АО2 х1000, сек.
F06.27 63003 0 0 # Нижний предел HDO1 х10, %
F06.28 63004 0 0 # Значение нижнего предела HDO1 х100, КГц
F06.29 63005 1000 0 # Верхний предел HDO1 х10, %
F06.30 63006 5000 0 # Значение верхнего предела HDO1 х100, КГц
F06.31 63007 0 0 # Время фильтрации выхода HDO1 х1000, сек.
F06.32 63008 1 0 # Функция управления тормозом
F06.33 63009 500 0 # Частота отпускания тормоза при подъеме х100, Гц
F06.34 63010 20 0 # Ток отпускания тормоза при подъеме, % от ном.тока
F06.35 63011 600 0 # Частота задержки отпускания тормоза при подъеме х100, Гц
F06.36 63012 2 0 # Время задержки отпускания тормоза при подъеме х10, сек.
F06.37 63013 500 0 # Частота включения тормоза при подъеме х100, Гц
F06.38 63014 450 0 # Частота задержки включения тормоза при подъеме х100, Гц
F06.39 63015 2 0 # Время задержки включения тормоза при подъеме х10, сек.
F06.40 63016 500 0 # Частота отпускания тормоза при спуске х100, Гц
F06.41 63017 20 0 # Ток отпускания тормоза при спуске, % от ном.тока
F06.42 63018 600 0 # Частота задержки отпускания тормоза при спуске х100, Гц
F06.43 63019 2 0 # Время задержки отпускания тормоза при спуске х100, сек.
F06.44 63020 500 0 # Частота включения тормоза при спуске х100, Гц
F06.45 63021 450 0 # Частота задержки включения тормоза при спуске х100, сек.
F06.46 63022 2 0 # Время задержки включения тормоза при спуске х10, сек.
F06.47 63023 1000 0 # Ограничение момента при включенном тормозе х10, %
F07.00 63232 0 0 # Пароль пользователя
F07.01 63233 0 0 # Выбор функции кнопки S
F07.02 63234 255 0 # Параметры состояния 1
F07.03 63235 255 0 # Параметры состояния 2
F07.04 63236 255 0 # Параметры состояния при остановке
F07.05 63237 100 0 # Коэффициент частоты х100
F07.06 63238 1000 0 # Скорость вращения х10, %
F07.07 63239 10 0 # Коэффициент линейной скорости х10, %
F07.08 63240 36 0 # Температура выпрямителя, С
F07.09 63241 36 0 # Температура инвертора, С
F07.10 63242 60770 0 # Версия ПО
F07.11 63243 0 0 # Время наработки, час.
F07.12 63244 0 0 # Нижний предел сигнализации AI1, В
F07.13 63245 680 0 # Верхний предел сигнализации AI1, В
F07.14 63246 0 0 # Выбор канала ограничения верхнего предела выхода ПИД-регулятора
F07.15 63247 15 0 # Номинальная мощность ПЧ х10, КВт
F07.16 63248 380 0 # Номинальное напряжение, В
F07.17 63249 75 0 # Номинальный ток х10, А
F07.18 63250 0 0 # Текущая ошибка
F07.19 63251 0 0 # Ошибка при предыдущем отключении
F07.20 63252 0 0 # Ошибка при 2-м отключении
F07.21 63253 0 0 # Ошибка при 3-м отключении
F07.22 63254 0 0 # Ошибка при 4-м отключении
F07.23 63255 0 0 # Ошибка при 5-м отключении
F07.24 63256 0 0 # Частота в момент текущей аварии х100, Гц
F07.25 63257 0 0 # Опорная частота в момент текущей аварии х100, Гц
F07.26 63258 0 0 # Выходное напряжение в момент текущей аварии, В
F07.27 63259 0 0 # Выходной ток в момент текущей аварии х10, В
F07.28 63260 0 0 # Напряжение звена постоянного тока в момент текущей аварии х10, В
F07.29 63261 0 0 # Максимальная температура ПЧ в момент текущей аварии х10, С
F07.30 63262 0 0 # Состояние входных клемм в момент текущей аварии
F07.31 63263 0 0 # Состояние выходных клемм в момент текущей аварии
F07.32 63264 0 0 # Выходная частота в момент предыдущей аварии х100, Гц
F07.33 63265 0 0 # Опорная частота в момент предыдущей аварии х100, Гц
F07.34 63266 0 0 # Выходное напряжение в момент предыдущей аварии, В
F07.35 63267 0 0 # Выходной ток в момент предыдущей аварии х10, А
F07.36 63268 0 0 # Напряжение звена постоянного тока в момент предыдущей аварии х10, В
F07.37 63269 0 0 # Максимальная температура ПЧ в момент предыдущей аварии х10, С
F07.38 63270 0 0 # Состояние входных клемм в момент предыдущей аварии
F07.39 63271 0 0 # Состояние выходных клемм в момент предыдущей аварии
F07.40 63272 0 0 # Частота в момент 2-й аварии х100, Гц
F07.41 63273 0 0 # Опорная частота в момент 2-й аварии х100, Гц
F07.42 63274 0 0 # Выходное напряжение в момент 2-й аварии, В
F07.43 63275 0 0 # Выходной ток в момент 2-й аварии х10, А
F07.44 63276 0 0 # Напряжение звена постоянного тока в момент 2-й аварии, В
F07.45 63277 0 0 # Максимальная температура ПЧ в момент 2-й аварии х10, С
F07.46 63278 0 0 # Состояние входных клемм в момент 2-й аварии
F07.47 63279 0 0 # Состояние выходных клемм в момент 2-й аварии
F08.00 63488 100 0 # Время разгона 2 х10, сек.
F08.01 63489 100 0 # Время торможения 2 х10, сек.
F08.02 63490 100 0 # Время разгона 3 х10, сек.
F08.03 63491 100 0 # Время торможения 3 х10, сек.
F08.04 63492 100 0 # Время разгона 4 х10, сек.
F08.05 63493 100 0 # Время торможения 4 х10, сек.
F08.06 63494 500 0 # Толчковая частота х100, Гц
F08.07 63495 100 0 # Время разгона толчкового режима х10, сек.
F08.08 63496 100 0 # Время торможения толчкового режима х10, сек.
F08.09 63497 0 0 # Количество сбросов аварии
F08.10 63498 10 0 # Время задержки автоматического сброса х10, сек.
F08.11 63499 0 0 # Контроль снижения частоты х100, Гц
F08.12 63500 0 0 # Переключение двигателя
F08.13 63501 5000 0 # Уровень достижения частоты FDT1 х100, Гц
F08.14 63502 50 0 # Удержание FDT1 х10, %
F08.15 63503 5000 0 # Уровень достижения частоты FDT1 х100, Гц
F08.16 63504 50 0 # Удержание FDT2 х10, %
F08.17 63505 0 0 # Ширина обнаружения частоты х100, Гц
F08.18 63506 1 0 # Тормозной прерыватель
F08.19 63507 3800 0 # Уровень напряжения срабатывания х10, В
F08.20 63508 0 0 # Компенсация ШИМ
F08.21 63509 0 0 # Функция кнопок пульта
F08.22 63510 10 0 # Время задержки кнопок 'ВВЕРХ'/'ВНИЗ х10, сек.'
F08.23 63511 0 0 # Задание кнопок 'ВВЕРХ'/'ВНИЗ'
F08.24 63512 50 0 # Время задержки кнопки 'ВВЕРХ' х100, сек.
F08.25 63513 50 0 # Время задержки кнопки 'ВНИЗ' х100, сек.
F08.26 63514 0 0 # Частота при потере питания
F08.27 63515 50 0 # Торможение магнитным потоком х100, сек.
F08.28 63516 1 0 # Вспомогательный мониторинг
F08.29 63517 0 0 # Копирование параметров (только для панели)
F08.30 63518 0 0 # Дополнительная плата входов/выходов
F08.31 63519 0 0 # Торможение при потере питания
F08.32 63520 0 0 # Время торможения при потере питания х10, сек.
F08.33 63521 2000 0 # Напряжение срабатывания, В
F08.34 63522 5000 0 # Произвольная частота 1 х100, Гц
F08.35 63523 0 0 # Ширина обнаружения произвольной частоты 1
F08.36 63524 5000 0 # Произвольная частота 2 х100, Гц
F08.37 63525 0 0 # Ширина обнаружения произвольной частоты 2
F08.38 63526 0 0 # Толчковый режим во время работы
F09.00 63744 0 0 # Источник задания уставки ПИД
F09.01 63745 500 0 # Уставка ПИД х10, %
F09.02 63746 0 0 # Обратная связь ПИД
F09.03 63747 0 0 # Тип обратной связи
F09.04 63748 200 0 # Пропорциональная составляющая (Кр) х10
F09.05 63749 20 0 # Интегральная составляющая (Ti) х10
F09.06 63750 0 0 # Дифференциальная составляющая (Td) х100
F09.07 63751 10 0 # Цикл выборки(T) х100, сек.
F09.08 63752 2 0 # Предел отклонения ПИД х10, %
F09.09 63753 1000 0 # Верхний предел ПИД х10, %
F09.10 63754 0 0 # Нижний предел ПИД х10, %
F09.11 63755 0 0 # Величина сигнала обратной связи, активирущая ошибку пропажи сигнала х10, %
F09.12 63756 10 0 # Задержка включения ошибки пропажи сигнала х10, сек.
F09.13 63757 0 0 # Зарезервировано
F09.14 63758 50 0 # Пропорциональная составляющая 2 (Кр2) х100
F09.15 63759 20 0 # Интегральная составляющая 2 (Ti2) х100
F09.16 63760 0 0 # Дифференциальная составляющая 2 (Td2) х100
F09.17 63761 0 0 # Переключение ПИД параметров
F09.18 63762 200 0 # Пороговое отклонение ПИД х10, %
F09.19 63763 600 0 # Частота засыпания х100, %
F09.20 63764 0 0 # Задержка засыпания х10, сек.
F09.21 63765 0 0 # Коэффициент пробуждения х10, %
F09.22 63766 5 0 # Задержка пробуждения х10, сек
F09.23 63767 0 0 # Предустановленное значение ПИД х10, %
F09.24 63768 0 0 # Время удержания предустановленного значения ПИД х10, сек.
F0A.00 64000 0 0 # Частота колебаний х10, %
F0A.01 64001 0 0 # Амплитуда частоты толчка х10, сек.
F0A.02 64002 0 0 # Время увеличения частоты колебаний х10, сек.
F0A.03 64003 0 0 # Время снижения частоты колебаний х10, сек.
F0A.04 64004 0 0 # Установка длины, м
F0A.05 64005 0 0 # Заданная длина, м
F0A.06 64006 1 0 # Количество импульсов на оборот
F0A.07 64007 1000 0 # Длина окружности вала х100, м
F0A.08 64008 1000 0 # Множитель х1000
F0A.09 64009 1000 0 # Корректирующий коэффициент х1000
F0A.10 64010 0 0 # Установленное значение счетчика
F0A.11 64011 0 0 # Определяемое значение счетчика
F0A.12 64012 0 0 # Время работы, мин.
F0A.13 64013 0 0 # Метод остановки
F0A.14 64014 0 0 # Зарезервировано
F0B.00 64256 0 0 # Режим простого ПЛК
F0B.01 64257 0 0 # Режим работы ПЛК при перебое с питанием
F0B.02 64258 0 0 # Многоскоростной режим 0 х10, %
F0B.03 64259 0 0 # Время работы в режиме 0 х10, сек.
F0B.04 64260 0 0 # Многоскоростной режим 1 х10, %
F0B.05 64261 0 0 # Время работы в режиме 1 х10, сек.
F0B.06 64262 0 0 # Многоскоростной режим 2 х10, %
F0B.07 64263 0 0 # Время работы в режиме 2 х10, сек.
F0B.08 64264 0 0 # Многоскоростной режим 3 х10, %
F0B.09 64265 0 0 # Время работы в режиме 3 х10, сек.
F0B.10 64266 0 0 # Многоскоростной режим 4 х10, %
F0B.11 64267 0 0 # Время работы в режиме 4 х10, сек.
F0B.12 64268 0 0 # Многоскоростной режим 5 х10, %
F0B.13 64269 0 0 # Время работы в режиме 5 х10, сек.
F0B.14 64270 0 0 # Многоскоростной режим 6 х10, %
F0B.15 64271 0 0 # Время работы в режиме 6 х10, сек.
F0B.16 64272 0 0 # Многоскоростной режим 7 х10, %
F0B.17 64273 0 0 # Время работы в режиме 7 х10, сек.
F0B.18 64274 0 0 # Многоскоростной режим 8 х10, %
F0B.19 64275 0 0 # Время работы в режиме 8 х10, сек.
F0B.20 64276 0 0 # Многоскоростной режим 9 х10, %
F0B.21 64277 0 0 # Время работы в режиме 9 х10, сек.
F0B.22 64278 0 0 # Многоскоростной режим 10 х10, %
F0B.23 64279 0 0 # Время работы в режиме 10 х10, сек.
F0B.24 64280 0 0 # Многоскоростной режим 11 х10, %
F0B.25 64281 0 0 # Время работы в режиме 11 х10, сек.
F0B.26 64282 0 0 # Многоскоростной режим 12 х10, %
F0B.27 64283 0 0 # Время работы в режиме 12 х10, сек.
F0B.28 64284 0 0 # Многоскоростной режим 13 х10, %
F0B.29 64285 0 0 # Время работы в режиме 13 х10, сек.
F0B.30 64286 0 0 # Многоскоростной режим 14 х10, %
F0B.31 64287 0 0 # Время работы в режиме 14 х10, сек.
F0B.32 64288 0 0 # Многоскоростной режим 15 х10, %
F0B.33 64289 0 0 # Время работы в режиме 15 х10, сек.
F0B.34 64290 0 0 # Значения разгона и торможения ПЛК (0 - 7)
F0B.35 64291 0 0 # Значения разгона и торможения ПЛК (8 - 15)
F0B.36 64292 0 0 # Перезапуск ПЛК
F0B.37 64293 0 0 # Режим перезапуска ПЛК
F0C.00 64512 11 0 # Защита от потери фазы
F0C.01 64513 0 0 # Снижение частоты при перебое c питанием х100, Гц/сек.
F0C.02 64514 1000 0 # Скорость снижения частоты при перебое с питанием х100, Гц/сек.
F0C.03 64515 0 0 # Превышение напряжения при блокировке вала
F0C.04 64516 140 0 # Уровень превышения напряжения при блокировке вала, %
F0C.05 64517 1 0 # Ограничение тока
F0C.06 64518 1660 0 # Автоматическое ограничение тока х10, %
F0C.07 64519 1000 0 # Шаг понижения частоты при ограничении тока х100, Гц/сек.
F0C.08 64520 0 0 # Защита от перегрузки
F0C.09 64521 166 0 # Предварительный сигнал обнаружения перегрузки, %
F0C.10 64522 0 0 # Время обнаружения перегрузки х100, сек.
F0C.11 64523 0 0 # Предварительный сигнал низкой нагрузки, %
F0C.12 64524 30 0 # Предварительный сигнал обнаружения низкой нагрузки, %
F0C.13 64525 10 0 # Время обнаружения низкой нагрузки х10, сек.
F0C.14 64526 0 0 # Режимы оповещения при обнаружении низкой нагрузки
F0C.15 64527 0 0 # Выбор регулировки несущей частоты
F0C.16 64528 1 0 # Режим ШИМ
F0C.17 64529 1 0 # Фильтр низких частот
F0C.18 64530 1 0 # Зарезервирован
F0D.00 64768 1 0 # Метод управления вторым двигателем
F0D.01 64769 1 0 # Тип нагрузки
F0D.02 64770 1 0 # Тип второго двигателя
F0D.03 64771 15 0 # Номинальная мощность двигателя 2 х10, КВт
F0D.04 64772 380 0 # Номинальное напряжение двигателя 2, В
F0D.05 64773 65 0 # Номинальный ток двигателя 2 х10, А
F0D.06 64774 5000 0 # Номинальная чаота двигателя 2 х100, Гц
F0D.07 64775 1450 0 # Номинальные обороты двигателя 2 х10, об/мин.
F0D.08 64776 1414 0 # Сопротивление статора двигателя 2 х1000, Ом
F0D.09 64777 1264 0 # Сопротивление ротора двигателя 2 х1000, Ом
F0D.10 64778 67 0 # Индуктивность рассеяния двигателя 2 х10
F0D.11 64779 956 0 # Индуктивность двигателя 2 х10
F0D.12 64780 33 0 # Ток холостого хода двигателя 2 х10, А
F0D.13 64781 1 0 # Зарезервировано
F0D.14 64782 1 0 # Зарезервировано
F0D.15 64783 1 0 # Зарезервировано
F0D.16 64784 1 0 # Зарезервировано
F0D.17 64785 1 0 # Зарезервировано
F0D.18 64786 1 0 # Зарезервировано
F0D.19 64787 1 0 # Зарезервировано
F0D.20 64788 1 0 # Зарезервировано
F0D.21 64789 1 0 # Зарезервировано
F0D.22 64790 1 0 # Зарезервировано
F0D.23 64791 1 0 # Зарезервировано
F0D.24 64792 1 0 # Зарезервировано
F0D.25 64793 1 0 # Зарезервировано
F0D.26 64794 1 0 # Защита от перегрузки для двигателя 2
F0D.27 64795 1000 0 # Обнаружение перегрузки двигателя 2 х10, %
F0E.00 65024 1 0 # Сетевой адрес
F0E.01 65025 4 0 # Скорость передачи данных
F0E.02 65026 4 0 # Тип связи
F0E.03 65027 5 0 # Задержка ответа
F0E.04 65028 0 0 # Время обнаружения потери связи х10, сек
F0E.05 65029 0 0 # Ошибка передачи данных
F0E.06 65030 0 0 # Зарезервировано
F0E.07 65031 200 0 # Зарезервировано
F0E.08 65032 0 0 # Зарезервировано
A00.00 40960 0 0 # Управление скоростью/моментом
A00.01 40961 0 0 # Канал задания при выбранном управлении моментом
A00.02 40962 1500 0 # Цифровое задание момента х10, %
A00.03 40963 0 0 # Время разгона при управлении моментом х10, сек.
A00.04 40964 0 0 # Время замедления при управлении моментом х10, сек.
A00.05 40965 0 0 # Выбор канала ограничения частоты прямого вращения при управлении моментом
A00.06 40966 5000 0 # Цифровое ограничение частоты прямого вращения х100, Гц
A00.07 40967 0 0 # Выбор канала ограничения частоты обратного вращения при управлении моментом
A00.08 40968 5000 0 # Цифровое ограничение частоты обратного вращения х100, Гц
A00.09 40969 0 0 # Коэффициент компенсации момента нулевой скорости х10, %
A00.10 40970 300 0 # Уровень определения нулевой скорости х100, Гц
A00.11 40971 0 0 # Коэффициент компенсации трения скольжения х10, %
A01.00 41216 0 0 # Нижний предел входа AI1 х100, В, мА
A01.01 41217 0 0 # Соответствие нижнему пределу входа AI1 х10, %
A01.02 41218 1000 0 # Верхний предел входа AI1 х100, В, мА
A01.03 41219 1000 0 # Соответствие верхнему пределу входа AI1 х10, %
A01.04 41220 100 0 # Фильтр входа AI1 х1000, сек.
A01.05 41221 0 0 # Нижний предел входа AI2 х100, В, мА
A01.06 41222 0 0 # Соответствие нижнему пределу входа AI2 х10, %
A01.07 41223 1000 0 # Верхний предел входа AI2 х100, В, мА
A01.08 41224 1000 0 # Соответствие верхнему пределу входа AI2 х10, %
A01.09 41225 0 0 # Среднее значение входа AI2 х100, В
A01.10 41226 0 0 # Соответствие среднему значению входа AI2 х10, %
A01.11 41227 100 0 # Фильтр входа AI2 х1000, сек.
A01.12 41228 0 0 # Нижний предел входа AI3 х100, В
A01.13 41229 0 0 # Соответствие нижнему пределу входа AI3 х10, %
A01.14 41230 1000 0 # Верхний предел входа AI3 х100, В
A01.15 41231 1000 0 # Соответствие верхнему пределу входа AI3 х10, %
A01.16 41232 500 0 # Среднее значение входа AI3 х100, В
A01.17 41233 500 0 # Соответствие среднему значению входа AI3 х10, %
A01.18 41234 100 0 # Фильтр входа AI3 х1000, сек
A01.19 41235 50 0 # Фильтр дребезга контактов х1000, сек.
A02.00 41472 0 0 # Заданная частота х100, Гц
A02.01 41473 0 0 # Выходная частота х100, Гц
A02.02 41474 0 0 # Опорная частота разгона х100, Гц
A02.03 41475 0 0 # Выходное напряжение, В
A02.04 41476 0 0 # Выходной ток х10, А
A02.05 41477 0 0 # Обороты двигателя, об/мин
A02.06 41478 0 0 # Зарезервировано
A02.07 41479 0 0 # Зарезервировано
A02.08 41480 0 0 # Выходная мощность х10, %
A02.09 41481 0 0 # Выходной момент х10, %
A02.10 41482 0 0 # Оценка частоты двигателя х100, Гц
A02.11 41483 0 0 # Напряжение звена постоянного тока, В
A02.12 41484 0 0 # Состояние дискретных входов
A02.13 41485 0 0 # Состояние дискретных выходов
A02.14 41486 0 0 # Цифровое задание частоты х100, Гц
A02.15 41487 0 0 # Зарезервировано
A02.16 41488 0 0 # Линейная скорость
A02.17 41489 0 0 # Длина импульсов
A02.18 41490 0 0 # Счетчик значения
A02.19 41491 0 0 # Напряжение на входе AI1 х100, В
A02.20 41492 0 0 # Напряжение на входе AI2 х100, В
A02.21 41493 0 0 # Напряжение на входе AI3 х100, В
A02.22 41494 0 0 # Частота на входе HDI1 х100, КГц
A02.23 41495 0 0 # Уставка ПИД х10, %
A02.24 41496 0 0 # Обратная связь ПИД х10, %
A02.25 41497 0 0 # Выходной сигнал ПИД х100, %
A02.26 41498 0 0 # Коэффициент мощности х10, %
A02.27 41499 0 0 # Время работы, мин.
A02.28 41500 0 0 # Шаг работы ПЛК
A02.29 41501 0 0 # Выходной сигнал регулятора ASR х10, %
A02.30 41502 0 0 # Напряжение на выходе A01 х100, В
A02.31 41503 0 0 # Напряжение на выходе A02 х100, В
A02.32 41504 0 0 # Ток ПЧ х10, А
A02.33 41505 0 0 # Момент х10
A02.34 41506 0 0 # Счетчик перегрузок двигателя
A02.35 41507 0 0 # Зарезервировано
A02.36 41508 1 0 # Текущий выбор двигателя
A03.00 41728 0 0 # Тип телеграммы
A03.01 41729 1 0 # Адрес устройства
A03.02 41730 0 0 # Параметр в телеграмме PZD3 (запись в ПЧ - DateOutput, %QW)
A03.03 41731 0 0 # Параметр в телеграмме PZD4 (запись в ПЧ - DateOutput, %QW)
A03.04 41732 0 0 # Параметр в телеграмме PZD5 (запись в ПЧ - DateOutput, %QW)
A03.05 41733 0 0 # Параметр в телеграмме PZD6 (запись в ПЧ - DateOutput, %QW)
A03.06 41734 0 0 # Параметр в телеграмме PZD7 (запись в ПЧ - DateOutput, %QW)
A03.07 41735 0 0 # Параметр в телеграмме PZD8 (запись в ПЧ - DateOutput, %QW)
A03.08 41736 0 0 # Параметр в телеграмме PZD9 (запись в ПЧ - DateOutput, %QW)
A03.09 41737 0 0 # Параметр в телеграмме PZD10 (запись в ПЧ - DateOutput, %QW)
A03.10 41738 0 0 # Параметр в телеграмме PZD11 (запись в ПЧ - DateOutput, %QW)
A03.11 41739 0 0 # Параметр в телеграмме PZD12 (запись в ПЧ - DateOutput, %QW)
A03.12 41740 0 0 # Зарезервировано
A03.13 41741 0 0 # Зарезервировано
A03.14 41742 0 0 # Параметр в телеграмме PZD3 (чтение из ПЧ - DateInput, %IW)
A03.15 41743 0 0 # Параметр в телеграмме PZD4 (чтение из ПЧ - DateInput, %IW)
A03.16 41744 0 0 # Параметр в телеграмме PZD5 (чтение из ПЧ - DateInput, %IW)
A03.17 41745 0 0 # Параметр в телеграмме PZD6 (чтение из ПЧ - DateInput, %IW)
A03.18 41746 0 0 # Параметр в телеграмме PZD7 (чтение из ПЧ - DateInput, %IW)
A03.19 41747 0 0 # Параметр в телеграмме PZD8 (чтение из ПЧ - DateInput, %IW)
A03.20 41748 0 0 # Параметр в телеграмме PZD9 (чтение из ПЧ - DateInput, %IW)
A03.21 41749 0 0 # Параметр в телеграмме PZD10 (чтение из ПЧ - DateInput, %IW)
A03.22 41750 0 0 # Параметр в телеграмме PZD11 (чтение из ПЧ - DateInput, %IW)
A03.23 41751 0 0 # Параметр в телеграмме PZD12 (чтение из ПЧ - DateInput, %IW)
A03.24 41752 0 0 # Зарезервировано
A03.25 41753 0 0 # Зарезервировано

120
modbus_params/main.c Normal file
View File

@ -0,0 +1,120 @@
/*
* This file is part of the modbus_param project.
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <signal.h>
#include <stdio.h>
#include <usefull_macros.h>
#include "modbus.h"
#include "verbose.h"
typedef struct{
int help; // help
int verbose; // verbose level (not used yet)
int slave; // slave ID
char **dumpcodes; // keycodes to dump into file
char **writeregs; // reg=val to write
char **writecodes; // keycode=val to write
int **readregs; // regs to write
char **readcodes; // keycodes to write
char *dumpfile; // dump file name
char *outdic; // output dictionary to save everything read from slave
char *dicfile; // file with dictionary
char *device; // serial device
int baudrate; // baudrate
double dTdump; // dumping time interval (s)
} parameters;
static parameters G = {
.slave = 1,
.device = "/dev/ttyUSB0",
.baudrate = 9600,
.dTdump = 0.1,
};
static sl_option_t cmdlnopts[] = {
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&G.help), "show this help"},
{"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verbose), "verbose level (each -v adds 1)"},
{"outfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.dumpfile), "file with parameter's dump"},
{"dumpkey", MULT_PAR, NULL, 'k', arg_string, APTR(&G.dumpcodes), "dump entry with this keycode; multiply parameter"},
{"dumptime", NEED_ARG, NULL, 't', arg_double, APTR(&G.dTdump), "dumping time interval (seconds, default: 0.1)"},
{"dictionary", NEED_ARG, NULL, 'D', arg_string, APTR(&G.dicfile), "file with dictionary (format: code register value writeable)"},
{"slave", NEED_ARG, NULL, 's', arg_int, APTR(&G.slave), "slave ID (default: 1)"},
{"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), "modbus device (default: /dev/ttyUSB0)"},
{"baudrate", NEED_ARG, NULL, 'b', arg_int, APTR(&G.baudrate), "modbus baudrate (default: 9600)"},
{"writer", MULT_PAR, NULL, 'w', arg_string, APTR(&G.writeregs), "write new value to register (format: reg=val); multiply parameter"},
{"writec", MULT_PAR, NULL, 'W', arg_string, APTR(&G.writecodes),"write new value to register by keycode (format: keycode=val); multiply parameter"},
{"outdic", NEED_ARG, NULL, 'O', arg_string, APTR(&G.outdic), "output dictionary for full device dump by input dictionary registers"},
{"readr", MULT_PAR, NULL, 'r', arg_int, APTR(&G.readregs), "registers (by address) to read; multiply parameter"},
{"readc", MULT_PAR, NULL, 'R', arg_string, APTR(&G.readcodes), "registers (by keycodes, checked by dictionary) to read; multiply parameter"},
end_option
};
void signals(int sig){
if(sig > 0) WARNX("Exig with signal %d", sig);
close_modbus();
exit(sig);
}
int main(int argc, char **argv){
sl_init();
sl_parseargs(&argc, &argv, cmdlnopts);
if(G.help) sl_showhelp(-1, cmdlnopts);
sl_loglevel_e lvl = G.verbose + LOGLEVEL_ERR;
set_verbose_level(lvl);
if(lvl >= LOGLEVEL_AMOUNT) lvl = LOGLEVEL_AMOUNT - 1;
if(!G.dicfile) ERRX("Point filename of dictionary");
if(!opendict(G.dicfile)) signals(-1);
if(G.dumpcodes && !setdumppars(G.dumpcodes)) signals(-1);
if(G.dumpfile && !opendumpfile(G.dumpfile)) signals(-1);
if(!open_modbus(G.device, G.baudrate)) signals(-1);
if(!set_slave(G.slave)) signals(-1);
signal(SIGTERM, signals); // kill (-15) - quit
signal(SIGHUP, SIG_IGN); // hup - ignore
signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
if(G.writeregs){
DBG("writeregs");
green("Write user registers to slave %d\n", G.slave);
green("Total: %d written successfully", write_regval(G.writeregs));
fflush(stdout);
}
if(G.writecodes){
DBG("writecodes");
green("Write user registers coded by keycode to slave %d\n", G.slave);
green("Total: %d written successfully", write_codeval(G.writecodes));
fflush(stdout);
}
if(G.outdic){
DBG("outdic");
int N = dumpall(G.outdic);
if(N < 1) WARNX("Dump full dictionary failed");
else green("Read %N registers, dump to %s\n", N, G.outdic);
fflush(stdout);
}
if(G.readregs) dumpregs(G.readregs);
if(G.readcodes) dumpcodes(G.readcodes);
if(G.dumpfile){
DBG("dumpfile");
if(!rundump(G.dTdump)) signals(-1);
DBG("Done, wait for ctrl+C");
while(1);
}
return 0;
}

409
modbus_params/modbus.c Normal file
View File

@ -0,0 +1,409 @@
/*
* This file is part of the modbus_param project.
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include <modbus/modbus.h>
#include <stdatomic.h>
#include <stdio.h>
#include <string.h>
#include <usefull_macros.h>
#include "modbus.h"
#include "verbose.h"
static FILE *dumpfile = NULL;
static dicentry_t *dumppars = NULL;
static int dumpsize = 0;
static dicentry_t *dictionary = NULL;
static int dictsize = 0;
static modbus_t *modbus_ctx = NULL;
static pthread_mutex_t modbus_mutex = PTHREAD_MUTEX_INITIALIZER;
static atomic_int stopdump = FALSE, isstopped = TRUE;
// open dictionary file and check it; return TRUE if all OK
// all after "#" is comment;
// dictionary format: "'code' 'register' 'value' 'readonly flag'\n", e.g.
// "F00.09 61444 5000 1"
int opendict(const char *dic){
FILE *f = fopen(dic, "r");
if(!f){
WARN("Can't open %s", dic);
return FALSE;
}
int dicsz = 0;
size_t linesz = BUFSIZ;
char *line = MALLOC(char, linesz);
dicentry_t curentry;
curentry.code = MALLOC(char, BUFSIZ);
int retcode = TRUE;
while(1){
if(getline(&line, &linesz, f) < 0) break;
// DBG("Original LINE: '%s'", line);
char *comment = strchr(line, '#');
if(comment) *comment = 0;
char *newline = strchr(line, '\n');
if(newline) *newline = 0;
// DBG("LINE: '%s'", line);
if(*line == 0) continue;
if(4 != sscanf(line, "%s %" SCNu16 " %" SCNu16 " %" SCNu8, curentry.code, &curentry.reg, &curentry.value, &curentry.readonly)){
WARNX("Can't understand this line: '%s'", line);
continue;
}
// DBG("Got line: '%s %" PRIu16 " %" PRIu16 " %" PRIu8, curentry.code, curentry.reg, curentry.value, curentry.readonly);
if(++dictsize >= dicsz){
dicsz += 50;
dictionary = realloc(dictionary, sizeof(dicentry_t) * dicsz);
if(!dictionary){
WARN("Can't allocate memory for dictionary");
retcode = FALSE;
goto ret;
}
}
dicentry_t *entry = &dictionary[dictsize-1];
entry->code = strdup(curentry.code);
entry->reg = curentry.reg;
entry->value = curentry.value;
entry->readonly = curentry.readonly;
//DBG("Add entry; now dictsize is %d", dictsize);
}
ret:
fclose(f);
FREE(curentry.code);
FREE(line);
return retcode;
}
static int chkdict(){
if(dictsize < 1){
WARNX("Open dictionary first");
return FALSE;
}
return TRUE;
}
// find dictionary entry
dicentry_t *findentry_by_code(const char *code){
if(!chkdict()) return NULL;
for(int i = 0; i < dictsize; ++i){
if(strcmp(code, dictionary[i].code)) continue;
return &dictionary[i];
}
return NULL;
}
dicentry_t *findentry_by_reg(uint16_t reg){
if(!chkdict()) return NULL;
for(int i = 0; i < dictsize; ++i){
if(reg != dictionary[i].reg) continue;
return &dictionary[i];
}
return NULL;
}
// prepare a list with dump parameters
int setdumppars(char **pars){
if(!pars || !*pars) return FALSE;
if(!chkdict()) return FALSE;
FNAME();
char **p = pars;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int cursz = -1; // current allocated size
int N = 0;
pthread_mutex_lock(&mutex);
while(*p){ // count parameters and check them
dicentry_t *e = findentry_by_code(*p);
if(!e){
WARNX("Can't find entry with code %s", *p);
pthread_mutex_unlock(&mutex);
return FALSE;
}
DBG("found entry do dump, reg=%d", e->reg);
if(cursz <= N){
cursz += 50;
DBG("realloc list to %d", cursz);
dumppars = realloc(dumppars, sizeof(dicentry_t) * (cursz));
DBG("zero mem");
bzero(&dumppars[N], sizeof(dicentry_t)*(cursz-N));
}
FREE(dumppars[N].code);
dumppars[N] = *e;
dumppars[N].code = strdup(e->code);
DBG("Add %s", e->code);
++N; ++p;
}
dumpsize = N;
pthread_mutex_unlock(&mutex);
return TRUE;
}
// open dump file and add header; return FALSE if failed
int opendumpfile(const char *name){
if(!chkdict()) return FALSE;
if(dumpsize < 1){
WARNX("Set dump parameters first");
return FALSE;
}
if(!name) return FALSE;
closedumpfile();
dumpfile = fopen(name, "w+");
if(!dumpfile){
WARN("Can't open %s", name);
return FALSE;
}
fprintf(dumpfile, "# time,s ");
for(int i = 0; i < dumpsize; ++i){
fprintf(dumpfile, "%s ", dumppars[i].code);
}
fprintf(dumpfile, "\n");
return TRUE;
}
void closedumpfile(){
if(dumpfile && !isstopped){
if(!isstopped){
stopdump = TRUE;
while(!isstopped);
}
fclose(dumpfile);
}
}
static void *dumpthread(void *p){
isstopped = FALSE;
stopdump = FALSE;
double dT = *(double*)p;
DBG("Dump thread started. Period: %gs", dT);
double startT = sl_dtime();
while(!stopdump){
double t0 = sl_dtime();
fprintf(dumpfile, "%6.3g", t0 - startT);
for(int i = 0; i < dumpsize; ++i){
if(!read_entry(&dumppars[i])) fprintf(dumpfile, "---- ");
else fprintf(dumpfile, "%4d ", dumppars[i].value);
}
fprintf(dumpfile, "\n");
while(sl_dtime() - t0 < dT) usleep(100);
}
isstopped = TRUE;
return NULL;
}
int rundump(double dT){
if(!dumpfile){
WARNX("Open dump file first");
return FALSE;
}
if(dT < 0.){
WARNX("Time interval should be > 0");
return FALSE;
}
pthread_t thread;
static double T = 0.;
if(T != dT) T = dT;
DBG("user give dT: %g", T);
if(pthread_create(&thread, NULL, dumpthread, (void*)&T)){
WARN("Can't create dumping thread");
return FALSE;
}
DBG("Thread created, detach");
pthread_detach(thread);
return TRUE;
}
void close_modbus(){
if(modbus_ctx){
closedumpfile();
modbus_close(modbus_ctx);
modbus_free(modbus_ctx);
}
}
// read register and modify entry->reg; return FALSE if failed
int read_entry(dicentry_t *entry){
if(!entry) return FALSE;
int ret = TRUE;
pthread_mutex_lock(&modbus_mutex);
if(modbus_read_registers(modbus_ctx, entry->reg, 1, &entry->value) < 0) ret = FALSE;
pthread_mutex_unlock(&modbus_mutex);
return ret;
}
// write register value; FALSE - if failed or read-only
int write_entry(dicentry_t *entry){
if(!entry || entry->readonly) return FALSE;
int ret = TRUE;
pthread_mutex_lock(&modbus_mutex);
if(modbus_write_register(modbus_ctx, entry->reg, entry->value) < 0) ret = FALSE;
pthread_mutex_unlock(&modbus_mutex);
return ret;
}
// write multiply regs (without checking by dict) by NULL-terminated array "reg=val"; return amount of items written
int write_regval(char **keyval){
int written = 0;
dicentry_t entry = {0};
while(*keyval){
DBG("Parse %s", *keyval);
char key[SL_KEY_LEN], value[SL_VAL_LEN];
if(2 != sl_get_keyval(*keyval, key, value)){
WARNX("%s isn't in format reg=val", *keyval);
}else{
DBG("key: %s, val: %s", key, value);
int r=-1, v=-1;
if(!sl_str2i(&r, key) || !sl_str2i(&v, value) || r < 0 || v < 0 || r > UINT16_MAX || v > UINT16_MAX){
WARNX("Wrong register number or value: %d=%d; should be uint16_t", r, v);
}else{
entry.value = (uint16_t)v;
entry.reg = (uint16_t)r;
if(write_entry(&entry)){
++written;
verbose(LOGLEVEL_MSG, "Written %u to register %u", entry.value, entry.reg);
}else verbose(LOGLEVEL_WARN, "Can't write %u to register %u", entry.value, entry.reg);
}
}
++keyval;
}
return written;
}
// write multiply regs by NULL-terminated array "keycode=val" (checking `keycode`); return amount of items written
int write_codeval(char **codeval){
if(!chkdict()) return FALSE;
int written = 0;
dicentry_t entry = {0};
while(*codeval){
char key[SL_KEY_LEN], value[SL_VAL_LEN];
if(2 != sl_get_keyval(*codeval, key, value)){
WARNX("%s isn't in format keycode=val");
}else{
int v=-1;
if(!sl_str2i(&v, value) || v < 0 || v > UINT16_MAX){
WARNX("Wrong value: %d; should be uint16_t", v);
}else{
dicentry_t *de = findentry_by_code(key);
if(!de){
WARNX("Keycode %s not found in dictionary", key);
}else{
entry.readonly = de->readonly;
entry.reg = de->reg;
if(entry.readonly){
verbose(LOGLEVEL_WARN, "Can't change readonly register %d", entry.reg);
}else{
entry.value = (uint16_t)v;
if(write_entry(&entry)){
++written;
verbose(LOGLEVEL_MSG, "Written %u to register %u", entry.value, entry.reg);
}else verbose(LOGLEVEL_WARN, "Can't write %u to register %u", entry.value, entry.reg);
}
}
}
}
++codeval;
}
return written;
}
int open_modbus(const char *path, int baudrate){
int ret = FALSE;
if(modbus_ctx) close_modbus();
pthread_mutex_lock(&modbus_mutex);
modbus_ctx = modbus_new_rtu(path, baudrate, 'N', 8, 1);
if(!modbus_ctx){
WARNX("Can't open device %s @ %d", path, baudrate);
goto rtn;
}
modbus_set_response_timeout(modbus_ctx, 0, 100000);
if(modbus_connect(modbus_ctx) < 0){
WARNX("Can't connect to device %s", path);
modbus_free(modbus_ctx);
modbus_ctx = NULL;
goto rtn;
}
ret = TRUE;
rtn:
pthread_mutex_unlock(&modbus_mutex);
return ret;
}
int set_slave(int ID){
int ret = TRUE;
pthread_mutex_lock(&modbus_mutex);
if(modbus_set_slave(modbus_ctx, ID)){
WARNX("Can't set slave ID to %d", ID);
ret = FALSE;
}
pthread_mutex_unlock(&modbus_mutex);
return ret;
}
// dump all registers by input dictionary into output; also modify values of registers in dictionary
int dumpall(const char *outdic){
if(!chkdict()) return -1;
int got = 0;
FILE *o = fopen(outdic, "w");
if(!o){
WARN("Can't open %s", outdic);
return -1;
}
for(int i = 0; i < dictsize; ++i){
if(read_entry(&dictionary[i])){
verbose(LOGLEVEL_MSG, "Read register %d, value: %d\n", dictionary[i].reg, dictionary[i].value);
++got;
fprintf(o, "%s %4" PRIu16 " %4" PRIu16 " %" PRIu8 "\n", dictionary[i].code, dictionary[i].reg, dictionary[i].value, dictionary[i].readonly);
}else verbose(LOGLEVEL_WARN, "Can't read value of register %d\n", dictionary[i].reg);
}
fclose(o);
return got;
}
// read dump register values and dump to stdout
void dumpregs(int **addresses){
dicentry_t entry = {0};
green("Dump registers: (reg val)\n");
while(*addresses){
int addr = **addresses;
if(addr < 0 || addr > UINT16_MAX){
WARNX("Wrong register number: %d", addr);
}else{
entry.reg = (uint16_t) addr;
if(!read_entry(&entry)) WARNX("Can't read register %d", addr);
else printf("%4d %4d\n", entry.reg, entry.value);
}
++addresses;
}
printf("\n");
}
// `dumpregs` but by keycodes (not modifying dictionary)
void dumpcodes(char **keycodes){
if(!chkdict()) return;
dicentry_t entry = {0};
green("Dump registers: (code (reg) val)\n");
while(*keycodes){
dicentry_t *de = findentry_by_code(*keycodes);
if(!de){
WARNX("Can't find keycode %s in dictionary", *keycodes);
}else{
entry.reg = de->reg;
if(!read_entry(&entry)) WARNX("Can't read register %s (%d)", *keycodes, entry.reg);
else printf("%s (%4d) %4d\n", de->code, entry.reg, entry.value);
}
++keycodes;
}
printf("\n");
}

51
modbus_params/modbus.h Normal file
View File

@ -0,0 +1,51 @@
/*
* This file is part of the modbus_param project.
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
typedef struct{
char *code; // mnemonic code
uint16_t value; // value
uint16_t reg; // register number
uint8_t readonly; // ==1 if can't be changed
} dicentry_t;
int setdumppars(char **pars);
int opendumpfile(const char *name);
void closedumpfile();
int rundump(double dT);
int opendict(const char *dic);
dicentry_t *findentry_by_code(const char *code);
dicentry_t *findentry_by_reg(uint16_t reg);
int open_modbus(const char *path, int baudrate);
void close_modbus();
int set_slave(int ID);
int read_entry(dicentry_t *entry);
int write_entry(dicentry_t *entry);
int write_regval(char **keyval);
int write_codeval(char **codeval);
int dumpall(const char *outdic);
void dumpregs(int **addresses);
void dumpcodes(char **keycodes);

View File

@ -0,0 +1 @@
-std=c17

View File

@ -0,0 +1,2 @@
#define _XOPEN_SOURCE 1111
#define _GNU_SOURCE

View File

@ -0,0 +1 @@
[General]

View File

@ -0,0 +1 @@
-std=c++17

View File

@ -0,0 +1,5 @@
main.c
modbus.c
modbus.h
verbose.c
verbose.h

View File

40
modbus_params/verbose.c Normal file
View File

@ -0,0 +1,40 @@
/*
* This file is part of the modbus_param project.
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stdio.h>
#include "verbose.h"
static sl_loglevel_e verblvl = LOGLEVEL_WARN;
void set_verbose_level(sl_loglevel_e level){
if(level >= LOGLEVEL_AMOUNT) level = LOGLEVEL_AMOUNT - 1;
else if(level < 0) level = 0;
verblvl = level;
}
void verbose(sl_loglevel_e lvl, const char *fmt, ...){
if(lvl > verblvl) return;
va_list ar;
va_start(ar, fmt);
vprintf(fmt, ar);
va_end(ar);
fflush(stdout);
}

24
modbus_params/verbose.h Normal file
View File

@ -0,0 +1,24 @@
/*
* This file is part of the modbus_param project.
* Copyright 2025 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <usefull_macros.h>
void set_verbose_level(sl_loglevel_e level);
void verbose(sl_loglevel_e lvl, const char *fmt, ...);