Process / Edge

All projects

SUDS — Soap Usage & Dispensing System

Four-tank water quality monitoring with automated dosing at a fraction of vendor cost.

$3,051 delivered$35,850 quote91% reduction
RevPiPythonIgnition Perspective

01

Problem

Electrostatic-dissipating soap in the glass washer was causing static-shock incidents on the line. Early conductivity sensing was unusable: the same supply that drove the probes also collapsed under load, so readings looked like process swings when they were really voltage drop and coupled noise.

02

Approach

I treated it as a measurement problem before a software problem. Star grounding came first. Then Atlas Scientific conductivity modules got their own isolated supply and differential wiring into a Revolution Pi, with Python normalizing tank data for an Ignition Perspective dosing view.

SUDS installation

Installed SUDS enclosure with Raspberry Pi and four conductivity displays. Select the image to inspect it at a larger size.
Installed SUDS enclosure with Raspberry Pi and four conductivity displays

03

Architecture

Four washer tanks feed isolated Atlas Scientific conductivity modules. Independent 5 V rails and differential pairs land on the RevPi; Perspective only sees cleaned engineering units and dose commands.

SUDS — Soap Usage & Dispensing System architectureSanitized block diagram of data flow for SUDS — Soap Usage & Dispensing System.4 washer tanksESD soap circuitAtlas ScientificIsolated 5 V / diff.Star groundNoise rejectionRevPi + PythonNormalize / dosePerspectiveAlarm + control

04

Implementation

The edge script never trusts a raw UART line. It rejects probe chatter, converts microsiemens to a tank state, and only then writes tags the Perspective application uses for alarming and dose control.

suds_conductivity.pySanitized RevPi reader for Atlas Scientific EZO conductivity. No plant I/O map.
# Isolated 5 V rail + differential pair into the RevPi UART
PROBE_ERROR_PREFIXES = ("*", "ERROR")

def read_conductivity(uart):
    uart.write(b"R\r")
    line = uart.readline().decode("ascii", errors="ignore").strip()
    if not line or line.startswith(PROBE_ERROR_PREFIXES):
        return None
    us_cm = float(line)
    if us_cm < 0:
        return None
    return us_cm

def tank_state(us_cm, low, high):
    if us_cm is None:
        return "fault"
    if us_cm < low:
        return "dose"
    if us_cm > high:
        return "high"
    return "ok"

05

Results

$3,051Delivered four-tank monitoring and automated dosing
$35,850Commercial vendor quote for the same class of system
91%Cost reduction versus buying the packaged solution

06

Reflection

What I’d do next

Next I would add a commissioning screen that graphs supply voltage next to conductivity so the next technician can see grounding issues in minutes, and store dose totals per tank for soap usage reporting.