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
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.
Wiring Guide
Arduino Wiring
| Wire | Arduino Pin | Details |
|---|---|---|
| Red (Vcc) | 5V | |
| Black (GND) | GND | |
| Yellow (Signal) | D2 | Interrupt pin, INPUT_PULLUP |
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
// 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)
# 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)
#!/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)
# 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))