ladder logic

sequencer

hands-on project

PLC Bottle Filling Machine: Step-by-Step Project

‌
PLC bottle filling machine project diagram showing conveyor, fill valve, sensors and PLC rack in flat vector style

A bottle filling machine is the perfect first real project for a PLC student or a technician moving beyond simple start/stop logic. It has everything: a conveyor, sensors, a timed fill cycle, a valve, a counter, and enough edge cases to actually teach you something. This post walks through the whole thing, from writing the I/O list to a runnable ladder sequence you can load into Studio 5000 or adapt to any other platform.

How the Machine Works

The setup is intentionally simple so you can replicate it on a training rig or even simulate it in software. A conveyor carries empty bottles single-file under a fill nozzle. A proximity sensor detects when a bottle is in position. The conveyor stops, a solenoid fill valve opens for a timed period, the valve closes, and the conveyor restarts. A separate sensor downstream counts filled bottles and stops the run when a batch target is reached.

That is it at the functional level. But the devil is in the details: what happens if the bottle sensor never triggers? What if the fill valve does not close? What if the operator hits stop mid-fill? These are the questions that turn a textbook exercise into real engineering.

I/O List for the Bottle Filling Machine Project

Define your I/O before you write a single rung. Here is a practical list for this project. Adjust addresses to match your actual hardware.

Tag NameTypeAddress (Logix)Description
PB_StartDILocal:0:I.Data.0Momentary start pushbutton, N.O.
PB_StopDILocal:0:I.Data.1Momentary stop pushbutton, N.C. wired
Prox_BottleInPosDILocal:0:I.Data.2PNP prox sensor: bottle under nozzle
Prox_BottleFilledDILocal:0:I.Data.3PNP prox sensor: bottle past nozzle (count)
FillValve_OpenDOLocal:1:O.Data.0Solenoid fill valve, energise to open
Conveyor_RunDOLocal:1:O.Data.1Conveyor motor contactor or VFD run command
PL_RunningDOLocal:1:O.Data.2Panel pilot light: system running
PL_BatchDoneDOLocal:1:O.Data.3Panel pilot light: batch complete
HMI_BatchTargetINTN7:0 / DINT tagOperator-set number of bottles per batch
HMI_FillTime_msINTN7:1 / DINT tagFill duration in milliseconds (HMI entry)
Bottle filling machine I/O list. Addresses shown for ControlLogix; remap as needed for your platform.
Wire the stop button N.C. at the field device and use XIC in the PLC. That way a broken wire stops the machine. It is the safer default and the IEC 60204-1 recommendation.

Sequence Design: States, Not Rungs

Most beginners try to write this as one giant blob of ladder rungs and then wonder why bottles are getting double-filled or the conveyor starts before the valve closes. The fix is to think in states first. Draw it out on paper before you open the software.

  1. IDLE: System powered, waiting for start. Conveyor off, valve closed.
  2. RUNNING: Conveyor on, transporting bottle toward fill position.
  3. FILLING: Conveyor stopped, fill valve open, fill timer counting.
  4. FILL_DONE: Fill valve closed, short settle delay (100 to 200 ms), then back to RUNNING.
  5. BATCH_COMPLETE: Bottle count reached target. Conveyor stops, PL_BatchDone on. Wait for operator reset.

In Studio 5000 you can implement this with a DINT tag called FillerState and use values 0 through 4. Each state block is a set of rungs gated by an EQU instruction comparing FillerState to the state number. It is not fancy SFC, but it is explicit and easy to debug on a laptop at the machine.

PLC Bottle Filling Machine: Core Ladder Logic

The rung below handles the transition from RUNNING into FILLING and back again. This is the heart of the fill sequence: the bottle-in-position sensor stops the conveyor and starts the fill timer. When the timer completes, the valve closes and the state advances. This is the rung new engineers always get wrong, usually because they forget to interlock the conveyor output with the fill state.

Bottle Filling: Conveyor Stop, Fill Timer, and State Advance (Studio 5000). Ladder logic (4 rungs): Rung 0: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is off (XIO), then energize output Conveyor_Run (OTE). Rung 1: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then TON on Fill_Timer. Rung 2: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then examine if Fill_Timer.DN is off (XIO), then energize output FillValve_Open (OTE). Rung 3: examine if Sys_Running is on (XIC), then examine if Fill_Timer.DN is on (XIC), then examine if Fill_DN_OneShot is on (XIC), then either CTU on Bottle_Count. Rung 1: Conveyor runs only when the system is active and no bottle is in position. Rung 2: TON fill timer starts when a bottle is detected. Rung 3: Fill valve energises while timer is running (not done). Rung 4: On the rising edge of timer done, increment the bottle counter. Sys_Running is a BOOL set by your start/stop seal-in logic. Replace HMI_FillTime_ms with a fixed preset (e.g. 2000 for 2 seconds) if you are not using an HMI.

Bottle Filling: Conveyor Stop, Fill Timer, and State Advance (Studio 5000)Ladder logic
Toggle inputs
Rung 0
Ladder logic rung: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is off (XIO), then energize output Conveyor_Run (OTE) examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is off (XIO), then energize output Conveyor_Run (OTE) XIC Sys_Running Sys_Running Sys_Running XIO Prox_BottleInPos Prox_BottleInPos Prox_BottleInPos OTE Conveyor_Run Conveyor_Run Conveyor_Run
Rung 1
Ladder logic rung: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then TON on Fill_Timer examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then TON on Fill_Timer XIC Sys_Running Sys_Running Sys_Running XIC Prox_BottleInPos Prox_BottleInPos Prox_BottleInPos TON Fill_Timer HMI_FillTime_ms 0 TONTimerFill_TimerFill_TimerPresetHMI_FillTime_msHMI_FillTime_msAccum00
Rung 2
Ladder logic rung: examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then examine if Fill_Timer.DN is off (XIO), then energize output FillValve_Open (OTE) examine if Sys_Running is on (XIC), then examine if Prox_BottleInPos is on (XIC), then examine if Fill_Timer.DN is off (XIO), then energize output FillValve_Open (OTE) XIC Sys_Running Sys_Running Sys_Running XIC Prox_BottleInPos Prox_BottleInPos Prox_BottleInPos XIO Fill_Timer.DN Fill_Timer.DN Fill_Timer.DN OTE FillValve_Open FillValve_Open FillValve_Open
Rung 3
Ladder logic rung: examine if Sys_Running is on (XIC), then examine if Fill_Timer.DN is on (XIC), then examine if Fill_DN_OneShot is on (XIC), then either CTU on Bottle_Count examine if Sys_Running is on (XIC), then examine if Fill_Timer.DN is on (XIC), then examine if Fill_DN_OneShot is on (XIC), then either CTU on Bottle_Count XIC Sys_Running Sys_Running Sys_Running XIC Fill_Timer.DN Fill_Timer.DN Fill_Timer.DN OSR Fill_DN_OneShot Fill_DN_OneShot Fill_DN_OneShot OSR CTU Bottle_Count HMI_BatchTarget 0 CTUCounterBottle_CountBottle_CountPresetHMI_BatchTargetHMI_BatchTargetAccum00
energizedTip: click a contact in the diagram to flip its bit.
Rung 1: Conveyor runs only when the system is active and no bottle is in position. Rung 2: TON fill timer starts when a bottle is detected. Rung 3: Fill valve energises while timer is running (not done). Rung 4: On the rising edge of timer done, increment the bottle counter. Sys_Running is a BOOL set by your start/stop seal-in logic. Replace HMI_FillTime_ms with a fixed preset (e.g. 2000 for 2 seconds) if you are not using an HMI.
Notice that FillValve_Open is driven by XIO(Fill_Timer.DN), not by XIC(Fill_Timer.TT). Both work while the timer is timing, but using .DN as the interlock means the valve stays closed if the timer preset is zero or if the tag gets corrupted to a done state. It is a small thing, but these are the gotchas that cause rejects on the line.

Batch Counter and Auto-Stop Logic

The CTU counter in the rung above accumulates every fill cycle. When Bottle_Count.ACC reaches Bottle_Count.PRE (which you load from HMI_BatchTarget), the counter's DN bit goes true. Wire that into a rung that clears Sys_Running and lights PL_BatchDone. Then add a separate operator reset rung: XIC(PB_Start) and XIC(Batch_Done) can both RES the counter and OTL the Sys_Running bit.

One thing to decide early: do you want the machine to stop immediately when the batch count hits, or finish the current fill cycle first? Finishing the current cycle is almost always right. So gate the batch stop on XIC(Bottle_Count.DN) combined with XIO(FillValve_Open): only stop the conveyor after the valve has closed.

Fill-by-Time vs Fill-by-Level: Which to Use

The project above uses fill-by-time: the valve opens for a fixed number of milliseconds. It is easy to implement and works fine for low-viscosity liquids like water when supply pressure is stable. For anything where pressure varies (gravity-fed tanks that drain down, for example) or for viscous products, you need fill-by-weight or fill-by-level using an analog sensor.

If you want to extend this project to use a 4-20 mA level sensor inside the bottle (or a load cell), you will need to scale the raw analog count to engineering units. The analog scaling calculator on this site does that math for you, and the post on 4-20 mA scaling formula for PLCs covers the formula you will drop into your structured text.

Fault Handling You Should Not Skip

Every real machine needs at least these three faults wired up, even on a training rig:

  • Bottle jam timeout: If Prox_BottleInPos stays true for more than 2x the fill time (say 10 seconds), the bottle has not cleared after filling. Stop the conveyor, set a fault bit, and flash a light. A TON with a long preset handles this.
  • Fill valve stuck open: If FillValve_Open is commanded off but a flow sensor (if fitted) still sees flow, latch a fault. Even without a flow sensor, add a sanity check: if the fill timer is not running but the valve output is on, that is a wiring or output card fault.
  • No bottle detected timeout: If the system is in RUNNING state and no bottle arrives within a configurable window (say 30 seconds), pause and alert the operator. Empty conveyor or upstream jam.
On a real production machine you would also add an E-stop loop and a safety relay. For the project level, wire a physical E-stop N.C. in series with your 24 VDC control supply so it kills all outputs on hardware, independent of the PLC. Do not rely on the PLC program alone to stop the machine in an emergency.

Suggested Build Stages for Learning

If you are using this as a training project, build it in stages. Each stage gives you a working, testable machine before you add complexity.

  1. Stage 1: Manual mode only. Individual pushbuttons jog the conveyor and open the valve. Verify wiring and sensor polarity before any auto logic runs.
  2. Stage 2: Add start/stop with a seal-in rung and conveyor run output. Test the conveyor runs continuously and stops cleanly.
  3. Stage 3: Add the bottle-in-position sensor and fill timer. Test a single fill cycle manually by placing a target in front of the sensor.
  4. Stage 4: Add the CTU batch counter and batch-done stop. Set target to 3 and run 3 fill cycles.
  5. Stage 5: Add fault timers for jam and no-bottle conditions. Deliberately block the sensor and confirm the fault triggers.
  6. Stage 6: Add HMI screen (if available) with fill time entry, batch target entry, bottle count display, and fault annunciation.

Sensor Placement Tips

The bottle-in-position sensor is the most critical one. Use an inductive or capacitive prox sensor depending on bottle material: inductive for metal caps or metal bottles, capacitive for plastic or glass. Mount it so the bottle centre aligns with the nozzle when the sensor fires. A misaligned sensor is the number one cause of spills on first commissioning. Give yourself 5 to 10 mm of adjustment in the mount.

For the filled-bottle counter downstream, a diffuse reflective photoelectric sensor works well. Keep it at least 150 mm past the fill station so a bottle that is still settling does not get counted twice. If bottles are clear or translucent, use a retro-reflective type with a polarising filter, or you will get false triggers from the liquid surface.

Bottle filling machine PLC sequence diagram showing detect, fill timer, and count stages in flat vector style
Three-stage sequence: detect bottle, open valve with timer, count filled bottle downstream.

Quick Reference: Timer Presets for Common Fill Volumes

These numbers assume a 1/2 inch (DN15) solenoid valve at 2 bar supply pressure and water as the product. Use them as a starting point and calibrate on your actual rig.

Bottle VolumeApprox Fill TimeNotes
250 mL1.5 to 2.0 sSmall PET bottle, water
500 mL3.0 to 3.5 sStandard water bottle
1000 mL6.0 to 7.0 s1 L bottle, may need larger valve
1500 mL9.0 to 10.0 sConsider DN20 valve at this volume
Approximate fill times for water at 2 bar through a DN15 solenoid valve. Always measure and calibrate on your system.

Where to Take It Next

Once the basic fill cycle is solid, there are several natural extensions that each teach a new skill. Add a capping station: a second pneumatic cylinder that presses a cap after the bottle exits the fill zone. That brings in cylinder sequencing, and the post on pneumatic cylinder sizing will help you pick the right bore for the capping force you need. Or wire the conveyor motor through a VFD and control speed from the PLC: slow the belt when a bottle is approaching the sensor, speed it up between bottles. That gets you into analog output and drive integration without a complex motion application.

Another good extension is replacing the fixed fill timer with a recipe system: store fill time, batch size and settle delay as a recipe DINT array indexed by product number. The operator picks a product on the HMI and the PLC loads the right values. That is exactly how real machines work, and it forces you to learn indirect addressing, which is one of the most useful skills you can build.