Страница 13 из 13 ПерваяПервая ... 3111213
Показано с 121 по 130 из 130

Тема: Универсальный диспетчер для Modbus.lib

  1. #121

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    Изучил тему с работой с битами, и, наконец, смогу правильно сформировать вопрос)

    Почему настолько целесообразно работать с масками и смещениями (поглядел в модули других участников, что, собственно и помогло в написании задач под себя, но, вижу, что маски время от времени мелькают), ведь есть такой, вполне себе симпатичный инструмент, как EXTRACT? Ведь после получения всех данных, в случае, когда регистр набит кучей разнокалиберной информации, и она нам нужна (пусть не вся, но более 1-2) мы же уже заранее знаем, к какому номеру бита нам обратиться и, если, данные хранятся в 2+ битах, то мы просто клеим их в некоторую переменную. Или это слишком ресурсоемко, в отличие от обработки масками? Возможно это будет еще кому-то полезно при написании своих модулей
    Зачем вам экстракт, если любой бит можно распаковать ( упаковать) через точку прямо в программе?

  2. #122

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Зачем вам экстракт, если любой бит можно распаковать ( упаковать) через точку прямо в программе?
    Вот да, в частности, ж, есть еще unpack.. Почему же маски до сих пор в ходу? Настолько быстрее обработка? Или экономия загруженности железа?

  3. #123

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    Вот да, в частности, ж, есть еще unpack.. Почему же маски до сих пор в ходу? Настолько быстрее обработка? Или экономия загруженности железа?
    Дело не в экономии, а в удобстве. Экстрактов нужно 16 шт. для 16 битов, анпаков 2 шт., это лишние и ненужные блоки в программе, они занимают место и вообще не нужны.
    Работа с битами через точку намного удобнее, компактнее и проще во всём и на любом языке.
    Последний раз редактировалось kondor3000; 08.10.2023 в 21:14.

  4. #124

    По умолчанию

    Как ни странно, приведя в пример шлюз дайкин - из 50+ устройств исключительно с ним больше всего приключений. В данный момент - не хочет опрашиваться в цикле. В чем суть - есть 5 регистров на чтение, 5 на запись. 7 файнкойлов. Каждый последующий койл хранит для себя данные, начиная от первого и +6 регистров. То есть, фактически, сводится к написанию 10 циклов For с параметром регистра StartRegister1 + ((CurrentCon-1)*6). Но, по каким-то причинам, данный шлюз так опрашиваться не хотит.. То есть, если мы пишем следующую конструкцию, то все данные у нас - нулевые. При этом - ошибок нет. В буфере мы видим наши данные, ошибки не копятся, ибо модуль ответил и все ок.
    IF Mdl.ExecStep = 1 THEN
    FOR CurrentCon:=1 TO 7 DO

    Mdl.pDisp^.GetInputRegs(Enable:= NOT Mdl.pDisp^.GetInputRegs.Read,
    Mode:= MB_RTU,
    DevAddr:= Mdl.Base.Adress,
    FirstAddr:= StartRegister1 + ((CurrentCon-1)*6),
    Quantity:= RegisterCount,
    ComHandle:= Mdl.pDisp^.Settings.Port,
    TimeOut:= Mdl.Base.TimeOut,
    Buffer:= Mdl.pDisp^.ReciveBuffer);

    IF Mdl.pDisp^.GetInputRegs.Complete THEN
    tmpReadError := Mdl.pDisp^.GetInputRegs.Exception;
    IF tmpReadError = 0 THEN

    pData := ADR(Mdl.dwDaikinRegisterRead); (*просто переменная, типа Слово, для текущего значения текущего кондея*)
    pData^ := Mdl.pDisp^.ReciveBuffer[1];
    pData := pData + 1;
    pData^ := Mdl.pDisp^.ReciveBuffer[0];
    Mdl.RCurTemp[CurrentCon]:=Mdl.dwDaikinRegisterRead; (* Пихаем полученные данные в объявленный массив из интов *)

    ELSE

    fcModuleAddAttempt(MdlBase := Mdl.Base);

    IF Mdl.Base.CurrentAttempt > Mdl.Base.MaxAttempts THEN
    Mdl.ExecStep := CompleteExecStep;
    END_IF;
    END_IF;
    END_IF;
    END_FOR;
    Mdl.ExecStep:=Mdl.ExecStep+1;
    END_IF;

    Однако, если мы убираем цикл, опрашивая один регистр, на примере:
    CurrentCon:=1;
    IF Mdl.ExecStep = 1 THEN
    Mdl.pDisp^.GetInputRegs(Enable:= NOT Mdl.pDisp^.GetInputRegs.Read,
    Mode:= MB_RTU,
    DevAddr:= Mdl.Base.Adress,
    FirstAddr:= StartRegister1 + ((CurrentCon-1)*6),
    Quantity:= RegisterCount,
    ComHandle:= Mdl.pDisp^.Settings.Port,
    TimeOut:= Mdl.Base.TimeOut,
    Buffer:= Mdl.pDisp^.ReciveBuffer);

    IF Mdl.pDisp^.GetInputRegs.Complete THEN
    tmpReadError := Mdl.pDisp^.GetInputRegs.Exception;
    IF tmpReadError = 0 THEN

    pData := ADR(Mdl.dwDaikinRegisterRead);
    pData^ := Mdl.pDisp^.ReciveBuffer[1];
    pData := pData + 1;
    pData^ := Mdl.pDisp^.ReciveBuffer[0];
    Mdl.RCurTemp[CurrentCon]:=Mdl.dwDaikinRegisterRead;
    CurrentCon:=CurrentCon+1;
    Mdl.ExecStep:=Mdl.ExecStep+1;

    ELSE

    fcModuleAddAttempt(MdlBase := Mdl.Base);
    IF Mdl.Base.CurrentAttempt > Mdl.Base.MaxAttempts THEN
    Mdl.ExecStep := CompleteExecStep;
    END_IF;
    END_IF;
    END_IF;
    END_FOR;
    END_IF;

    (*Далее опрос следующего кондиционера на те же данные *)
    IF Mdl.ExecStep = 1 THEN
    CurrentCon:=2;
    ...

    То после этого начинает все отличнейше работать. И можно было бы забить на циклы в целом, и на каждый регистр скопировать данный блок, но, исходя из того, что, в общей сложности 10 регистров * 7 койлов получается 70 блоков. Да и неаккуратно как-то.. Ткните, пожалуйста носом, что не так..
    Последний раз редактировалось Easy_Enemy; 16.11.2023 в 23:26.

  5. #125

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    Как ни странно, приведя в пример шлюз дайкин - из 50+ устройств исключительно с ним больше всего приключений. В данный момент - не хочет опрашиваться в цикле. В чем суть - есть 5 регистров на чтение, 5 на запись. 7 файнкойлов. Каждый последующий койл хранит для себя данные, начиная от первого и +6 регистров. То есть, фактически, сводится к написанию 10 циклов For с параметром регистра StartRegister1 + ((CurrentCon-1)*6). Но, по каким-то причинам, данный шлюз так опрашиваться не хотит.. То есть, если мы пишем следующую конструкцию, то все данные у нас - нулевые. При этом - ошибок нет. В буфере мы видим наши данные, ошибки не копятся, ибо модуль ответил и все ок.
    IF Mdl.ExecStep = 1 THEN
    FOR CurrentCon:=1 TO 7 DO

    Mdl.pDisp^.GetInputRegs(Enable:= NOT Mdl.pDisp^.GetInputRegs.Read,
    Mode:= MB_RTU,
    DevAddr:= Mdl.Base.Adress,
    FirstAddr:= StartRegister1 + ((CurrentCon-1)*6),
    Quantity:= RegisterCount,
    ComHandle:= Mdl.pDisp^.Settings.Port,
    TimeOut:= Mdl.Base.TimeOut,
    Buffer:= Mdl.pDisp^.ReciveBuffer);

    IF Mdl.pDisp^.GetInputRegs.Complete THEN
    tmpReadError := Mdl.pDisp^.GetInputRegs.Exception;
    IF tmpReadError = 0 THEN

    pData := ADR(Mdl.dwDaikinRegisterRead); (*просто переменная, типа Слово, для текущего значения текущего кондея*)
    pData^ := Mdl.pDisp^.ReciveBuffer[1];
    pData := pData + 1;
    pData^ := Mdl.pDisp^.ReciveBuffer[0];
    Mdl.RCurTemp[CurrentCon]:=Mdl.dwDaikinRegisterRead; (* Пихаем полученные данные в объявленный массив из интов *)

    ELSE

    fcModuleAddAttempt(MdlBase := Mdl.Base);

    IF Mdl.Base.CurrentAttempt > Mdl.Base.MaxAttempts THEN
    Mdl.ExecStep := CompleteExecStep;
    END_IF;
    END_IF;
    END_IF;
    END_FOR;
    Mdl.ExecStep:=Mdl.ExecStep+1;
    END_IF;

    Однако, если мы убираем цикл, опрашивая один регистр, на примере:
    CurrentCon:=1;
    IF Mdl.ExecStep = 1 THEN
    Mdl.pDisp^.GetInputRegs(Enable:= NOT Mdl.pDisp^.GetInputRegs.Read,
    Mode:= MB_RTU,
    DevAddr:= Mdl.Base.Adress,
    FirstAddr:= StartRegister1 + ((CurrentCon-1)*6),
    Quantity:= RegisterCount,
    ComHandle:= Mdl.pDisp^.Settings.Port,
    TimeOut:= Mdl.Base.TimeOut,
    Buffer:= Mdl.pDisp^.ReciveBuffer);

    IF Mdl.pDisp^.GetInputRegs.Complete THEN
    tmpReadError := Mdl.pDisp^.GetInputRegs.Exception;
    IF tmpReadError = 0 THEN

    pData := ADR(Mdl.dwDaikinRegisterRead);
    pData^ := Mdl.pDisp^.ReciveBuffer[1];
    pData := pData + 1;
    pData^ := Mdl.pDisp^.ReciveBuffer[0];
    Mdl.RCurTemp[CurrentCon]:=Mdl.dwDaikinRegisterRead;
    CurrentCon:=CurrentCon+1;
    Mdl.ExecStep:=Mdl.ExecStep+1;

    ELSE

    fcModuleAddAttempt(MdlBase := Mdl.Base);
    IF Mdl.Base.CurrentAttempt > Mdl.Base.MaxAttempts THEN
    Mdl.ExecStep := CompleteExecStep;
    END_IF;
    END_IF;
    END_IF;
    END_FOR;
    END_IF;

    (*Далее опрос следующего кондиционера на те же данные *)
    IF Mdl.ExecStep = 1 THEN
    CurrentCon:=2;
    ...

    То после этого начинает все отличнейше работать. И можно было бы забить на циклы в целом, и на каждый регистр скопировать данный блок, но, исходя из того, что, в общей сложности 10 регистров * 7 койлов получается 70 блоков. Да и неаккуратно как-то.. Ткните, пожалуйста носом, что не так..
    Не получится использовать цикл FOR, т.к. опрос каждого регистра занимает некоторое время, а вы пытаетесь за ОДИН программный цикл ПЛК опросить сразу ВСЕ регистры.
    Во втором случае у вас счётчик CurrentCon инкрементируется только после завершения предыдущего запроса, что конечно правильно

  6. #126

    По умолчанию

    Цитата Сообщение от 1exan Посмотреть сообщение
    Не получится использовать цикл FOR, т.к. опрос каждого регистра занимает некоторое время, а вы пытаетесь за ОДИН программный цикл ПЛК опросить сразу ВСЕ регистры.
    Во втором случае у вас счётчик CurrentCon инкрементируется только после завершения предыдущего запроса, что конечно правильно
    Да, там, по документации получается, что-то типа 2 по 2,5 мс на чтение/формирование ответа и по 20мс на запрос-ответ, просто странно как-то.. фактически же одно и тоже, мы ничего лишнего не обрабатываем между перемещением к следующему регистру.. уж не на 45 мс.. При этом, мы же ждем обработку данных (IF Mdl.pDisp^.GetInputRegs.Complete THEN), или я что-то путаю? В довесок - при опросе через цикл - у нас прям все данные - нули и, если я правильно понимаю, даже, если шлюз не успевает ответить - как минимум первое значение мы же должны были получить?..

    Ну и, с точки зрения опыта - есть, может быть, у кого-то мысли, как сделать правильно в данной ситуации?.. Получается, железка довольно медленная, информации с нее - много. Опрос получается нереально долгим.. Уже придется делить не то, что "сейчас - чтение, в следующее обращение - запись", а, прям "один цикл - один кондей"

    Пробовал переиначить, выбросив FOR, использовав IF CurrentCon <> 7 ... CurrentCon:=CurrentCon+1; в конце обработки данных, что, по-сути около-одно и тоже, с другой стороны - не понимаю, чем использование "следующего шага" отличается настолько, что с ним все преображается..
    Последний раз редактировалось Easy_Enemy; 17.11.2023 в 18:39.

  7. #127

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    Да, там, по документации получается, что-то типа 2 по 2,5 мс на чтение/формирование ответа и по 20мс на запрос-ответ, просто странно как-то.. фактически же одно и тоже, мы ничего лишнего не обрабатываем между перемещением к следующему регистру.. уж не на 45 мс.. При этом, мы же ждем обработку данных (IF Mdl.pDisp^.GetInputRegs.Complete THEN), или я что-то путаю? В довесок - при опросе через цикл - у нас прям все данные - нули и, если я правильно понимаю, даже, если шлюз не успевает ответить - как минимум первое значение мы же должны были получить?..

    Ну и, с точки зрения опыта - есть, может быть, у кого-то мысли, как сделать правильно в данной ситуации?.. Получается, железка довольно медленная, информации с нее - много. Опрос получается нереально долгим.. Уже придется делить не то, что "сейчас - чтение, в следующее обращение - запись", а, прям "один цикл - один кондей"

    Пробовал переиначить, выбросив FOR, использовав IF CurrentCon <> 7 ... CurrentCon:=CurrentCon+1; в конце обработки данных, что, по-сути около-одно и тоже, с другой стороны - не понимаю, чем использование "следующего шага" отличается настолько, что с ним все преображается..
    Может пример вам поможет, как считать 280 регистров с 7 блоков за 30-80 ms. Чтение и запись надо разнести по шагам CASE.
    https://owen.ru/forum/showthread.php?t=10555&page=987
    https://owen.ru/forum/showthread.php...&page=988#9876
    Последний раз редактировалось kondor3000; 17.11.2023 в 19:35.

  8. #128

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Может пример вам поможет, как считать 350 регистров с 7 блоков за 30-80 ms. Чтение и запись надо разнести по шагам CASE.
    https://owen.ru/forum/showthread.php?t=10555&page=987
    https://owen.ru/forum/showthread.php...&page=988#9876
    Насколько я понял, тут общение происходит через входы/выходы самого плк? По ним не было проблем, тоже довольно шустрый, в моей случае -160М02, управляет парогенератором, воздушными заслонками и частью вентиляции. Без нареканий. Как и овеновские модули, кстати - по модбас - никаких нареканий в нестабильности работы. А вот дайкиновская железяка (на секундочку - за 4.800 евро) прям расстроила.. Тогда, примем, как факт невозможность опроса в цикле..

    Спасибо за помощь!

  9. #129

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    Насколько я понял, тут общение происходит через входы/выходы самого плк? По ним не было проблем, тоже довольно шустрый, в моей случае -160М02, управляет парогенератором, воздушными заслонками и частью вентиляции. Без нареканий. Как и овеновские модули, кстати - по модбас - никаких нареканий в нестабильности работы. А вот дайкиновская железяка (на секундочку - за 4.800 евро) прям расстроила.. Тогда, примем, как факт невозможность опроса в цикле..

    Спасибо за помощь!
    Опрос 7 модулей МВ110-8АС по Модбас, с помощью String через структуру. Через String можно ещё и записывать (если надо)
    Последний раз редактировалось kondor3000; 17.11.2023 в 19:52.

  10. #130
    Пользователь
    Регистрация
    23.09.2008
    Адрес
    Центророссийск
    Сообщений
    2,278

    По умолчанию

    Цитата Сообщение от Easy_Enemy Посмотреть сообщение
    .. . Тогда, примем, как факт невозможность опроса в цикле..
    Просто Вы немного неправильно понимаете термин "цикл". Точнее - у вас в голове совместилось понятие цикла плк и цикла опроса. Про case вам выше говорили.

Страница 13 из 13 ПерваяПервая ... 3111213

Похожие темы

  1. Универсальный блок питания ПР114
    от sea в разделе Программируемые реле
    Ответов: 12
    Последнее сообщение: 13.10.2013, 22:56
  2. PCLogger - универсальный логгер для CDS v3
    от Mikhail Shvetsov в разделе ПЛК3хх
    Ответов: 0
    Последнее сообщение: 23.11.2012, 14:39
  3. Универсальный Modbus Сервер Инсат и 200 контроллеров ПЛК-100
    от lomtik в разделе Сетевые технологии
    Ответов: 17
    Последнее сообщение: 08.11.2012, 23:42
  4. Универсальный конфигурируемый регулятор
    от ОООСА в разделе Разработки
    Ответов: 32
    Последнее сообщение: 09.12.2009, 22:12
  5. Ответов: 7
    Последнее сообщение: 04.05.2009, 10:42

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •