Создание Slave устройства в сети Modbus
Re: Создание Slave устройства в сети Modbus
Олег, наши тысячи устройств работают в сетях Modbus наших разных Заказчиков. Про спецификации и алгоритмы подсчета CRC мы сами можем оказвать какие угодно консультации. От операционнной системы суть протоколов не зависит. Эта тема закрыта. И проблемы возможно действительно в вызовах API Posix, обернутых разными библиотеками. Я провалилась в библиотеки и выбрала все вызовы. Нас беспокот, правильность настройки драйвера. Если можете - окажите консультацию по этому вопросу.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Сам сериальный драйвер в Linux вы никак не настраиваете, но параметры самой сериальной линии вы устанавливаете, и в вашем коде (на 1-й стр.) - tcsetattr(). Но я бы попробовал изменить параметры struct termios линии так, как они называют RAW-mode:Larisa писал(а):Нас беспокот, правильность настройки драйвера.
Код: Выделить всё
$ man cfmakeraw
...
Как-то так:
Код: Выделить всё
$ cat term.c
#include <termios.h>
int fd = ...;
struct termios tios,
*termios_p = &tios;
tcgetattr( fd, termios_p );
termios_p->c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON );
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
termios_p->c_cflag &= ~( CSIZE | PARENB );
termios_p->c_cflag |= CS8;
tcsetattr( fd, TCSAFLUSH, termios_p );
Мне почему-то кажется, что у вас некоторые параметры порта установлены не так, в том что вы показывали:
Код: Выделить всё
stty -a < /dev/ttymxc0
...
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Флаги открытия канала тоже вызывают некоторые сомнения:Larisa писал(а): Используем порт /dev/ttymxc0
флаги открытия порта
flags = O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL;
ctx->s = open(ctx_rtu->device, flags);
- O_RDWR | O_NOCTTY - это не вызывает вопросов
- O_NDELAY - в книге, которую я показывал, Стивенс пишет:
- но, если вы используете для чтения select(), и использование неблокирующего режима - под вопросом;... сохранилась поддержка флага O_NDELAY с устаревшей семантикой, однако все новые приложения должны использовать флаг O_NONBLOCK.
- O_EXCL - мне кажется лишним для аппаратного сериального порта;
Вот это место тоже интересное:
Но вы не показываете как это происходит...Larisa писал(а): select(ctx->s+1, rset, NULL, NULL, tv);
на бесконечный таймаут, когда в канале появяться данные, считываем несколькоми портциями (могу рассказать подробнее, но сейчас это не важно, там проблем вроде нет)
анализируем данные, отправляем ответ.
Анализируете ли вы результат (код) возвращаемый select()? Как?
И в read() после select(), если вы используете неблокирующий режим ввода, нужно очень аккуратно анализировать код возврата, потому что вы можете получить результат EAGAIN, что вовсе не означает что вы считали данные (они ещё могут быть не совсем готовы), и чтение в таком случае нужно тут же повторять (иначе при следующих read() как раз и возникнут неприятности).
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Хорошая идея, мне кажется, пройтись информационным поиском по проектам с ключевой сигнатурой "Modbus RTU slave emulator" + подсмотреть кто и какими параметрами инициализирует обмен.Larisa писал(а):Если можете - окажите консультацию по этому вопросу.
Вот любопытный вариант: LibModbus (это совсем другой libmodbus):
Там в файле commun.c функция Mb_open_device() - открытие и инициализация параметров порта ... рассмотрите тщательно (что и зачем?):Libmodbus is a dynamic library to use Modbus dialog protocol with GNU/Linux.
LibModbus include master, slave and also serial port configuration functions.
GModbusControl is a simple tool tu use with libmodbus
Код: Выделить всё
fd = open(Mbc_port,O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY) ;
...
Mb_tio.c_iflag &= ~ICRNL;
if (Mbc_bit_s==2)
Mb_tio.c_cflag = Mb_tio.c_cflag | CSTOPB;
Mb_tio.c_cflag = Mb_tio.c_cflag | CLOCAL | CREAD;
Mb_tio.c_oflag = 0;
Mb_tio.c_lflag = 0; /*ICANON;*/
Mb_tio.c_cc[VMIN]=1;
Mb_tio.c_cc[VTIME]=0;
/* clean port */
tcflush(fd, TCIFLUSH);
fcntl(fd, F_SETFL, FASYNC);
if (tcsetattr(fd,TCSANOW,&Mb_tio) <0)
...
/* clean I & O device */
tcflush(fd,TCIOFLUSH);
...
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Лариса, вы спешите как если бы вы вызвали доктора к своему больному родственнику, у которого цвет лица неправильный - синюшный...Larisa писал(а):Олег, наши тысячи устройств работают в сетях Modbus наших разных Заказчиков. Про спецификации и алгоритмы подсчета CRC мы сами можем оказвать какие угодно консультации. От операционнной системы суть протоколов не зависит. Эта тема закрыта.
А потом торопите доктора: "Доктор! Чего вы там возитесь?! Затеяли: температуру мерять, сахар определять, клинический анализ крови заказываете... Мне нужно только чтобы вы убрали его синюшный цвет лица. ... А то он уже холодеть начинает."
Я не знаю всех превходящих деталей вашей ситуации. И вы, с самого начала, не очень внятно их излагаете ... просто потому что вы в ситуации и вам всё изнутри понятно и известно, а снаружи ситуации всё далеко не так ясно. Давайте теперь, слегка разобравшись, переформулируем ситуацию и посмотрим на неё внимательнее.
И давайте переформулирую именно я (чтобы зафиксировать ясность проблем), а вы только подтвердите ("да" - "нет") и поправите...
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Итак (как я могу судить)...Olej писал(а):И давайте переформулирую я, а вы только подтвердите ("да" - "нет") и поправите...
1. У вас есть ARM одноплатник (SBC) собственной разработки и сборки, сильно похожий на iMX6UL, но не от производителя, не фирменный...
2. На нём стоит Linux вашей собственной сборки, с помощью BuildRoot собранный...
3. У SBC 5 (или больше?) аппаратных сериальных портов, которые можно аппаратно переключать между режимами RS-232 / RS-485;
Покажите (чтоб дальше к этому не возвращаться):
Код: Выделить всё
$ ls -l /dev/ttymxc*
Для поддержки Modbus на этих 4-х портах используется API пакета LibModbus в составе Linux.
На уровне API: modbus_new_rtu(), modbus_connect(), modbus_mapping_new(), modbus_read_input_registers() и т.д. (/usr/include/modbus/modbus.h).
Правильно?
5. Оставшийся 5-й порт RS-485 преназначен для связи "вверх" по управлению, в режиме Slave Modbus...
Поскольку API библиотеки LibModbus предназначена только для написания ПО Master, вы пишете ПО этого канала используя низкоуровневый API терминальных линий POSIX.
На уровне UNIX/POSIX/Linux API: struct termios, open(), read(), write() ... и т.д.
Правильно?
6. При обмене этого Slave с Master возникают плавающие ошибки (1:6000, 1:100000) ... некоторые из них приводят к тому, что канал Slave после них полностью "умирает".
Вы обмен-тестирование проводили с Master из этой же своей реализации? Или с какими то сторонними Master, из другой реализации: автономными, какими-то эмуляторами из Windows и т.п.?
Вы можете организовать "петлю" обмена, внутри одного и того же SBC, между этим Slave и любым из 4-х каналов Master?
7. Поскольку это готовится реализация для серийных, тиражных поставок, то допустить эти, хоть и редкие, сбои нельзя - это в будущем рекламации от заказчиков и попадание на хорошие деньги...
Нужно локализовать место (уровень) возникновения сбоев, выяснить причину и устранить.
Теперь я правильно излагаю?
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Причина ваших плавающих ошибок может состоять в:Olej писал(а): Нужно локализовать место (уровень) возникновения сбоев, выяснить причину и устранить.
1. Дефектном ("горбатом" - с артефактами) конкретном чипе RS-232 / RS-485, заложенном вашими разработчиками в схемотехнику SBC;
2. Аппаратные ошибки-неточности в реализации схемотехники RS-232 / RS-485 ... например, при переключении протоколов, буферизация и др.
3. Ошибки в драйвере для RS-232 / RS-485 при сборке Linux - например, указание не того типа чипа, или каких-то параметров конфигурации ядра;
4. Ошибка в программной инициализации режима сериальной линии - вам нужно сменить канонический режим на неканонический (терминология UNIX/POSIX) и перевести канал в RAW-mode (сырой режим) ... как это делает, например, сетевой протокол PPP (можно и там подсмотреть);
5. Вообще ошибочной работе драйверов Linux (но это почти невозможно - система termios UNIX одна из старейших, и отрабатывалась 50 лет!);
5. Ошибка в программной реализации тонкостей обмена: select(), poll(), read(), write()... - блокирующий-неблокирующий режим open(), контроль и интерпретация кодов возвратов всех операций ... и т.д.
6. Несогласованность приёмно-передающих сторон Master-Slave протокола - временные задержки, тайм-ауты RTU... обработка ошибок в канале, реакция на ошибки обмена и т.д.
P.S. Может и ещё где-то есть слой, который я сразу не увидел, пропустил...
В принципе, нужно бы исключить возможность на каждом уровне отдельно, и быть уверенным что там она не возникает!
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Оставив, пока, в стороне п.п.1-2, по п.3:Olej писал(а): Причина ваших плавающих ошибок может состоять в:
1. Дефектном ("горбатом" - с артефактами) конкретном чипе RS-232 / RS-485, заложенном вашими разработчиками в схемотехнику SBC;
2. Аппаратные ошибки-неточности в реализации схемотехники RS-232 / RS-485 ... например, при переключении протоколов, буферизация и др.
3. Ошибки в драйвере для RS-232 / RS-485 при сборке Linux - например, указание не того типа чипа, или каких-то параметров конфигурации ядра;
Ведь каким-то образом при сборке Linux у вас каким-то образом получилось такое ... "странное" имя ttymxc0? Ведь это какими-то параметрами сборки, указанием типа чипа и др. было предопределено...Larisa писал(а): Используем порт /dev/ttymxc0
Я посмотрел, для сравнения, ARM одноплатные SBC (то что у меня оказалось под рукой):
1. Orange Pi One:
Код: Выделить всё
olej@orangepione:~$ inxi -C
CPU: Quad core ARMv7 rev 5 (v7l) (-MCP-) (ARM)
clock speeds: max: 1200 MHz 1: 1200 MHz 2: 1200 MHz 3: 1200 MHz 4: 1200 MHz
olej@orangepione:~$ inxi -S
System: Host: orangepione Kernel: 4.14.70-sunxi armv7l (32 bit) Console: tty 0
Distro: Debian GNU/Linux 9 (stretch)
olej@orangepione:~$ ls /dev/ttyS*
/dev/ttyS0 /dev/ttyS1 /dev/ttyS2 /dev/ttyS3 /dev/ttyS4 /dev/ttyS5 /dev/ttyS6 /dev/ttyS7
2. Rapsberry Pi 2+ с hard realtime Xenomai патчем:
Код: Выделить всё
olej@raspberrypi:~ $ inxi -C
CPU: Quad core ARMv7 rev 5 (v7l) (-MCP-) (ARM)
Clock Speeds: 1: MHz 2: MHz 3: MHz 4: MHz
olej@raspberrypi:~ $ inxi -S
System: Host: raspberrypi Kernel: 4.1.21-v7+ armv7l (32 bit) Desktop: Cinnamon Distro: Raspbian GNU/Linux 8
olej@raspberrypi:~ $ ls /dev/ttyA*
/dev/ttyAMA0
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
Посмотрел какие параметры порта устанавливает (runtime) вот этот проект (Modbus Master-Slave):Olej писал(а): 4. Ошибка в программной инициализации режима сериальной линии - вам нужно сменить канонический режим на неканонический (терминология UNIX/POSIX) и перевести канал в RAW-mode (сырой режим) ... как это делает, например, сетевой протокол PPP (можно и там подсмотреть);
Дописал туда небольшой тест:Olej писал(а): Вот любопытный вариант: LibModbus (это совсем другой libmodbus):
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ cat modopt.c
#include "modbus.h"
int main() {
Mb_verbose = 1; /* print debugging informations */
int device = Mb_open_device( "/dev/ttyS0", 115200, 0, 8, 1 ); /* open device */
getchar(); /* hit <return> to stop program */
Mb_close_device( device ); /* close device */
}
Код: Выделить всё
CFLAGS = -Wall -O3
all: modopt
modopt: commun.o modopt.o
$(CC) $(CFLAGS) -o modopt commun.o modopt.o -lpthread -I.
commun.o: commun.c modbus.h
$(CC) $(CFLAGS) -c commun.c -I.
modopt.o: modopt.c modbus.h
$(CC) $(CFLAGS) -c modopt.c -I.
clean:
rm -f *.o > /dev/null
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: Создание Slave устройства в сети Modbus
У меня на этом компьютере 2 физических сериальных порта, UART: /dev/ttyS0 + /dev/ttyS0 (сам не знал про этот компьютер ... но это изрядно помогает).Olej писал(а):Дальше можем наблюдать...
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ sudo stty -a -F /dev/ttyS0
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O;
min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ diff <(sudo stty -a -F /dev/ttyS0) <(sudo stty -a -F /dev/ttyS1)
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ echo $?
0
А теперь можем перестроить порт под использование Modbus RTU:
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ sudo ./modopt
setting ok:
device /dev/ttyS0
speed 115200
data bits 8
stop bits 1
parity 0
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ sudo stty -a -F /dev/ttyS0
speed 115200 baud; rows 0; columns 0; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>;
werase = <undef>; lnext = <undef>; discard = <undef>; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke -flusho -extproc
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ diff <(sudo stty -a -F /dev/ttyS0) <(sudo stty -a -F /dev/ttyS1)
1,7c1,6
< speed 115200 baud; rows 0; columns 0; line = 0;
< intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>;
< eol = <undef>; eol2 = <undef>; swtch = <undef>; start = <undef>; stop = <undef>;
< susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>;
< discard = <undef>; min = 1; time = 0;
< -parenb -parodd -cmspar cs8 -hupcl -cstopb cread clocal -crtscts
< -ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
---
> speed 9600 baud; rows 0; columns 0; line = 0;
> intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
> eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
> werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
> -parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
> -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
9,11c8,10
< -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
< -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
< -echoctl -echoke -flusho -extproc
---
> opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
> isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
> echoctl echoke -flusho -extproc
Код: Выделить всё
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$ diff <(sudo stty -a -F /dev/ttyS0) <(sudo stty -a -F /dev/ttyS1)
olej@ACER:~/2019_WORK/own.WORK/Vector/modbus/modopt$
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 13 гостей