Search code examples
controlsplcindustrial

PLC Ladder logic - problematic sequence using two potentiometer


I've spent many hours and and a ton of paper sketching and I haven't been able to stumble upon anything to get me past this problem.

We got two tanks filled with water and two pumps between them. We need to automatically push the water to the second tank using these pumps if h>hmax (Tank 1) and H

I can't figure out one thing. First sequence assumes that if H>Hmax the pump 1 or 2 will work (they can't work simultaneously). When the water is pumped to second tank and in first tank will fall, the sequence is repeated after the water is replenished in first tank. I can't figure out how to make automatic change in pumps using only potentiometer after each sequence. What i need to do more is to include failure of one of the pump. I'm dealing with this problem for almost a week.

diagram of system


Solution

  • Hope this is what you mean. I wrote it as an "working" pseudo code. In real life this code is not the best, cause from the moment on you have more then 2 pumps it should be complicated, but this one is very detailed. Also an emergency switch is missing (so a button someone can push if he has to stop the pumps manually). Better would be to use some function_blocks and methods...

    declaration:

    VAR
    //INPUT
    levelTank1          AT %I*  : INT;  //potentiometer 1
    levelTank2          AT %I*  : INT;  //potentiometer 2
    
    pump1Malfunction    AT %I*  : BOOL; //TRUE=pump has no malfunction || FALSE=malfunction
    pump2Malfunction    AT %I*  : BOOL;
    
    //OUTPUT
    pump1Operation      AT %Q*  : BOOL; //TRUE=pump should run
    pump2Operation      AT %Q*  : BOOL;
    
    lastPumpInOperation : BYTE := 1;
    
    nState  : UINT  := 0;
    END_VAR
    

    Somewhere you should define the min and max levvels, I did it as a constant value:

    VAR CONSTANT
    tank1Hmax   : INT   := 32000;
    tank1Hmin   : INT   := 5000;
    tank2Hmax   : INT   := 25000;
    tank2Hmin   : INT   := 2000;
    END_VAR
    

    As remark: the analog inputs are usually INT values, so max. level equals 32767

    And now the program:

    CASE nState OF
    0:  //wait till tank 1 is filled and make sure tank2 is not overcharged
        IF (levelTank1 >= tank1Hmax) AND NOT (levelTank2 >= tank2Hmax) THEN
            nState := 1;
        END_IF
    
    1: //start one pump
        //first check worst case - both pumps are broken
        IF NOT pump1Malfunction AND NOT pump2Malfunction THEN
            nState := 100;  //emergency 
        //last time pump1 was used, and now pump 2 should start when it has no malfunction
        ELSIF lastPumpInOperation = 1 AND pump2Malfunction THEN 
            pump2Operation := TRUE;
            lastPumpInOperation := 2;
            nState := 2;
        //last time pump2 was used, and now pump 1 should start when it has no malfunction
        ELSIF lastPumpInOperation = 2 AND pump1Malfunction THEN
            pump1Operation := TRUE;
            pump2Operation := FALSE;
            lastPumpInOperation := 1;
            nState := 2;
        //now we have to define what happens when one pump is in malfunction
        ELSIF NOT pump1Malfunction THEN
            pump2Operation := TRUE;
            pump1Operation := FALSE;
            lastPumpInOperation := 2;
            nState := 2;
        ELSIF NOT pump2Malfunction THEN
            pump1Operation := TRUE;
            lastPumpInOperation := 1;
            nState := 2;
        END_IF
    
    2: //pump operation till tank1 is "empty", tank2 is "full" or pump failure occurs
        IF (levelTank1 <= tank1Hmin) OR (levelTank2 >= tank2Hmax) THEN
            nState := 3; //stop pumps
        ELSIF (pump1Operation AND NOT pump1Malfunction) THEN //pump has gone in malfunction during operation
            nState := 1;    //go back to step2 to start another pump
        ELSIF (pump2Operation AND NOT pump2Malfunction) THEN
            nState := 1;
        END_IF
    
    3:  //stop pumps
        pump1Operation := FALSE;
        pump2Operation := FALSE;
        nState := 0;
    
    100:    //emergency
            //do what you can do - close the valve to tank1 or run as fast as you can
            pump1Operation := FALSE;
            pump2Operation := FALSE;
    
            IF (pump1Malfunction OR pump2Malfunction) THEN
                nState := 0;
            END_IF 
    END_CASE