PLC

PLC software

Process-control software for industrial and craft plants — including brewery automation on ~500 L vessels. I design and test OpenPLC programs (Structured Text / ladder) with a Python companion over Modbus for operator UI and setpoints — the same quality habits as Magento work: clear structure, testable logic, and respect for living processes.

The craft-brewery problem

Many small craft setups cool and heat each vessel in isolation. That works in warm months, but becomes a real bottleneck for ale finishing in autumn, winter and early spring: tanks need reliable cooling (and sometimes heating) while ambient temperatures fight the process. Without shared utility loops, you either oversize the cold plant, wait longer for final fermentation / conditioning, or accept uneven batches.

The design goal was different: small shared cold and hot reservoirs plus shared cool and heat lines feeding multiple process vessels — uncommon on tiny craft floors, but essential if you want faster, controlled finishing without a giant cold tank.

What we built

A supervisory OpenPLC layer that owns plant safety and arbitration, with a Python sidecar for day-to-day operator interaction (thermostat targets, status, acknowledge). Bench-validated against a Linux OpenPLC runtime before field-controller deployment.

  • Level supervision on reservoirs and vessels — low / high sensors with fail-safe assumptions
  • Alarm latching, reset / acknowledge, optional bypasses, lamp and buzzer indication
  • Cooling permissives per vessel: request, mode/profile, and shared cold-reservoir health
  • Priority arbitration so higher-priority vessels get cold first; equals may cool together when eligible
  • Shared cold-pump demand derived from permitted coolers (one plant pump, not one per tank)
  • Hot-side supervision and heating request gating with mutual hot/cold interlocks per vessel
  • Thermostat mailbox from the Python UI into PLC-owned control — operators set targets; the PLC decides if cooling is allowed

Minimising cold-tank load

A small cold reservoir is only useful if the PLC refuses wasteful cooling. We treat the cold tank as a limited resource:

  • Priorities — finishing or critical vessels outrank others; lower priority waits instead of draining the shared cold loop
  • Reservoir thresholds + deadband — if the cold tank is too warm, cooling is inhibited until it recovers past a hysteresis band (no chatter near the limit)
  • Mode / profile aware setpoints — fermentor vs conditioning profiles pick the right cold threshold so the plant does not cool “just because a valve is open”
  • Alarm levels — low / high cutoffs protect pumps and vessels; latched alarms force a conscious acknowledge before the plant resumes
  • Arbitration — one shared cold pump demand from the OR of permitted coolers, with hardware timer-relay anti-short-cycle on the pump command

Result: the cold tank stays smaller, cool lines stay busy when it matters, and ale finishing in the cold season is no longer hostage to “wait for ambient” or an oversized chiller.

Challenges we worked through

  • Fitting supervisory I/O and logic on a constrained controller budget (priority as one choice per vessel, not a forest of hardwired bits)
  • Keeping PLC authority for safety while giving operators a clear Python UI for setpoints and status
  • Simulator-first development with a clean path to field upload — same program, different runtime surface
  • Separating source config (priority / mode codes) from the resolved downstream contract the plant actually runs on
  • Hot and cold mutual exclusion at vessel level so a fault cannot recirculate both loops at once

← All services · About — brewery