here is one approach using relay logic almost exclusively. It is broken into several steps, plus an input output map to move internal states to the physical outputs. The steps correspond roughly to states of the system and the limited and pre-defined transitions between them....
The overall program simply calls each section.
I forgot to annotate the code sections:
At the "run program" step of the scan cycle (refer to @Ron Beaufort's boot camp video series), the PLC calls MAIN Program File
View attachment 63584, which in turn simply calls the other Program Files in sequence. Remember that the "run program" step is something that happens at
repeated and
discrete times, at a frequency of at least 10Hz, and typically between 100Hz-1kHz. The entire program starts over and executes the logic on the rungs, left-to-right and top-to-bottom,
but with a new (i.e in time) set of inputs on each execution.
The COMPOSITES Program File
View attachment 63580 creates some composite or compound booleans out of atomic booleans, which simplifies the logic in the business logic of the other Program Files. It also keeps track of the last floor visited by the elevator car, which is necessary to know which motor, up or down, to use to get to the middle of the three floors; note the use of the Start/Stop Circuit pattern.
The CHEWSLOGIC (Choose Logic) Program File
View attachment 63581 responds to the push buttons that choose the floor. Note again the use of Start/Stop pattern.
The DOOR_LOGIC Program File
View attachment 63582 controls the motors that open and close the elevator car doors. Note for a third time the use of the Start/Stop pattern
The MOTORLOGIC Program File
View attachment 63583 controls the motors that move the elevator car up or down. They do not need the full Start/Stop pattern, specifically they don't need the Seal-in branch, because the condition(s) that cause the motor to run are True until the motor should stop. Now that I look at it again, I think the middle contact on the door-closed limit switch, [XIC IN_DOOR_IS_CLOSED_LS], that would seem to there to stop the motor when the door opens, is probably unnecessary. Although, if someone forced the door open between floors then its presence would be a nice safety feature, if such features did not have to be hardwired to be safety-related.
Finally, there is one more useful pattern, the Process Simulation pattern, that many programmers keep in their toolbox. Note that all of the business logic of the program operates on internal memory (N- and B-files), and it is the the INPUT_MAP and OUTPUT_MAP Program Files that transfer between that the physical I/O. There are several advantages to that, which has been discussed elsewhere on this forum and also
here. One useful feature,
especially during code development, is that the I/O maps make it easy to integrate
a process simulation to emulate the behavior of the physical system: you can write the code and do some pre-FAT (Factory Acceptance Test) exercising of the business logic without any (elevator) hardware at all; with a PLC emulator (e.g. RSEmulate 500), you don't even need the PLC hardware. The simulation does not have to be overly complex; again, there is a design choice of the level of fidelity necessary to do the job. But the Simulation pattern can save a lot of time while the coder is still at the keyboard, by not having to waste time running up and down stairs to manually trigger a limit switch or some such to debug the logic.