задержка цикла структурированного текста plc

Я пытаюсь создать цикл, в котором он начнется со 100 и упадет до тех пор, пока не достигнет точки, в которой условие while больше не выполняется.

я начал с

While Solar_Power_House_W_Solar_PER <= OneHundred AND BatChargePercent < OneHundred DO
    State_Dis_Charge := false
    FOR PLC_SetLoopChargeValue:= 100 TO 0 By -1  DO
        ConvertoReal   := INT_TO_LREAL(PLC_SetLoopChargeValue);
        Divide         := ConvertoReal DIV(100);
        PLC_SetCharge  := Divide;         
        PLC_Charge     := 1500 * PLC_SetCharge; 
        RB_Charge      := PLC_Charge;
        Visual_RBPower := 1500 * PLC_SetCharge;    (*Charge *) 
    END_FOR;

Проблема, с которой я столкнулся, заключается в том, что он работает слишком быстро, поэтому условие никогда не выходит из цикла while, потому что для обновления системы требуется некоторое время, поэтому я подумал о добавлении части задержки:

While Solar_Power_House_W_Solar_PER <= OneHundred AND BatChargePercent < OneHundred DO
    State_Dis_Charge := false;
    wait(IN:=not wait.Q , PT:=T#50ms);
    if Wait.Q Then 
        FOR PLC_SetLoopChargeValue:= 100 TO 0 By -1  DO
            ConvertoReal   := INT_TO_LREAL(PLC_SetLoopChargeValue);
            Divide         := ConvertoReal DIV(100);
            PLC_SetCharge  := Divide;         
            PLC_Charge     := 1500 * PLC_SetCharge; 
            RB_Charge      := PLC_Charge;
            Visual_RBPower := 1500 * PLC_SetCharge;    (*Charge *) 
        END_FOR; 
    END_IF;
END_WHILE;     

Как я думаю, это должно работать: каждые 50 мс должен выполняться 1 цикл for. В настоящее время ничего не происходит каждые 50 мс.


person tony1420    schedule 02.12.2018    source источник
comment
Привет Тони! Было немного сложно понять код, так как вы не предоставили полный пример. Надо бы иметь все декларации софта. Но я сразу вижу, почему он не выходит из цикла. Кажется, вы не меняете ни переменную Solar_Power_House_W_Solar_PER, ни переменную BatChargePercent. Какое бы значение они не имели при запуске цикла WHILE, это значение они сохранят.   -  person Jakob    schedule 03.12.2018
comment
да, это часть большого кода. Solar_Power_House_W_Solar_PER — это процент, который рассчитывается на основе показаний счетчика, который определяет, входит ли он в цикл или выходит из него. Более подробно, когда он работает, условие выполняется, поэтому он изменяет скорость заряда на 1 процент для каждого цикла цикла. Проблема в том, что он работает слишком быстро, поэтому, когда, например, он переходит от 100% к 30% менее чем за секунду, система недостаточно быстро реагирует на изменение, поэтому он возвращается к 100% и снова падает снова и снова. Итак, я попытался добавить задержку, и это вызывает проблемы   -  person tony1420    schedule 04.12.2018
comment
Solar_Power_House_W_Solar_PER, OneHundred или BatChargePercent должны быть изменены внутри цикла, иначе цикл никогда не закончится.   -  person Sergey Romanov    schedule 05.12.2018


Ответы (2)


Вы должны учитывать, что WHILE и FOR выполняются синхронно. Это означает блокировку. Это означает, что интерпретатор не выполняет следующую строку, пока не будет завершена предыдущая строка.

  1. Это означает, что «быстрый бег» здесь неприменим. Неважно, как быстро он работает, выполнение линий всегда будет в порядке.

  2. Единственное, я бы изменил и зациклил не от 100 до 0, а наоборот от 0 до 100, потому что я не уверен, что это обратно будет работать нормально. И тогда все, что вам нужно изменить:

    ConvertoReal   := INT_TO_LREAL(100 - PLC_SetLoopChargeValue);
    
  3. Теперь вы показываете весь код, ОЧЕНЬ ТРУДНО судить, но если FOR ткацкий станок завершен, это совершенно не имеет смысла. Вы вычисляете некоторые переменные, но не используете их там. Вы же знаете, что их нельзя использовать вне цикла FOR, верно? Потому что вне вашего цикла FOR эта переменная всегда будет иметь то же значение, что и в последнем цикле.

  4. Во втором примере ваш цикл FOR, хотя он может работать, вы не должны использовать таймер для запуска цикла внутри цикла. Потому что циклы синхронны и временами асинхронны.

  5. Насколько я понимаю, ваша задача WHILE вам вообще не нужна. При таком подходе выполнение других частей вашей программы будет заблокировано до 100%. Это может занять некоторое время, как я вижу. Таким образом, вы должны использовать IF.

    IF Solar_Power_House_W_Solar_PER <= OneHundred AND BatChargePercent < OneHundred DO
        // ....
    END_IF;
    

    Разница существенная. С WHILE ваша программа будет заблокирована до WHILE завершения, а другие части не будут выполняться в течение этого времени, в одном и том же цикле ПЛК FOR может выполняться столько раз.

    С IF if будет запускаться FOR один раз за один цикл ПЛК и фактически не изменит вашу логику.

  6. Если бы вы поделились своим полным кодом или хотя бы частями, где используются переменные, которые у вас есть, чтобы была видна вся картина, вы могли бы получить лучшую помощь. Отредактируйте свой пост, и я отредактирую свой комментарий.

person Sergey Romanov    schedule 05.12.2018

С этим ответом я только решаю вашу проблему с циклом for, который не выполняется каждые 50 мс. Другие ответы, почему цикл while не может быть завершен, верны, если переменные Solar_Power_House_W_Solar_PER и BatChargePercent не изменены в параллельном потоке.

Я предлагаю, чтобы wait был функциональным блоком TON. Обратите внимание, что имена FB чувствительны к регистру: wait.Q возможно не равно Wait.Q. Я думаю, что это основная причина, по которой ваш цикл for не выполняется, потому что вы проверяете вывод другого FB. Возможно, проверьте свой список объявлений на наличие двойников с более высокими или нижними регистрами.

Другая возможность заключается в том, что ваше условие для цикла while вообще не выполняется, и вы этого не заметили. В этом случае цикл for, конечно, тоже не будет выполняться.

person Wizzard    schedule 21.01.2019