Что корифеи скажут? Нет ли в моей теории явных ляпов?
Вид для печати
Что корифеи скажут? Нет ли в моей теории явных ляпов?
И еще сразу вопрос. По моим представлениям конфигуратор реализует некоторую последовательность опроса и в сущности выполняется в некоторой отдельной системной задаче. В общем опрос с конфигуратором выглядит как вариант №2. Так почему его ругают при большом количестве модулей?
Прям такой-эдакий "недоляп" вы только планируете работать и , как я понял , только структуру продумываете , а как у вас с кодом дела обстоят ?
1.Можно и без ПЛК начать тренироваться , только я вас заранее огорчу работать код будет не так как вы рассчитываете , а ... как есть , с некоторыми "нюансами".
2. При всем уважении к товарищам библиотечникам скажу так десятки проектов работают ч-з конфигуратор с количеством модулей 4...12 . Самый первый проект ч-з конфигуратор ПЛК100 работает по модбасу с 12ю частотниками (485й) и 8 модулей на DCON (232-АС3м) . Плюс слэйв , плюс сетевые переменные (UDP) .
3. Чисто для прикола сделал опрос 4 Z-SG (по 1му реалу) и МДВВ на базе дельты (1 DWORD - маска входов , 1 DWORD - маска выходов) ч-з сислибком (Овен Модбас либ мне не нравится ) и Что ???? Скорость ни капельки не увеличилась по сравнению с конфигуратором !!!
4. Конфигуратор работает НОРМАЛЬНО ! Просто как начудят , как наконфигурируют (мы конфигурировали-конфигурировали да невыконфигурировали:p) , что просто ... короче афтар жжот .
5. Теоретизировать по поводу кода опроса это как секс по книжкам изучать :p , лучше собственно и лично на практике ... пробовать ;).
6. Длительность выполнения программы в 50мс !!! Это что ? Программа управления космическим шаттлом ? Тогда модулей маловато ! Откуда вы берете эти дикие миллисекунды ?
7. Вообще "Если можешь что-то делать - бери и делай!" .
в конфигураторе определенно или не чистится буффер, или не проверяется соответствие отвечающего ведомого требуемому, что при малых таймаутах (настройка ожидания ответа меньше 100мс) приводило к сказочным результатам при управлении ПЧ и модулями мдвв. Возможно связано с тем, что ответ для ведомого с адресом 2 приходил с опозданием от ведомого 1. хотелось бы увидеть исходный код, отвечающий за работу конфигуратора. Думаю, много кто желает понять причину непредсказуемого поведения конфигуратора и знать наверняка, как обходить его подводные камни.
Набрал статистику скорости опроса по сети Modbus.
Мастером выступал ПЛК110. В качестве слейва выступал S7-1214 (он имитировал работу МВ110-8АС).
Опрос проводился с использованием библиотеки modbus.lib. Реализацию опроса прикрепляю (см. проект).
Мастер и слейв соединены проводом длиной 30 см.
Реальное время опроса оказалось значительно больше рассчитанного теоретически. Так для опроса 16 байт данных на скорости 115200 бод затрачивается 8мс, в то время как расчет дает значение в 1,9 мс (см. пост №20). С другой стороны если оценить разницу времени опроса 32 и 16 байт, 48 и 32 байт, то она как раз составляет 2 мс.
Для скорости 115 Кбод были получены данные для опроса 64, 80 и 96 байт.
64 байт = 14 мс;
80 байт = 16 мс;
96 байт = 18 мс.
Следовательно, опрос 16 байт, действительно, занимает примерно 1,9 мс. Т.е. практические данные сходятся с рассчитанными теоретически. Единственно, что теоретический расчет не учитывает некоторую постоянную составляющую.
А вот почему она такая большая - для скорости 115 Кбод примерно 6 мс - и почему разная для разных скоростей, мне пока не понятно.
Во всех экспериментах параметр MinCycleLength был установлен в 0.
Я думаю, что он тут не при чем.
я не вникал в проект.. а могу чисто интереса ради попросить установить MinCycleLength 10 ? Ну, просто очень любопытно...
А что Вы ожидаете увидеть?
изменение времени опроса в ту или иную сторону.
Насколько мне известно, параметр MinCycleLength определяет минимальное время цикла. Более того он дополняет его до указанного значения, если реальное время цикла меньше. Т.е. если MInCycleLength = 1 и некая PLC_PRG исполняется за 0,6 мс, то еще 0,4 мс процессор будет спать. Во время 0,6 мс я включаю и его сервисные операции. Учитывая, что у тестовой программы цикл выполнения был меньше 1 мс, то установка любого MinCycleLength отличного от 0 должна увеличить время опроса.
Вы согласны? Или у Вас другое мнение?
Пока суд да дело, провел интересующие Вас эксперименты.
Привожу данные:
MinCycleLength = 0 СВО = 7
MinCycleLength = 1 СВО = 7
MinCycleLength = 2 СВО = 8
MinCycleLength = 5 СВО = 10
MinCycleLength = 10 СВО = 20
СВО (среднее время опроса 4 байт на 115 Кбод).
Время увеличивается и кратно MinCycleLength, чего и следовало ожидать.
опять же стоит Вам для нас уточнить, как считаете среднее время опроса, возможно на больших циклах добавляется некая паразитная составляющая. Потому что обмен совершенно ге зависит от цикла основной программв, только получение результата лпроса
Проект опроса прикреплен к посту №46.
смешно, я еду в поезде и этот факт не дает мне предсьавления как организован опрос в Вашем проекте, потому что банально телефон не поддерживает КДС
SKV,
я просмотрел. навскидку: применяется CASE. не кавай. при переходе к следующему шагу, шаг выполняется в след цикле, насколько я помню... сейчас попробую разобраться детально. Увидел такие вещи как сканнинг и поллинг. Вы меня заинтересовали, буду изучать Ваш подход. Обратите внимание: в modbus.lib CASE не используются (видимо для ускорения). У меня тоже есть нечто подобное на стадии тестирования. Не могу довести до ума, тк нет контроллера. Могу я попросить попользоваться ПЛК через интернет?))
http://i.imgur.com/xSP9PEG.png
С позволения автора, могу в текстовом виде листинг прислать)))
Вот тут я уже ниасилил....
IF pDisp^.AdressForPooling = Base.Adress THEN
PoolingStat.SecondPoint();
IF GetData THEN AnswerStat.FirstPoint(); END_IF;
pDisp^.GetHoldRegs(
Enable:= GetData,
Mode:= MB_RTU,
DevAddr:= Base.Adress,
FirstAddr:= DataRegister,
Quantity:= RegisterCount,
ComHandle:= pDisp^.Settings.Port,
TimeOut:= TimeOut,
Buffer:= pDisp^.ReciveBuffer);
Указатели в VAR_INPUT можно заменить на внутренние переменные FB в разделе VAR_IN_OUT (это те же указатели в более удобоваримой для этих функций форме, не создают области памяти для себя и не происходит копирования переменных при вызове экземпляра. Поправьте меня, если ошибаюсь)
В принципе без детального изучения... разобрался. Вижу основную проблему быстродействия в CASE. Очередность вызовов диспетчером: диспетчер должен (имхо) не только устанавливать флаг, если время поллинга наступило, но и сразу же осуществлять вызов экземляров фб для записи чтения - для этого модули желательно унифицировать в массив из одноипных FB с массивами регистров внутрях. А массивы уже можно привязать к суказателям на структуры самих модулей в дальнейшем. Я пошел по такому пути.
Сегодня я уже должен идти. Завтра с удовольствием прокомментирую свой код.
а какой смысл в листинге? если человек не может объяснить алгоритм своей программы, это уже ни в какие ворота, а сделав попытку интерпретировать написанную прогу без алгоритма словами, в большинстве случаев приводит к нахождения способов её опьимизации или выявления багов
к Вашему сведенью программа подверглась измегениям со слов автора,правда в другой теме и почему я должен обращаться к давно выложенному файлу, чтоб возникло новое гедопонимание, кста на форуме поднималась не раз тема считать затраченое время и выкладывались достойные решения
capzap, пруфлинк, пожалуйста, на достойное решение с поллингом (диспетчером опроса группы ведомых с разным интервалом опроса для каждого)
Spectrum48k, я так понимаю, что Вы уже сами разобрались.
Действительно, ничего сложного. Каждый ФБ модуль имеет параметр PoolingTime, который определяет через какое время модуль требует опроса. В случае истечения этого времени модуль выставляет флаг ReqForPooling. Диспетчер в каждом цикле последовательно бегает по массиву модулей и как только увидел, что какой-то модуль выставил флаг на опрос, передает ему такое право, устанавливая переменную AdressForPooling в
значение адреса данного модуля. Когда модуль завершил опрос, он выставляет флаг готовности и диспетчер снова сканирует массив модулей на предмет запроса на опрос. Это общая схема.
Далее дам свое мнение по Вашим вопросам.
Действительно, можно так поступить. В сущности это будет тоже самое. Копирует он в область Var_input не весь массив, а только указатель. Так же он поступает в случае Var_In_out. Но подход с указателем все же имеет преимущество. Его Вы можете один раз проинициализировать (у меня это делается тут: If FirstScan ...). А вот переменную Var_IN_out вы должны при каждом вызове устанавливать.
Я об этом не думал, но задумаюсь над этим. Может, действительно, так сделаю. Но вообще-то это не должно влиять на время опроса, так как у меня последовательность вызовов такая: диспетчер, модуль1, модуль2 и т.д. Т.е. как только диспетчер выдаст кому-то разрешение на опрос, то на этом же скане модуль начнет опрос.
Так как время скана в тестовом примере меньше 1 мс, то любые подобные вещи (Case, вызов модуля из диспетчера) могут увеличить время опроса максимум на 2 мс, а мы видим, что для опроса 4 байт на 115 Кбод требуется 7мс. Я думаю причина где-то глубже.
Вспомнил. Я задумывался над тем, что могу тратить несколько сканов на разрешение опроса модулю. Поэтому, как видно, делаю так, что модуль вызывает диспетчер когда готов:
Base.Ready := TRUE;
pDisp^();
Но в этом случае диспетчер переходит из состояния Pooling в Scaning и не проводит сканирование.
Зато если написать так:
Base.Ready := TRUE;
pDisp^();
pDisp^();
То он еще и сканирование проведет.
А если вот так:
Base.Ready := TRUE;
pDisp^();
pDisp^();
pDisp^();
То проведет сканирование и если найдет нужный модуль, то сразу же даст ему разрешение на опрос и опрос следующего модуля начнется на этом же скане.
Спасибо за критику.
SKV, CASE в любом случае нужно убирать и не тиражироать вызовы (CASE заменить на IF Step = .. ;;;; IF Condition THEN Step := Step +1; IF Error THEN Step := 0; и т.д.), тк дисперчер должен после освобождения одного слейва тут же посылать запрос другому. Например, так (фрагмент моего "диспетчера"):
возможно, когда откатаю на паре объектов, выложу полностью. А пока не готов к жесткой критике со стороны старослужащих))Код:2: (*RUN*)
(*WatchDog*)
TON_WD(IN := TRUE, PT := Set_Poll.WDT);
IF TON_WD.Q THEN ErrCode := ErrCode_WatchDog; Step := 3; RETURN; END_IF
(*Last Cycle 'Busy' Slave: Busy Flag Check*)
IF Busy THEN
SLAVE[BusyNum](Busy => Busy);
IF SLAVE[BusyNum].Done THEN DoneNum := BusyNum; END_IF
END_IF
(*No 'Busy' Slave: Check all slaves for busy again *)
(*ДОБАВИЛ ДЛЯ ПОЯСНЕНИЯ В ЭТОМ ТОПИКЕ: в цикле и далее вызывается Массив из FB-слейвов, в каждом из них буффер чтения, буффер записи, флаги диагностики, таймеры таймаутов, счетчики ошибок, и естественно единственный код опроса на всех напрямую с ком портом без modbus.lib. При вызове обновляются таймеры и если какой-то из них превышает время поллинга больше других слейвов , то он "отправляется на опрос". Также есть вотч-дог диспетчера, если слейвы перестали опрашиваться в течение заданного интервала. *)
IF Busy = FALSE THEN
OverT:= t#0ms;
KickNum := 0;
BusyNum := 0;
FOR Cnt := 1 TO Set_Poll.SlaveCnt DO
IF SLAVE[Cnt].Set.Use THEN
SLAVE[Cnt](
Start:= FALSE,
Poll:= FALSE,
Reset:= FALSE
);
(*'Busy' Slave detected: Set common 'Busy' flag and return*)
IF SLAVE[Cnt].Busy THEN Busy := TRUE; BusyNum := Cnt; RETURN; END_IF
(*Calc Higher OverTime Slave number*)
IF SLAVE[Cnt].ByTime AND SLAVE[Cnt].OverTime > OverT THEN OverT := SLAVE[Cnt].OverTime; KickNum := Cnt; END_IF
END_IF
END_FOR
(*'Kick-start' slave with higher OverTime *)
IF KickNum > 0 THEN
(*New 'Kick-Start' : Reset WatchDog*)
TON_WD(IN := FALSE);
SLAVE[KickNum](Poll:= TRUE, Busy => Busy);
IF Busy THEN BusyNum := KickNum; END_IF
END_IF
END_IF
Еще раз по поводу быстродействия: в modbus.lib есть мистический таймер с вызовом PT:=t#3ms, точно не помню, но какжца, он все тормозит как минимум на один цикл. Модифицировать биб-ку или уходить от нее - это уже дело вкуса)
SKV - не слушайте никого про case. Case, case и еще раз case - удобней и читаемей.
А для ликвидации пустых шагов - while true do с return/exit в шагах при необходимости
Речь не идет о исключении CASE и свитч-технологий из обихода) Речь идет об оптимизации выполнения чтения-записи в одной единственной функции/функциональном блоке. В моем примере видно метку "шага" 2: того же самого CASE.
Валенок, вы опытный и мудрый программист, но здесь не хотите вникать снова )
Так как я предложил:
pDisp^();
pDisp^();
pDisp^();
Решает проблему с лишними сканами.
Отмечу также, что лишние сканы влияют на время между опросами, а не на время опроса модуля.
Саму идею использования If вместо, case там где нужно, чтобы на том же скане мы переходили на следующий шаг, буду иметь ввиду.
Обязательно изучите modbus.lib, а именно FB приема на наличие таймера таймаута t#3ms на предмет его необходимости и влияния этого таймера скорость работы биб-ки в части завершения ожидания приема буффера данных.
З.Ы. (да где вообще разработчики взяли это время...это не 1,5 и не 3,5 символа)
какие у кого решения ищите сами, на вкус и цвет ...
у меня есть свой взгляд на такой опрос и меня он вполне устраивает
я добрался до дома, посмотрел ваш проект, слишком всё заморочено, спецам Ваш код бесполезен, новички в нем не разберутся и зачем он такой нужен
что касается времен опроса при разных временах мин.цикла, они такие как есть,но я уже писал что на одной и той же скорости сам обмен время не поменяет, проблемы только с отображением результата в текущем циикле, причем это сильно зависит от полноты наполнения проекта, на видео которое выкладываю при работе только одного TON-а среднее время было 8мс, добавив второй таймер среднее время увеличилось на 2мс, уже не говорю если это будет полноценный проект. Кроме того на видео показал время свободное от работы процессора, мин.цикл лучше подбирать, чтоб оставался некоторый запас микросекунд. Я не сторонник нуля в мин.цикле, если хочется свободное выполнение для этого есть конфигуратор задач. Еще Вы что то писали про операции обмена после выполнения PLC_PRG, тогда стоит рассмотреть ситуацию с модбасом мастером в конфигураторе и программой в стопе, удивительно на данные из слейва будут читаться, так что по моему мнению искать связь выполнения программы и обмена не стоит и уменьшение ради этого мин.времени цикла бесполезное занятие и вообще это может привести к нестабильному или приему с большим количеством ошибок
ну не Вы же написали эту бибку, Вы ей только пользуетесь и цокаете и чем Вы отличаетесь от меня тогда? Поставил человек 3мс и ладно, не сильно это будет тормозить в отличии от 3,5 символовЦитата:
(да где вообще разработчики взяли это время...это не 1,5 и не 3,5 символа)
ЗЫ для видео увеличил время первого таймера до 300мс, но его можно поставить чуть больше среднего времени
Вынужден расстроить: ей только и не пользуюсь и не пользовался. Перед первым использованием открыл, изучил и передумал использовать. Написал в мае-июне свой луна-паркс блекджеком и плюшками. До этого пользовался конфигуратором. Как я ранее писал, конфигуратор меня очень расстроил. А вообще, я - фанат IOScanner )) Но об этом в другом форуме (se-automation.in.ua).Цитата:
ну не Вы же написали эту бибку, Вы ей только пользуетесь и цокаете и чем Вы отличаетесь от меня тогда? Поставил человек 3мс и ладно, не сильно это будет тормозить в отличии от 3,5 символов
да меня это вобще не задевает, чем Вы пользуетесь. Полноценный проект обычно занимает не менее 2мс, пауза между фреймами по стандарту не должна быть меньше этих пресловутых 3,5 символов, но больше то ни кто не запрещает, поэтому 3мс в бибке ни как не скажутся на работе, тем более приведенные здесь статистические данные относятся к 4 байтам, а в рабочих проектах выборка данных на много больше, таким образом гипотетически следующий запрос можно смело посылать в следующем цикле, вот только кто так делает
3,5 символа, это вообще по-хорошему интервал для ведомого, перед ответом ведущему. Мастер же не должен ничего ждать, если размер принятого буффера равен ожидаемому размеру. И после проверки CRC, адреса, функции и дальнейшей разборки пакета, должен в этом же вызове накормить следующий буфер отправки. Вот это было бы логично и быстро. А при использовании modbus.lib, давайте при готовом принятом буфере отдадим ~t#10ms основному вызову проекта каждый раз после принятого буфера. Для 8 регистров это будет каких-то t#80ms. Не мешает? Да пользуйтесь на здоровье. Плачьте и колитесь) Кактуса хватит на всех. А если опрос и проект(алгоритм) не разнесены по разным задачам, то это будет вообще паровоз....
повторюсь, я веду речь о модбас rtu, цитата из вики:" Сообщение должно начинаться и заканчиваться интервалом тишины, длительностью не менее 3,5 символов при данной скорости передачи. Во время передачи сообщения не должно быть пауз длительностью более 1,5 символов. Для скоростей более 19200 бод допускается использовать интервалы 1,75 и 0,75 мс, соответственно" ни о какой паузе между запросом и ответом речь не идет,хотя и включает в себя эту ситуацию тоже
что касается должен ли чего то ждать мастер, это обусловленно концепцией контроллеров, если в моем примере обработку ответа поставить в начало поу, так и выйдет получив ответ прога может сразу,в этом же цикле, отправить очередной запрос
а последняя часть Вашего опуса вобще какой то бред, неимеющий ни какого отношения к передаче данных
Сергей, не спешите приписывать мне патологическое расстройство сознания - вы не психиатр) Мой "бред" как раз опровергает это:
О Вашем примере речи не было, я его даже не смотрел, т.к. Вы не предложили это сделать)Цитата:
поэтому 3мс в бибке ни как не скажутся на работе
Если мои рассуждения не верны по-вашему, Вы можете обосновать свою точку зрения, а не приписывать диагнозы))