OK, for those that might be interested, as promised, here is my shot at the multiple-pump problem.The aim of this coding is to automatically determine which pump to bring on-line when the demand increases. Then, when demand decreases, which pump to bring off-line.
The over-all aim is to maintain equal run times on all of the pumps as much as possible.
This routine will constantly attempt to bring all available pumps to equal operating times.
The coding described assumes that "POINTERS" are not available on the PLC. Having "POINTERS" would certainly reduce the amount of coding greatly.
General Description:
Code is created to monitor the Auto/Man Switch. The code should should also monitor for Running pumps faulting out. This code is used to set the "Available" status.
Demand vs. Supply is monitored and decisions are made as to whether a pump should be brought on-line, off-line or no change.
If need to add a pump, ADD PUMP goes TRUE for one scan.
If need to drop a pump, SUB PUMP goes TRUE for one scan.
The change in Demand vs. Supply needs to sufficiently large and of sufficient time. That is, you don't want pumps reacting too quickly to minor changes in Demand vs. Supply.
If there is no change in Demand vs. Supply then the code is bypassed.
The manner in which demand is determined depends on the particular situation.
If Demand Increases: ADD PUMP
The code looks through the "available" pumps to find the pump with the least run-time and brings that pump on-line.
If Demand Decreases: SUB PUMP
The code looks through the "running" pumps to determine which one has the most run-time and brings that pump off-line.
The method used to find the least or most is a "Single Scan Bubble Sort".
A "Bubble Sort" is a method where a value is compared to some other value and a determination is made as to whether to carry forth the former value or the latter value.
At the end of the Bubble Sort, the pump with the least or most run-time (depending on what is sought) is in hand. That pump is then brought on-line or off-line as required.
Meanwhile, there is a 1-sec timer that initiates a run-time update on all running pumps. This is a 1-scan pulse that updates the run-time on all running pumps. Run-time is tracked by Hour-Minute-Second for each pump.
Because pumps are occasionally taken off-line and repaired or replaced, there should be a means to reset the run-time for each pump to zero.
Preliminary Setup:
(this can be done in many different ways, this is just one)
This particular problem, as posted, involves 5 pumps.
Five words of memory need to be set aside for each pump.
PUMP-1 (A-Data)
Word 1 V100 Pump ID # (1, 0001 binary) hard-coded
Word 2 V101 Pump-A Status (1=Available 0001) (3=Running 0011)
Word 3 V102 Pump-A Hours (0 to 32,768)
Word 4 V103 Pump-A Minutes (0 to 59)
Word 5 V104 Pump-A Seconds (0 to 59)
PUMP-2 (B-Data)
Word 1 V200 Pump ID # (2, 0010 binary) hard-coded
Word 2 V201 Pump-B Status (1=Available 0001) (3=Running 0011)
Word 3 V202 Pump-B Hours (0 to 32,768)
Word 4 V203 Pump-B Minutes (0 to 59)
Word 5 V204 Pump-B Seconds (0 to 59)
Repeat and inc as required for Pumps 3(C), 4(D) and 5(E).
In this example,
Word VX00...
0000 = n/a
0001 = Pump-1 (A)
0010 = Pump-2 (B)
0011 = Pump-3 (C)
0100 = Pump-4 (D)
0101 = Pump-5 (E)
Word VX01...
0000 = Not Available
0001 = Available
0010 = Faulted while running -> NOT AVAILABLE 'til reset
0011 = RUNNING
There are any number of ways to set up the intelligence in the code.
Another set of five words need to be set aside as the "Working Registers".
Work Reg Data (R)
Word 1 V600 Pump ID # (1, 2, 3, 4 or 5 in binary) variable info
Word 2 V601 Pump-X Status (1=Available 0001) (3=Running 0011)
Word 3 V602 Pump-X Hours (0 to 32,768)
Word 4 V603 Pump-X Minutes (0 to 59)
Word 5 V604 Pump-X Seconds (0 to 59)
This routine completes in 1 Scan!
There will be a few holes in the following code... I'm just trying to present the general idea.
Again, this code can be greatly reduced if it is done with pointers.
So.... Supply vs. Demand Monitor says,
"ADD Pump" Find Least Run Time on Available Pump.
ADD A +-------------+
PUMP Stat 1 | Copy A-Data |
---| |------|=|----------+ to +-----(SET)REG LOADED
| Working Reg |
+-------------+
.
If Pump-A is available (A-Stat=1) then the words associated with Pump-A are loaded into the working register. The Reg Loaded Flag is SET.
.
ADD B REG +--------+ REG
PUMP Stat 1 LOADED | COPY B | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG B R | +--------+
| LOADED Hr Hr |
+---| |---+---|<|-----------------------+
| B R B R |
| Hr Hr Min Min |
+---|=|---+---|<|-------------+
| B R B R |
|Min Min Sec Sec|
+---|=|-------|<|---+
.
If Reg is NOT loaded, and Pump-B is available, then Pump-B data is loaded into the working reg and the flag is set. Then proceed to find the next available pump.
If Reg IS loaded then begin comparing Pump-B run-time to the run-time in the working reg. If Pump-B has less run-time, then copy Pump-B data into the working reg. Then proceed to find the next available pump.
That pump with the lesser run-time continues to reside in the work register. That is the "Bubble Sort".
.
ADD C REG +--------+ REG
PUMP Stat 1 LOADED | COPY C | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG C R | +--------+
| LOADED Hr Hr |
+---| |---+---|<|-----------------------+
| C R C R |
| Hr Hr Min Min |
+---|=|---+---|<|-------------+
| C R C R |
|Min Min Sec Sec|
+---|=|-------|<|---+
ADD D REG +--------+ REG
PUMP Stat 1 LOADED | COPY D | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG D R | +--------+
| LOADED Hr Hr |
+---| |---+---|<|-----------------------+
| D R D R |
| Hr Hr Min Min |
+---|=|---+---|<|-------------+
| D R D R |
|Min Min Sec Sec|
+---|=|-------|<|---+
ADD E REG +--------+ REG
PUMP Stat 1 LOADED | COPY E | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG E R | +--------+
| LOADED Hr Hr |
+---| |---+---|<|-----------------------+
| E R E R |
| Hr Hr Min Min |
+---|=|---+---|<|-------------+
| E R E R |
|Min Min Sec Sec|
+---|=|-------|<|---+
ADD REG +--------------+ REG
PUMP LOADED | NO PUMPS | LOADED
---| |---+---|/|------+ AVAILABLE!!! +---+---(RESET)
| +--------------+ |
| REG +--------------+ |
| LOADED | Read Pump ID | |
+---| |------+ In V601 and +---+
+----------------->| Start Pump-X |
| +--------------+
|
+-- This causes Pump-X to attempt to start. The Aux contact
on the mag is read to determine if the pump has in fact
started. If so, then the status of the pump is set to
"running". If, after a delay, the Aux contact is not
closed, then the pump status is set to UNAVAILABLE!
The process then begins again to find the next pump.
So.... Supply vs. Demand Monitor says,
"SUB Pump" Find Most Run Time on Running Pump.
SUB A +-------------+
PUMP Stat 1 | Copy A-Data |
---| |------|=|----------+ to +-----(SET)REG LOADED
| Working Reg |
+-------------+
.
If Pump-A is running (A-Stat=3) then the words associated with Pump-A are loaded into the working register. The Reg Loaded Flag is SET.
.
SUB B REG +--------+ REG
PUMP Stat 1 LOADED | COPY B | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG B R | +--------+
| LOADED Hr Hr |
+---| |---+---|>|-----------------------+
| B R B R |
| Hr Hr Min Min |
+---|=|---+---|>|-------------+
| B R B R |
|Min Min Sec Sec|
+---|=|-------|>|---+
.
If Reg is NOT loaded, and Pump-B is running, then Pump-B data is loaded into the working reg and the flag is set. Then proceed to find the next running pump.
If Reg IS loaded then begin comparing Pump-B run-time to the run-time in the working reg. If Pump-B has more run-time, then copy Pump-B data into the working reg. Then proceed to find the next running pump.
.
SUB C REG +--------+ REG
PUMP Stat 1 LOADED | COPY C | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG C R | +--------+
| LOADED Hr Hr |
+---| |---+---|>|-----------------------+
| C R C R |
| Hr Hr Min Min |
+---|=|---+---|>|-------------+
| C R C R |
|Min Min Sec Sec|
+---|=|-------|>|---+
SUB D REG +--------+ REG
PUMP Stat 1 LOADED | COPY D | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG D R | +--------+
| LOADED Hr Hr |
+---| |---+---|>|-----------------------+
| D R D R |
| Hr Hr Min Min |
+---|=|---+---|>|-------------+
| D R D R |
|Min Min Sec Sec|
+---|=|-------|>|---+
SUB E REG +--------+ REG
PUMP Stat 1 LOADED | COPY E | LOADED
---| |------|=|---+---|/|---------------------------------+--+ to REG +---(SET)
| REG E R | +--------+
| LOADED Hr Hr |
+---| |---+---|>|-----------------------+
| E R E R |
| Hr Hr Min Min |
+---|=|---+---|>|-------------+
| E R E R |
|Min Min Sec Sec|
+---|=|-------|>|---+
SUB REG +--------------+ REG
PUMP LOADED | Read Pump ID | LOADED
---| |-------| |------+ In V601 and +--------(RESET)
| Stop Pump-X |
| Reset Status |
+--------------+
Meanwhile, update the run-time for each running pump. Five copies of the following code need to be built; one for each pump.
1 A +--------------+ Dummy
Sec Stat 3 Sec 59 Min 59 Hr 32,768 | Hour OverRun | Bit
--| |----|=|---+---|=|---+---|=|---+---|=|--------+ Message +------------------+--( )
| | | +--------------+ |
| | | Hr 32,768 |
| | +---|<|-------[ADD Hr+1=Hr]---[Min=0]-+-[Sec=0]--+
| | | |
| |Min 59 | |
| +---|<|-------[ADD Min+1=Min]-------------------+ |
| |
|Sec 59 |
+---|<|-------[ADD Sec+1=Sec]----------------------------------------+
So, there ya go... whadaya think?