Learn

An Arduino water meter with a YF-S201 flow sensor

Beginner

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: YF-S201 water meterlive0.000 s 0.00x
Click to open it in the editor
A YF-S201 flow sensor counted on an interrupt, with an I2C LCD, on a simulated ATmega328P. Drag the flow slider.

The YF-S201 is the black plastic flow sensor with a half-inch thread at each end and three wires. Inside is a little paddle wheel with a magnet, and a Hall sensor that pulses every time the magnet goes past. The faster the water flows, the faster the pulses come. Count them and you have a water meter.

The circuit above is an Uno with a YF-S201 on pin 2 and a 16x2 I2C LCD. The flow slider starts at 6 liters a minute, and the screen and serial monitor show the flow and the total so far. It runs in your browser on the sketch below.

What you need

  • An Arduino Uno
  • A YF-S201 water flow sensor
  • A 16x2 LCD with an I2C backpack (optional; the serial monitor shows the same)
  • A half-size breadboard and jumper wires

Wiring

Part and pinGoes toNote
Sensor yellow (SIG)Pin 2An interrupt pin on the Uno
Sensor red (VCC)5 VNot 12 V when SIG goes straight to the Uno
Sensor black (GND)GND
LCD SDA and SCLA4 and A5Backpack address 0x27
LCD VCC and GND5 V and GND

From pulses to liters

The seller’s listings give one formula: the pulses a second equal 7.5 times the flow in liters a minute. Work it through and 450 pulses make one liter. Every YF-S201 sketch is built on those two numbers.

At 30 liters a minute, the top of the sensor’s range, that is 225 pulses a second. A loop() with delays in it will miss some, so the sketch counts them with an interrupt instead: attachInterrupt() runs a tiny function on every falling edge of pin 2, and that function adds one to a counter.

The yellow wire comes from an open-collector output with its own pull-up resistor to the red wire, so the pulses swing between 0 V and whatever the sensor is powered from. That is why it must run from 5 V when its signal goes straight into an Uno. The sketch still sets INPUT_PULLUP, which does no harm.

The sketch, step by step

Once a second, loop() copies the counter with interrupts paused for a moment, so it never reads a number that is changing. The pulses in that second, times 4 and divided by 3, give the flow in tenths of a liter a minute. All the pulses so far, times 20 and divided by 9, give the total in milliliters. The math is in whole numbers to keep it small and fast on the Uno.

At 6 liters a minute the serial monitor prints "flow 6.0 L/min" and the total grows by 100 ml every second, which is 6 liters a minute exactly. Drag the slider to 15 and the lines move to "flow 15.0 L/min".

The pulse counter and the math, as a whole sketch
const int SENSOR = 2;  // the yellow wire

volatile unsigned long pulses = 0;
unsigned long counted = 0;     // pulses already turned into flow
unsigned long lastSecond = 0;

void onPulse() {
  pulses++;
}

void setup() {
  Serial.begin(9600);
  pinMode(SENSOR, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SENSOR), onPulse, FALLING);
}

void loop() {
  if (millis() - lastSecond < 1000) return;
  lastSecond += 1000;
  noInterrupts();
  unsigned long all = pulses;
  interrupts();
  unsigned long thisSecond = all - counted;
  counted = all;

  unsigned long tenths = thisSecond * 4 / 3;
  unsigned long ml = all * 20 / 9;
  Serial.print("flow ");
  Serial.print(tenths / 10);
  Serial.print('.');
  Serial.print(tenths % 10);
  Serial.print(" L/min, total ");
  Serial.print(ml);
  Serial.println(" ml");
}

How accurate is it?

A real YF-S201 is good to about 10 percent, and it changes with the water pressure and the way it is mounted. The wheel also stops turning below about 1 liter a minute. To calibrate yours, run water through it into a measuring jug, count the pulses for a known volume, and use your number instead of 450.

The simulated sensor’s pulses are exact, so the math here comes out perfect. That is useful for getting the code right, and it is a reason to calibrate the real one.

Try it in the editor

Add a relay that shuts a valve after 2 liters, for a plant waterer or a fill-to-the-line jug. Or add a buzzer that warns when the flow has run for more than five minutes, for a leak alarm.

Common mistakes

Counting pulses with digitalRead() in loop(). At high flow you miss pulses. Use an interrupt on pin 2 or 3.

Forgetting volatile. The counter is changed inside the interrupt, so it must be declared volatile, or the compiler may never see it change.

Powering it from 12 V with SIG wired straight to the Uno. The sensor’s pull-up goes to its own supply, so the pulses reach 12 V. Run it from 5 V.

Mounting it the wrong way. The arrow on the body shows the direction the water must flow.

Questions

How do I connect a YF-S201 to an Arduino?

Red to 5 V, black to GND and yellow to pin 2. Count the falling edges on pin 2 with attachInterrupt(), and divide by 450 for liters.

What is the YF-S201 calibration factor?

7.5: the pulses a second equal 7.5 times the flow in liters a minute, so 450 pulses make a liter. Real sensors vary, so measure yours with a jug for better than 10 percent.

Which pins can count flow pulses on an Uno?

Pins 2 and 3, the two external interrupt pins. On a Mega there are six, and on an ESP32 almost any pin can take an interrupt.

What does Mokxi not model on the flow sensor?

The real sensor’s 10 percent error, the low flow where the wheel stops, the water pressure, and a wheel that keeps spinning for a moment after the tap closes.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.