Tutorial: Building a pH Control Flow

This tutorial walks you through a real-world automation flow that maintains pH levels in a nutrient reservoir. You’ll learn how blocks work together to read sensors, make decisions, dose chemicals, and loop until the target is reached.


What This Flow Does

The flow automatically adjusts pH by:

  1. Reading the current pH level
  2. Comparing it to the target
  3. If pH is too low → dosing pH UP solution in a loop
  4. If pH is too high → dosing pH DOWN solution in a loop
  5. If pH is already at target → finishing immediately

Variables

Before placing any blocks, define the variables the flow will use. Open the Variable Manager from the toolbar.

Local Variable (temporary)

IDNameUnitPurpose
var_1pH NowpHStores the current sensor reading. Overwritten each time the sensor is read.

Global Variables (configurable by Programs)

IDNameUnitDefaultTolerancePurpose
global_5pH NeedpH6.2± 0.2The target pH setpoint. A Program can override this per schedule.
global_2pH Dosecount1—How many doses to dispense per loop cycle.
global_4PumpMixTimesec85—How long the mixing pump runs after each dose to distribute the solution.

Why Global? Because a Program might need different pH targets for day/night, or different dose amounts for different growth stages. Global variables make the flow reusable without editing it.


Step-by-Step Build

Step 1: Read the Current pH

Block: Sensor Read → name it “Sensor pH 01”

SettingValue
DevicepH SIM (your pH sensor)
Reading Modeph:multi_point
Target VariablepH Now (var_1)

What happens: The sensor reads the current pH and stores it in pH Now.


Step 2: Is pH Already at Target?

Block: IF (Condition) → name it “Check pH = Target”

SettingValue
VariablepH Now
Operator== (equal)
Value{{pH Need}} (global_5)

Connections:

  • TRUE → End block (pH is perfect, nothing to do)
  • FALSE → next IF block (need to determine direction)

What happens: If the current pH equals the target (within tolerance), the flow ends. Otherwise, we need to figure out which direction to adjust.


Step 3: Which Direction to Adjust?

Block: IF (Condition) → name it “Check pH < Target”

SettingValue
VariablepH Now
Operator< (less than)
Value{{pH Need}} (global_5)

Connections:

  • TRUE → pH is too low → go to the pH UP loop (Step 4a)
  • FALSE → pH is too high → go to the pH DOWN loop (Step 4b)

Step 4a: pH UP Loop (pH is too low)

Block: Loop → name it “Loop pH+“

SettingValue
ModeCOUNT
Iterations5 (maximum attempts)
Interval2 sec
Stop ConditionpH Now < {{pH Need}} (keep looping while pH is below target)

Connections:

  • LOOP (body, purple) → Dose pH UP (Step 5a)
  • DONE (exit, green) → End block

Step 5a: Dose pH UP

Block: Actuator Set → name it “Pump pH+“

SettingValue
DevicePump pH+ SIM
ActionDOSE
Amount{{pH Dose}} (global_2) — 1 dose
Revert on Stop✅ Enabled

Step 6a: Mix the Solution

Block: Actuator Set → name it “Pump Mix pH+“

SettingValue
DevicePump Mix SIM
ActionPULSE_ON
Duration{{PumpMixTime}} (global_4) — 85 seconds
Revert on Stop✅ Enabled

Step 7a: Re-read pH

Block: Sensor Read → name it “Sensor pH+“

SettingValue
DevicepH SIM (same sensor)
Target VariablepH Now (var_1) — overwrites the previous reading

Step 8a: Close the Loop

Block: Flow Control → LOOP_BACK → targets “Loop pH+“


Step 4b: pH DOWN Loop (pH is too high)

This is a mirror of the pH UP path, with these differences:

BlockNameDifference
Loop”Loop pH-”Stop condition: pH Now > {{pH Need}}
Actuator”Pump pH-”Uses the pH DOWN pump device
Actuator”Pump Mix pH-”Same mixing pump, same duration
Sensor”Sensor pH-”Same sensor, writes to same pH Now variable
Flow ControlLOOP_BACKTargets “Loop pH-”

Complete Flow Diagram

START
  ↓
[Sensor pH 01] → pH Now = current reading
  ↓
IF: pH Now == pH Need?
  ├── TRUE → END (pH is perfect)
  └── FALSE ↓
      IF: pH Now < pH Need?
        ├── TRUE (pH too low) → LOOP pH+ (5x) → Dose → Mix → Re-read → LOOP BACK
        └── FALSE (pH too high) → LOOP pH- (5x) → Dose → Mix → Re-read → LOOP BACK

Key Design Patterns in This Flow

1. Read → Decide → Act → Re-read → Loop

This is the fundamental automation pattern. Every correction cycle ends with a fresh sensor reading so the loop condition uses up-to-date data.

2. Two-Direction Branching

A single IF block determines the correction direction. This avoids running the wrong pump.

3. Mix Before Re-read

The mixing pump runs for 85 seconds between dosing and re-reading. Without this, the sensor would read the old (unmixed) water and overdose.

4. Safety Limits

  • Max 5 iterations per loop prevents infinite dosing if the sensor is faulty
  • Revert on Stop ensures pumps turn off if the flow is stopped mid-operation

5. Global Variables for Reusability

By using globals for the target pH, dose amount, and mix time, you can run the same flow with different parameters at different times of day.


Testing This Flow

  1. Click ▶ Run in the editor toolbar
  2. In the Setup Dialog, set values for global variables
  3. Click Load Debugger
  4. Click ▶ Run Flow to start
  5. Watch in the console: sensor reads → IF decides direction → loop runs → flow exits

Common Modifications

Want to…Change
Adjust fasterReduce PumpMixTime or increase pH Dose
Adjust saferReduce pH Dose and increase loop Iterations
Add toleranceSet pH Need tolerance to ± 0.3
Add notificationsEnable notifications on the Loop block
Log progressAdd a Log block after each sensor re-read