Просмотр полной версии : SysLibCom.lib (SysComRead) потеря байтов.
Приветствую, столкнулся со следующей проблемой на ПЛК 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;
Поиде данные должны остаться в буфере, и считаны при следующем обращении, или нет?
Где-то тут есть обсуждение легенды про якобы пропадающие байты. Ищите. Вместе с байтами.
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom
1.По фотографии уха сложно судить о красоте женщины. А простому человеке иногда еще сложно определить - а женщина ли вообще.
2.Интересно - кокой размер буфера ?
Где-то тут есть обсуждение легенды про якобы пропадающие байты. Ищите. Вместе с байтами.
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom
1.По фотографии уха сложно судить о красоте женщины. А простому человеке иногда еще сложно определить - а женщина ли вообще.
2.Интересно - кокой размер буфера ?
Размер буффера 255 байт. Как написано выше.
14642
На скрине видно потерю байт.
Пока остаюсь на скорости 9600, других вариантов нет. Использование UNM исключено, только SysLibCom и SysLibSockets.
Основная проблема в том, что если исключить из проекта работу с 5 сокетами(MODBUS MASTER TCP опрос 5 ПЛК по ETH ), то SysComRead не теряет данные на любых скоростях.
Время цикла при выполнении всей программы замеренное SysLibTime в пределах 1.4мс - 3,5мс не более.
тихо сам с собою....блин.
Господа Разработчики, ваш выход....
http://www.owen.ru/forum/showthread....ight=SysLibCom <- в этой теме ответа нет
ссылка же не открывается :)
А какие претензии к UNM
ссылка же не открывается :)
TO AlexPC1 (http://www.owen.ru/forum/member.php?u=9291)
Ссылки нужно вставлять этой кнопкой14647
Размер буффера 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 - по
Кусок кода чтения из порта:не в состоянии.
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
http://www.owen.ru/forum/showthread.php?t=12305&highlight=SysLibCom
К UNM претензий нет, но если я правильно понимаю то это ОВЕНовская библиотека, а программа которая сейчас в разработке должна работать и на ОВЕН и на WAGO
P.S. На WAGO она уже работает, потери байт нет
И начнете жалавацца начальству - овен такой, овен сякой, выходите подлые трусы
А Вы, блин, сдвигаете константное окно для приема за пределы буфера. Не факт что именно Ваша проблема - из-за этого. Но легенда - пойдет в мир.
Я не жалуюсь начальству, я и принимаю решение о выборе контроллера, начальству пофиг с чем мы работаем. Мне не пофиг, почему моя программа не работает так как мне необходимо.
А как себя ведет плк если работа с сокетами и портом разнесены по разным задачам?
Дмитрий Артюховский
07.10.2014, 09:26
1. Время цикла давайте с запасом, если у вас на выполнение тратиться 1.5-3.5 мс -> минимальное время цикла 4 мс. Разные прошивки плк очень по разному распределяют время для системных задач и задач пользователя при недостатке оного, поэтому резервируйте его. В модуле статистика есть индикатор достаточности ресурса времени - он не должен быть активен для стабильной работы.
2. Буфер для порта (резервируемый при открытии) можно и побольше, а не в притык.
3. Считывайте буфер в каждом цикле и накапливайте где-нить, собственно обработку можно и пореже проводить.
Пробовал в разные задачи, результат тот же. Только при исключении всего из проекта, ком читает нормально
1. Время цикла давайте с запасом, если у вас на выполнение тратиться 1.5-3.5 мс -> минимальное время цикла 4 мс. Разные прошивки плк очень по разному распределяют время для системных задач и задач пользователя при недостатке оного, поэтому резервируйте его. В модуле статистика есть индикатор достаточности ресурса времени - он не должен быть активен для стабильной работы.
2. Буфер для порта (резервируемый при открытии) можно и побольше, а не в притык.
3. Считывайте буфер в каждом цикле и накапливайте где-нить, собственно обработку можно и пореже проводить.
1. Время цикла перебиралось в пределах от 1 до 50 мс
2. Буфер порта 512, при чтении 255, запас 2х кратный
3. Считывание в каждом цикле, обработки пока вообще нет в программе, то есть в программе пока тупо чтение и все никаких обработок запроса, тупо смотрю на размер
Переходите на скорость 38400, где то писался примерный расчет затраченного времени на передачу стандартного запроса модбас на скорости 9600, вроде выходило на 10 байт 4мс, значит на 255 байт уйдет около 100мс, поэтому удивляет что пытаетесь принять за один цикл, но может я и не прав
Переходите на скорость 38400, где то писался примерный расчет затраченного времени на передачу стандартного запроса модбас на скорости 9600, вроде выходило на 10 байт 4мс, значит на 255 байт уйдет около 100мс, поэтому удивляет что пытаетесь принять за один цикл, но может я и не прав
Я не пытаюсь принять за один цикл, я читаю до появления в буфере 0, а потом еще жду 10мс и считаю прием закончен.
Чтение может происходить в нескольких циклах ПЛК. Поэтому ReciveBuffer+totalBytesResive верно. Но во фразе IF ByteResive > 0 THEN - ошибка (чтение кончаецо на первом цикле хотя вполне может и хотеть продолжицо. видимо отсюда потеря части пакета. ). Должно быть как то так:
IF ByteResive = Длинна ожидаемого пакета (вы же мастер и длину можно рассчитать)
OR ReadTimeout.Q THEN
чтение закончили
Ошибка таймаута = ReadTimeout.Q;
END_IF
А так же:
ByteResive := ByteResive + SysComRead(Port, Адрес буфера + ByteResive , Длинна ожидаемого пакета - ByteResive, 0 );
Соотв. перед началом чтения КАЖДОГО НОВОГО ПАКЕТА ByteResive должно быть рано нулю.
Остальной код не смотрел. )
Чтение может происходить в нескольких циклах ПЛК. Поэтому ReciveBuffer+totalBytesResive верно. Но во фразе IF ByteResive > 0 THEN - ошибка (чтение кончаецо на первом цикле хотя вполне может и хотеть продолжицо. видимо отсюда потеря части пакета. ). Должно быть как то так:
IF ByteResive = Длинна ожидаемого пакета (вы же мастер и длину можно рассчитать)
OR ReadTimeout.Q THEN
чтение закончили
Ошибка таймаута = ReadTimeout.Q;
END_IF
А так же:
ByteResive := ByteResive + SysComRead(Port, Адрес буфера + ByteResive , Длинна ожидаемого пакета - ByteResive, 0 );
Соотв. перед началом чтения КАЖДОГО НОВОГО ПАКЕТА ByteResive должно быть рано нулю.
Остальной код не смотрел. )
Спасибо, попробую. Отпишусь
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot