Documentation

ZJ-S201 Water Flow Sensor G1/2" (1-30L/min) for Arduino, Raspberry Pi & ESP32 | ShillehTek Product Manual
Documentation / ZJ-S201 Water Flow Sensor G1/2" (1-30L/min) for Arduino, Raspberry Pi & ESP32 | ShillehTek Product Manual

ZJ-S201 Water Flow Sensor G1/2" (1-30L/min) for Arduino, Raspberry Pi & ESP32 | ShillehTek Product Manual

shillehtekwater-flow-sensor-g1-2-1-30l-min

Overview

The ZJ-S201 measures water flow the mechanical-meets-magnetic way: water spins a turbine inside the G1/2" body, a magnet on the rotor sweeps past a Hall sensor, and out comes a clean square-wave pulse train whose frequency is proportional to flow rate. Count pulses and you know liters per minute; accumulate them and you know total liters. No analog calibration, no drifting op-amps — just edges to count.

The conversion is the classic S201-family formula: frequency (Hz) ≈ 7.5 x flow (L/min), or about 450 pulses per liter. Across its 1-30 L/min working range the sensor holds roughly ±10% out of the box, and a one-jug calibration (run a known volume through, count pulses, compute your own pulses-per-liter) tightens it to a few percent — plenty for irrigation controllers, shower/usage monitors, pump protection (dry-run detection), coffee machines, and hydroponics dosing.

It wires like the simplest sensors: red Vcc (5-18V), black GND, yellow signal. The output is an open-collector-style pulse that every platform reads with an interrupt pin plus internal pull-up. Thread it inline with standard G1/2 fittings, note the flow-direction arrow on the body, and put it on the cold line — the plastic body and ≤ 1.75 MPa rating are made for household water, not boilers.

At a Glance

Flow Range
1 - 30 L/min
Output
Hall pulse train
Conversion
Hz ≈ 7.5 x L/min
Threads
G1/2" male, inline
Supply Voltage
5 - 18V DC
Max Pressure
≤ 1.75 MPa

Specifications

Parameter Value
Model ZJ-S201 (YF-S201 class) turbine flow sensor
Sensing Turbine rotor + magnet + Hall-effect switch
Working Range 1 - 30 L/min
Pulse Characteristic F = 7.5 x Q(L/min) ±10%; ~450 pulses per liter
Supply Voltage 5 - 18V DC (5V typical with MCUs)
Current Draw ~15 mA at 5V
Output Square wave, ~50% duty; needs pull-up on the signal line
Water Pressure ≤ 1.75 MPa
Water Temperature ≤ 80°C (cold-line use recommended)
Connections Red = Vcc, Black = GND, Yellow = pulse signal
Fitting G1/2" male threads both ends, arrow marks flow direction

Pinout Diagram

Three flying leads: red to 5V, black to GND, yellow to an interrupt-capable GPIO with the internal pull-up enabled. Mount with the arrow pointing along the flow; horizontal runs with the sensor upright give the most linear low-flow response.

ZJ-S201 water flow sensor wiring diagram showing yellow pulse signal, black GND and red Vcc wires

Wiring Guide

Arduino Wiring

Wire Arduino Pin Details
Red (Vcc) 5V
Black (GND) GND
Yellow (Signal) D2 Interrupt pin, INPUT_PULLUP
Tip: Uno/Nano interrupts live on D2 and D3 — use one of those. The code enables the internal pull-up, so no external resistor is needed.

ESP32 Wiring

Powered at 5V the yellow line can pull toward 5V through its pull-up — use the MCU-side pull-up only and it stays at 3.3V, or add a small divider for belt-and-braces.

Wire ESP32 Pin Details
Red VIN (5V)
Black GND
Yellow GPIO 27 Pin.PULL_UP in code (open-collector output)

Raspberry Pi Wiring

Wire Pi Pin Details
Red Pin 2 (5V)
Black Pin 6 (GND)
Yellow Pin 11 (GPIO 17) Internal pull-up in code keeps it at 3.3V

Raspberry Pi Pico Wiring

Wire Pico Pin Details
Red VBUS (pin 40, 5V)
Black GND (pin 38)
Yellow GP15 Pin.PULL_UP + IRQ on falling edge

Code Examples

Each example counts pulses in interrupts, converts to L/min once per second with the 7.5 factor, and integrates total liters — the complete pattern for any flow project. Replace 7.5 with your own calibrated factor for best accuracy.

Arduino

flow_arduino.ino
// ZJ-S201 Water Flow Sensor - Arduino Example
// Yellow->D2, Red->5V, Black->GND

const byte flowPin = 2;
const float PULSES_PER_LMIN = 7.5;    // F(Hz) = 7.5 x Q(L/min)

volatile unsigned long pulses = 0;
float totalLiters = 0;

void onPulse() { pulses++; }

void setup() {
  Serial.begin(115200);
  pinMode(flowPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(flowPin), onPulse, FALLING);
  Serial.println("Flow meter ready - open the tap!");
}

void loop() {
  noInterrupts();
  unsigned long count = pulses;
  pulses = 0;
  interrupts();

  float lmin = count / PULSES_PER_LMIN;      // pulses in 1 s = Hz
  totalLiters += lmin / 60.0;

  Serial.print("Flow: ");
  Serial.print(lmin, 2);
  Serial.print(" L/min | Total: ");
  Serial.print(totalLiters, 3);
  Serial.println(" L");
  delay(1000);
}

ESP32 (MicroPython)

flow_esp32.py
# ZJ-S201 Water Flow Sensor - ESP32 MicroPython Example
# Yellow->GPIO 27, Red->VIN(5V), Black->GND

from machine import Pin
import time

pulses = 0
def on_pulse(pin):
    global pulses
    pulses += 1

flow = Pin(27, Pin.IN, Pin.PULL_UP)
flow.irq(trigger=Pin.IRQ_FALLING, handler=on_pulse)

PULSES_PER_LMIN = 7.5
total_liters = 0.0

print("Flow meter ready - open the tap!")
while True:
    pulses = 0
    time.sleep(1)
    hz = pulses
    lmin = hz / PULSES_PER_LMIN
    total_liters += lmin / 60
    print("Flow: {:.2f} L/min | Total: {:.3f} L".format(lmin, total_liters))

Raspberry Pi (Python)

flow_rpi.py
#!/usr/bin/env python3
# ZJ-S201 Water Flow Sensor - Raspberry Pi Example
# Yellow->GPIO17, Red->5V, Black->GND

import RPi.GPIO as GPIO
import time

FLOW_PIN = 17
PULSES_PER_LMIN = 7.5

pulses = 0
def on_pulse(channel):
    global pulses
    pulses += 1

GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(FLOW_PIN, GPIO.FALLING, callback=on_pulse)

total_liters = 0.0
print("Flow meter ready - open the tap!")
try:
    while True:
        pulses = 0
        time.sleep(1)
        lmin = pulses / PULSES_PER_LMIN
        total_liters += lmin / 60
        print(f"Flow: {lmin:.2f} L/min | Total: {total_liters:.3f} L")
except KeyboardInterrupt:
    GPIO.cleanup()
    print("Stopped by user")

Raspberry Pi Pico (MicroPython)

flow_pico.py
# ZJ-S201 Water Flow Sensor - Pico MicroPython Example
# Yellow->GP15, Red->VBUS(5V), Black->GND
# Includes a simple leak alarm: flow when there shouldn't be any.

from machine import Pin
import time

pulses = 0
def on_pulse(pin):
    global pulses
    pulses += 1

flow = Pin(15, Pin.IN, Pin.PULL_UP)
flow.irq(trigger=Pin.IRQ_FALLING, handler=on_pulse)
led = Pin("LED", Pin.OUT)

PULSES_PER_LMIN = 7.5
total_liters = 0.0

print("Flow meter ready - open the tap!")
while True:
    pulses = 0
    time.sleep(1)
    lmin = pulses / PULSES_PER_LMIN
    total_liters += lmin / 60

    led.value(1 if lmin > 0.2 else 0)   # LED on while water flows
    print("Flow: {:.2f} L/min | Total: {:.3f} L".format(lmin, total_liters))

Frequently Asked Questions

No pulses at all, even with water clearly flowing.
Check the pull-up first — the Hall output only pulls low, so without INPUT_PULLUP (or an external 10k to Vcc-of-logic) the pin floats and nothing registers. Then check flow direction against the arrow, and confirm flow is above ~1 L/min — a barely-open tap may not spin the turbine. Finally verify red really has 5V+; at 3.3V supply many units won't switch reliably.
How accurate is the 7.5 factor, and how do I calibrate?
Out of the box expect ±10% — the factor varies with mounting, pressure, and unit tolerance. Calibrate once: run exactly 10 L (measured jug/bucket) through at a normal rate while counting total pulses, then pulses_per_liter = count / 10 and use flow = Hz x 60 / pulses_per_liter. That single step typically lands you within 2-3%.
Why does it under-read at a trickle?
Below ~1 L/min the turbine barely turns — friction and magnet cogging make the response non-linear, and below the threshold it stops entirely while water still seeps past. This is inherent to turbine meters. If dripping-level detection matters (leak monitoring), pair it with logic that treats ANY pulses during quiet hours as an alarm rather than trying to quantify them.
Can I use it on hot water or with drinking water?
The body tolerates up to ~80°C, but plastic threads and seals age fast on hot lines — cold-line use is the design intent. As for potable use: it's standard hobby-grade nylon/POM, fine for irrigation, aquariums, and monitoring, but it carries no food-safety certification — don't make it the wetted meter for water you drink if certification matters.
Does mounting orientation matter?
Best: horizontal pipe, sensor body upright (cable up). Vertical runs work but shift the low-flow threshold and the calibration factor slightly — just calibrate in the installed orientation. Keep a few pipe-diameters of straight run before the inlet if you can; elbows immediately upstream make the spin turbulent and noisy.
Can two sensors run on one board (hot + cold, or in/out)?
Easily — each needs its own interrupt-capable pin and its own counter variable. Uno gives you two interrupt pins (D2/D3); ESP32, Pi, and Pico attach interrupts to nearly any pin, so multi-point monitoring (detect leaks by comparing in vs out) is a natural extension of the sample code.
Will it survive pressure spikes and hammering?
Rated 1.75 MPa (~250 psi) static, which covers household mains with margin. Water hammer from fast solenoid valves is the real killer of any inline plastic component — if your project slams valves shut, add a hammer arrestor or slow-closing valve. And thread with PTFE tape onto plastic-friendly fittings; overtightening metal fittings cracks plastic bodies.

Related Tutorials