Building a Reliable 2-Floor Hydraulic Goods Lift PLC Program: Our Minimalist Control Philosophy

Hydraulic goods lifts do not always require complicated PLC programs. In fact, many field problems come from software that has become unnecessarily complex over time.

After building and commissioning numerous hydraulic lifting platforms and goods lifts, we decided to develop a standardized PLC program specifically for our two-floor hydraulic goods lifts. Our goal was simple:

Make the program easy to understand, easy to maintain, and easy to expand in the future.

This article introduces the design philosophy behind our PLC program and explains why a minimalist architecture often results in a more reliable lifting system.

Why Simplicity Matters

A hydraulic goods lift performs only a few basic tasks:

  • Receive an up or down call.

  • Verify all safety conditions.

  • Drive the hydraulic system.

  • Stop accurately at the destination floor.

  • Protect both the equipment and the operator.

Instead of mixing all these functions together, we separate them into independent layers.

This makes troubleshooting much easier for both our engineers and customers.

Layer 1 – Safety Logic

Safety always has the highest priority.

The first part of the PLC program determines whether movement is allowed at all.

Our safety layer includes:

  • Emergency Stop

  • Light Curtain

  • Safety Edge

  • Safety Circuit

  • Upper Travel Limit

These signals are processed before any movement request is accepted.

For example:

  • Pressing the Emergency Stop immediately disables all movement.

  • Triggering the Safety Edge immediately cancels downward travel.

  • Activating the Light Curtain stops all motion.

  • Opening the Safety Circuit immediately disables the system.

Because the safety logic is completely independent from the motion logic, every dangerous condition is handled immediately without waiting for other program sections.

Layer 2 – Position Detection

Instead of creating complicated position memories, we use the floor limit switches directly.

For example:

  • Floor 1 Sensor

  • Floor 2 Sensor

These sensors determine the current position of the lift.

The logic remains simple and avoids unnecessary internal memory bits.

Layer 3 – System Status

Several status variables are generated from the basic operating conditions.

Examples include:

  • Running

  • Moving Up

  • Moving Down

  • Idle

  • Ready

These variables make the remainder of the program much easier to read.

For example, instead of repeatedly checking multiple conditions throughout the program, we simply determine whether the lift is currently running.

This also provides convenient status information for future HMI displays.

Layer 4 – Request Logic

Motion requests are handled using a SET/RST architecture.

When an operator presses the floor button:

  • Safety conditions are verified.

  • Current floor is checked.

  • Running status is checked.

  • A travel request is stored.

The request remains active until one of the reset conditions occurs.

For downward travel, examples include:

  • Safety interruption

  • Arrival leveling timer completed

For upward travel:

  • Upper limit activated

  • Arrival timer completed

This architecture is considerably easier to extend than traditional self-holding logic.

Future features such as:

  • Fire Emergency Mode

  • Inspection Mode

  • Automatic Return to Base Floor

  • Remote HMI Commands

can all be added by simply introducing additional SET or RESET conditions without rewriting the entire control program.

Layer 5 – Output Control

Motor and valve outputs are controlled separately from the request logic.

The program includes an additional hardware interlock:

  • The hydraulic pump cannot run while the lowering valve is energized.

  • The lowering valve cannot energize while the pump command is active.

Although the request logic already prevents conflicting commands, this extra layer acts as a second level of software protection.

This defensive programming approach improves overall reliability.

Layer 6 – Automatic Floor Leveling

Hydraulic systems naturally experience small stopping variations due to oil flow and inertia.

Instead of stopping immediately when the floor sensor is reached, we use a leveling timer.

For example:

  • Downward leveling delay: 1.5 seconds

  • Upward leveling delay: 3 seconds

This allows the platform to align more accurately with the landing floor while keeping the control logic simple.

The timer values can be adjusted easily during commissioning to match different lift sizes and hydraulic systems. If you are interested in how these principles apply to heavier-duty applications, see our article on the Custom 1.5 Ton Hydraulic Scissor Lift Platform.

Layer 7 – Alarm Status

Rather than mixing alarms into the motion logic, each alarm is generated independently.

Typical alarm signals include:

  • Emergency Stop Activated

  • Safety Edge Activated

  • Light Curtain Triggered

  • Safety Circuit Open

  • Upper Limit Triggered

These status bits can be displayed directly on an HMI or transmitted through Modbus to simplify diagnostics.

Designed for Future Expansion

Although this program currently controls only a two-floor hydraulic goods lift, the software architecture was designed with future upgrades in mind.

Possible future additions include:

  • Three-floor and four-floor systems

  • Automatic parking floor

  • Firefighter operation

  • Maintenance mode

  • Password-protected engineer functions

  • PLC status monitoring screen

  • Remote troubleshooting through HMI

Because each function is isolated into its own logical layer, new features can be added without affecting the existing control structure. For a real-world example of a high-capacity hydraulic platform in action, read our case study on the Heavy Duty 5 Ton Hydraulic Scissor Lift Platform.

Final Thoughts

Good PLC programming is not about writing the most complicated logic—it is about creating software that remains reliable years after installation.

By separating safety, positioning, request handling, output control, timers, and alarms into independent functional layers, we have created a PLC architecture that is straightforward to understand, simple to maintain, and ready for future expansion.

For hydraulic goods lifts, simplicity is often the greatest strength. A clean and well-structured control program not only reduces commissioning time but also makes future troubleshooting significantly easier for service engineers and customers alike.

Below is the whole code:

(*====================================================*)
(* SAFETY LAYER                                       *)
(*====================================================*)

(* Main Safety *)
SystemAllow := X012 AND NOT X000 AND NOT X010;

(* Downward Safety *)
DownAllow := SystemAllow AND NOT X011;

(* Upward Safety *)
UpAllow := SystemAllow AND X013;

(*====================================================*)
(* POSITION                                           *)
(*====================================================*)

AtFloor1 := X001;
AtFloor2 := X002;


(*====================================================*)
(* STATUS                                         *)
(*====================================================*)

Running := M3 OR M4;
MovingUp := M4;
MovingDown := M3;
Idle := NOT Running;
Ready := SystemAllow AND Idle;


(*====================================================*)
(* REQUEST                                  *)
(*====================================================*)

BtnDownPressed := RisingEdge(X003); 
BtnUpPressed := RisingEdge(X004);

(* Down Request *)

IF BtnDownPressed AND DownAllow AND NOT AtFloor1 AND NOT Running THEN
    M3 := TRUE;
END_IF;


IF NOT DownAllow OR DownLevelTimer.Q THEN
    M3 := FALSE;
END_IF;

(* Up Request *)

IF BtnUpPressed AND UpAllow AND NOT AtFloor2 AND NOT Running THEN
    M4 := TRUE;
END_IF;

IF NOT UpAllow OR UpLevelTimer.Q THEN
    M4 := FALSE;
END_IF;

 

(*====================================================*)
(* OUTPUT                                             *)
(*====================================================*)

(* Down *)

IF M3 AND NOT M4 AND DownAllow
THEN
    Y001 := TRUE;
ELSE
    Y001 := FALSE;
END_IF;


(* Up *)

IF M4 AND NOT M3 AND UpAllow
THEN
    Y000 := TRUE;
ELSE
    Y000 := FALSE;
END_IF;

(*====================================================*)
(* TIMER                                     *)
(*====================================================*)

(* Down *)

DownLevelTimer(IN := M3 AND AtFloor1, PT := T#1500ms);

(* Up *)

UpLevelTimer(IN := M4 AND AtFloor2, PT := T#3000ms);

(*====================================================*)
(* ALARM                                              *)
(*====================================================*)

EmergencyStop := X000;

SafetyEdgeAlarm := X011;

LightCurtainAlarm := X010;

SafetyCircuitAlarm := NOT X012;

UpperLimitAlarm := NOT X013;

0 comments

Leave a comment

Please note, comments need to be approved before they are published.