Создание Slave устройства в сети Modbus

встраиваемые модели

Модераторы: Olej, vikos

Larisa
Интересующийся
Сообщения: 6
Зарегистрирован: 04 сен 2019, 14:14
Контактная информация:

Re: Создание Slave устройства в сети Modbus

Непрочитанное сообщение Larisa » 11 сен 2019, 19:10

Олег, наши тысячи устройств работают в сетях Modbus наших разных Заказчиков. Про спецификации и алгоритмы подсчета CRC мы сами можем оказвать какие угодно консультации. От операционнной системы суть протоколов не зависит. Эта тема закрыта. И проблемы возможно действительно в вызовах API Posix, обернутых разными библиотеками. Я провалилась в библиотеки и выбрала все вызовы. Нас беспокот, правильность настройки драйвера. Если можете - окажите консультацию по этому вопросу.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание Slave устройства в сети Modbus

Непрочитанное сообщение Olej » 11 сен 2019, 20:43

Larisa писал(а):Нас беспокот, правильность настройки драйвера.
Сам сериальный драйвер в Linux вы никак не настраиваете, но параметры самой сериальной линии вы устанавливаете, и в вашем коде (на 1-й стр.) - tcsetattr(). Но я бы попробовал изменить параметры struct termios линии так, как они называют RAW-mode:

Код: Выделить всё

$ man cfmakeraw
...
Или то, что делает непосредственно вызов 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 );
Все константы, естественно, в <termios.h> - уточняйте именно там почему они так устанавливают RAW-mode.
Мне почему-то кажется, что у вас некоторые параметры порта установлены не так, в том что вы показывали:

Код: Выделить всё

stty -a < /dev/ttymxc0
...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание Slave устройства в сети Modbus

Непрочитанное сообщение Olej » 11 сен 2019, 21:20

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 - в книге, которую я показывал, Стивенс пишет:
... сохранилась поддержка флага O_NDELAY с устаревшей семантикой, однако все новые приложения должны использовать флаг O_NONBLOCK.
- но, если вы используете для чтения select(), и использование неблокирующего режима - под вопросом;
- 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

Непрочитанное сообщение Olej » 12 сен 2019, 00:34

Larisa писал(а):Если можете - окажите консультацию по этому вопросу.
Хорошая идея, мне кажется, пройтись информационным поиском по проектам с ключевой сигнатурой "Modbus RTU slave emulator" + подсмотреть кто и какими параметрами инициализирует обмен.
Вот любопытный вариант: LibModbus (это совсем другой libmodbus):
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
Там в файле commun.c функция Mb_open_device() - открытие и инициализация параметров порта ... рассмотрите тщательно (что и зачем?):

Код: Выделить всё

  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);
  ...
P.S. Посмотрите код этого проекта: а). он достаточно простой и прозрачный, б). там есть готовый Slave-эмулятор, файл slave-example.c

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание Slave устройства в сети Modbus

Непрочитанное сообщение Olej » 12 сен 2019, 10:24

Larisa писал(а):Олег, наши тысячи устройств работают в сетях Modbus наших разных Заказчиков. Про спецификации и алгоритмы подсчета CRC мы сами можем оказвать какие угодно консультации. От операционнной системы суть протоколов не зависит. Эта тема закрыта.
Лариса, вы спешите как если бы вы вызвали доктора к своему больному родственнику, у которого цвет лица неправильный - синюшный... ;-)
А потом торопите доктора: "Доктор! Чего вы там возитесь?! Затеяли: температуру мерять, сахар определять, клинический анализ крови заказываете... Мне нужно только чтобы вы убрали его синюшный цвет лица. ... А то он уже холодеть начинает." :lol:

Я не знаю всех превходящих деталей вашей ситуации. И вы, с самого начала, не очень внятно их излагаете ... просто потому что вы в ситуации и вам всё изнутри понятно и известно, а снаружи ситуации всё далеко не так ясно. Давайте теперь, слегка разобравшись, переформулируем ситуацию и посмотрим на неё внимательнее.

И давайте переформулирую именно я (чтобы зафиксировать ясность проблем), а вы только подтвердите ("да" - "нет") и поправите...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание Slave устройства в сети Modbus

Непрочитанное сообщение Olej » 12 сен 2019, 10:50

Olej писал(а):И давайте переформулирую я, а вы только подтвердите ("да" - "нет") и поправите...
Итак (как я могу судить)...

1. У вас есть ARM одноплатник (SBC) собственной разработки и сборки, сильно похожий на iMX6UL, но не от производителя, не фирменный...
2. На нём стоит Linux вашей собственной сборки, с помощью BuildRoot собранный...
3. У SBC 5 (или больше?) аппаратных сериальных портов, которые можно аппаратно переключать между режимами RS-232 / RS-485;
Покажите (чтоб дальше к этому не возвращаться):

Код: Выделить всё

$ ls -l /dev/ttymxc*
4. Из имеющихся портов 4 RS-485 предназначены для управления "вниз" разной периферией - в режимах Master Modbus...
Для поддержки 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 » 12 сен 2019, 11:27

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

Непрочитанное сообщение Olej » 12 сен 2019, 13:07

Olej писал(а): Причина ваших плавающих ошибок может состоять в:
1. Дефектном ("горбатом" - с артефактами) конкретном чипе RS-232 / RS-485, заложенном вашими разработчиками в схемотехнику SBC;
2. Аппаратные ошибки-неточности в реализации схемотехники RS-232 / RS-485 ... например, при переключении протоколов, буферизация и др.
3. Ошибки в драйвере для RS-232 / RS-485 при сборке Linux - например, указание не того типа чипа, или каких-то параметров конфигурации ядра;
Оставив, пока, в стороне п.п.1-2, по п.3:
Larisa писал(а): Используем порт /dev/ttymxc0
Ведь каким-то образом при сборке Linux у вас каким-то образом получилось такое ... "странное" имя 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

Непрочитанное сообщение Olej » 12 сен 2019, 15:44

Olej писал(а): 4. Ошибка в программной инициализации режима сериальной линии - вам нужно сменить канонический режим на неканонический (терминология UNIX/POSIX) и перевести канал в RAW-mode (сырой режим) ... как это делает, например, сетевой протокол PPP (можно и там подсмотреть);
Посмотрел какие параметры порта устанавливает (runtime) вот этот проект (Modbus Master-Slave):
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 */
}
Makefile ... что-то такое:

Код: Выделить всё

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

Непрочитанное сообщение Olej » 12 сен 2019, 15:56

Olej писал(а):Дальше можем наблюдать...
У меня на этом компьютере 2 физических сериальных порта, UART: /dev/ttyS0 + /dev/ttyS0 (сам не знал про этот компьютер ;-) ... но это изрядно помогает).

Код: Выделить всё

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
Изначально, после загрузки Linux, их настройки идентичны, что можем проверить так:

Код: Выделить всё

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
Смотрим теперь настройки порта + сравним со 2-м портом - что поменялось?

Код: Выделить всё

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
После завершения ./modopt (нажатием Enter) состояние порта (канонический режим) восстанавливается:

Код: Выделить всё

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$

Ответить

Вернуться в «Одноплатные компьютеры»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 4 гостя