PDA

Просмотр полной версии : SysLibCom.lib (SysComRead) потеря байтов.



AlexPC1
06.10.2014, 12:13
Приветствую, столкнулся со следующей проблемой на ПЛК 110-30. порт RS232(COM1)
При чтении из буфера КОМ порта теряются байты, причем не начало или конец а середина.
Для отладки, в ком писал буфер 255байт со значениями от 1 до 255, заметил что пропадают
значения ....1,2,3,5,7,8,9,10,15,16,17, т.е куда то делись 4, 6 ,11 и, тд. закономерности особой нет,
могут теряться и другие.
Если оставить в проекте только процедуру чтения из порта то все вродебы в порядке, если сменить скорость на 9600, тоже становится легче.
Но в проекте крутится 5 сокетов, 1 ПИД и деть их никуда нельзя. И вот когда это все в куче работает получаю потерю байт.
Время цикла(MinCycleLength) менял в пределах от 1 до 50, остановился на 0, не помогло.
параметр dwBytesToRead, функции SysComRead, менял, было 1,2,3,4,8,16,32,64,128,255.

ReadTimeout(IN:=(ByteResive=0),PT:=T#10ms); Таймаут приема менял до 1000мс, Т.к данные шлю я то я их отправлял с интервалом 1 раз в 3 сек.
на скорости 9600 теряется 5% посылок
на скорости 19200 уже 50%
на скорости 115200 потеря 95% битых посылок

Кусок кода чтения из порта:
IF SerialOpen THEN
ByteResive := SysComRead(Port,ReciveBuffer+totalBytesResive,255, 0);
ReadTimeout(IN:=(ByteResive=0),PT:=T#10ms);
IF ByteResive > 0 THEN
totalBytesResive := totalBytesResive + ByteResive;
END_IF
IF ReadTimeout.Q THEN
ReadTimeout(IN:=FALSE);
IF totalBytesResive > 0 THEN
uiBytesResive := DWORD_TO_UINT(totalBytesResive);
END_IF
totalBytesResive := 0;
DataReceptionFinish := INIT;
serSTATE := serREAD;
INIT:=TRUE;
END_IF
ELSE
serSTATE := serOPEN;
END_IF
кто что посоветует?
Какой физический буфер ком порта?
Как отследить его переполнение?
Что будет если я буду забирать данные из ком порта 1 раз в 2 цикла(куда они денутся если я их не заберу)?
if (i MOD 2) = 0 then
ByteResive := SysComRead(Port,ReciveBuffer+totalBytesResive,255, 0);
end_if
i:=i+1;
Поиде данные должны остаться в буфере, и считаны при следующем обращении, или нет?

Валенок
06.10.2014, 15:57
Где-то тут есть обсуждение легенды про якобы пропадающие байты. Ищите. Вместе с байтами.
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom

1.По фотографии уха сложно судить о красоте женщины. А простому человеке иногда еще сложно определить - а женщина ли вообще.
2.Интересно - кокой размер буфера ?

AlexPC1
06.10.2014, 17:18
Где-то тут есть обсуждение легенды про якобы пропадающие байты. Ищите. Вместе с байтами.
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom

1.По фотографии уха сложно судить о красоте женщины. А простому человеке иногда еще сложно определить - а женщина ли вообще.
2.Интересно - кокой размер буфера ?

Размер буффера 255 байт. Как написано выше.

AlexPC1
06.10.2014, 17:30
14642
На скрине видно потерю байт.

AlexPC1
06.10.2014, 19:15
Пока остаюсь на скорости 9600, других вариантов нет. Использование UNM исключено, только SysLibCom и SysLibSockets.
Основная проблема в том, что если исключить из проекта работу с 5 сокетами(MODBUS MASTER TCP опрос 5 ПЛК по ETH ), то SysComRead не теряет данные на любых скоростях.
Время цикла при выполнении всей программы замеренное SysLibTime в пределах 1.4мс - 3,5мс не более.

тихо сам с собою....блин.

AlexPC1
06.10.2014, 21:13
Господа Разработчики, ваш выход....
http://www.owen.ru/forum/showthread....ight=SysLibCom <- в этой теме ответа нет

capzap
06.10.2014, 21:16
ссылка же не открывается :)

А какие претензии к UNM

petera
06.10.2014, 21:30
ссылка же не открывается :)

TO AlexPC1 (http://www.owen.ru/forum/member.php?u=9291)
Ссылки нужно вставлять этой кнопкой14647

Валенок
07.10.2014, 00:16
Размер буффера 255 байт. Как написано выше.
Так и думал.

ByteResive := SysComRead(Port,ReciveBuffer+totalBytesResive,255, 0);
ReadTimeout(IN:=(ByteResive=0),PT:=T#10ms);
IF ByteResive > 0 THEN
totalBytesResive := totalBytesResive + ByteResive;

Редкий момент - рождение легенды про глюк системы.
Пришлите извне байт так 300..500. Разом. И Вы запорете данные расположенные после буфера.
А если буфер в разделе объявлений последний - получите би-и-п и перезагрузку. И начнете жалавацца начальству - овен такой, овен сякой, выходите подлые трусы
А Вы, блин, сдвигаете константное окно для приема за пределы буфера. Не факт что именно Ваша проблема - из-за этого. Но легенда - пойдет в мир.

Может кто и поднялся на 11й уровень, но я не Герасимов, не могу по берцовой кости восстановить облик неардентальца. И, например, предсказать когда и где упадет SerialOpen - по

Кусок кода чтения из порта:не в состоянии.

AlexPC1
07.10.2014, 05:19
ReciveBuffer : POINTER TO ARRAY [0..511] OF BYTE;(*с запасом*)


IF NOT SerialOpen THEN
Delay := Delay + 1;
IF (Delay MOD 100) = 0 THEN
IF Opened = FALSE THEN
IF SysComOpen(Settings.Port) = 16#FFFFFFFF THEN
SysComClose(Settings.Port);
SerialOpen := FALSE;
Opened := FALSE;
ELSE
Opened := TRUE;
END_IF
ELSE
SerialOpen := NOT SysComSetSettings(Settings.Port, ADR(Settings));
END_IF
END_IF
ELSE
Delay := 0;
serSTATE := serSEND;
END_IF

AlexPC1
07.10.2014, 05:21
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom
К UNM претензий нет, но если я правильно понимаю то это ОВЕНовская библиотека, а программа которая сейчас в разработке должна работать и на ОВЕН и на WAGO
P.S. На WAGO она уже работает, потери байт нет

AlexPC1
07.10.2014, 05:26
И начнете жалавацца начальству - овен такой, овен сякой, выходите подлые трусы
А Вы, блин, сдвигаете константное окно для приема за пределы буфера. Не факт что именно Ваша проблема - из-за этого. Но легенда - пойдет в мир.
Я не жалуюсь начальству, я и принимаю решение о выборе контроллера, начальству пофиг с чем мы работаем. Мне не пофиг, почему моя программа не работает так как мне необходимо.

capzap
07.10.2014, 07:11
А как себя ведет плк если работа с сокетами и портом разнесены по разным задачам?

Дмитрий Артюховский
07.10.2014, 09:26
1. Время цикла давайте с запасом, если у вас на выполнение тратиться 1.5-3.5 мс -> минимальное время цикла 4 мс. Разные прошивки плк очень по разному распределяют время для системных задач и задач пользователя при недостатке оного, поэтому резервируйте его. В модуле статистика есть индикатор достаточности ресурса времени - он не должен быть активен для стабильной работы.
2. Буфер для порта (резервируемый при открытии) можно и побольше, а не в притык.
3. Считывайте буфер в каждом цикле и накапливайте где-нить, собственно обработку можно и пореже проводить.

AlexPC1
07.10.2014, 15:40
Пробовал в разные задачи, результат тот же. Только при исключении всего из проекта, ком читает нормально

AlexPC1
07.10.2014, 15:44
1. Время цикла давайте с запасом, если у вас на выполнение тратиться 1.5-3.5 мс -> минимальное время цикла 4 мс. Разные прошивки плк очень по разному распределяют время для системных задач и задач пользователя при недостатке оного, поэтому резервируйте его. В модуле статистика есть индикатор достаточности ресурса времени - он не должен быть активен для стабильной работы.
2. Буфер для порта (резервируемый при открытии) можно и побольше, а не в притык.
3. Считывайте буфер в каждом цикле и накапливайте где-нить, собственно обработку можно и пореже проводить.
1. Время цикла перебиралось в пределах от 1 до 50 мс
2. Буфер порта 512, при чтении 255, запас 2х кратный
3. Считывание в каждом цикле, обработки пока вообще нет в программе, то есть в программе пока тупо чтение и все никаких обработок запроса, тупо смотрю на размер

capzap
07.10.2014, 15:52
Переходите на скорость 38400, где то писался примерный расчет затраченного времени на передачу стандартного запроса модбас на скорости 9600, вроде выходило на 10 байт 4мс, значит на 255 байт уйдет около 100мс, поэтому удивляет что пытаетесь принять за один цикл, но может я и не прав

AlexPC1
09.10.2014, 17:55
Переходите на скорость 38400, где то писался примерный расчет затраченного времени на передачу стандартного запроса модбас на скорости 9600, вроде выходило на 10 байт 4мс, значит на 255 байт уйдет около 100мс, поэтому удивляет что пытаетесь принять за один цикл, но может я и не прав
Я не пытаюсь принять за один цикл, я читаю до появления в буфере 0, а потом еще жду 10мс и считаю прием закончен.

lazy
13.10.2014, 14:12
Чтение может происходить в нескольких циклах ПЛК. Поэтому ReciveBuffer+totalBytesResive верно. Но во фразе IF ByteResive > 0 THEN - ошибка (чтение кончаецо на первом цикле хотя вполне может и хотеть продолжицо. видимо отсюда потеря части пакета. ). Должно быть как то так:

IF ByteResive = Длинна ожидаемого пакета (вы же мастер и длину можно рассчитать)
OR ReadTimeout.Q THEN
чтение закончили
Ошибка таймаута = ReadTimeout.Q;
END_IF

А так же:

ByteResive := ByteResive + SysComRead(Port, Адрес буфера + ByteResive , Длинна ожидаемого пакета - ByteResive, 0 );

Соотв. перед началом чтения КАЖДОГО НОВОГО ПАКЕТА ByteResive должно быть рано нулю.
Остальной код не смотрел. )

AlexPC1
13.10.2014, 22:38
Чтение может происходить в нескольких циклах ПЛК. Поэтому ReciveBuffer+totalBytesResive верно. Но во фразе IF ByteResive > 0 THEN - ошибка (чтение кончаецо на первом цикле хотя вполне может и хотеть продолжицо. видимо отсюда потеря части пакета. ). Должно быть как то так:

IF ByteResive = Длинна ожидаемого пакета (вы же мастер и длину можно рассчитать)
OR ReadTimeout.Q THEN
чтение закончили
Ошибка таймаута = ReadTimeout.Q;
END_IF

А так же:

ByteResive := ByteResive + SysComRead(Port, Адрес буфера + ByteResive , Длинна ожидаемого пакета - ByteResive, 0 );

Соотв. перед началом чтения КАЖДОГО НОВОГО ПАКЕТА ByteResive должно быть рано нулю.
Остальной код не смотрел. )

Спасибо, попробую. Отпишусь