YFS201 Hall Effect Water Flow Sensor giving wrong values

Hi everyone, I am using YFS201 Hall Effect Water Flow Sensor with ESP8266 to calculate the volume of the water but its not giving accurate values.

I have changed the calibration factor many times but its giving different values withe same value of calibration factor.

float calibrationFactor = 7.5;

Here is my code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

#define i2c_Address 0x3c //initialize with the I2C addr 0x3C 
 
#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)
 
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define SENSOR  14
 
long currentMillis = 0;
long previousMillis = 0;
int interval = 1000;
float calibrationFactor = 7.5;
volatile byte pulseCount;
byte pulse1Sec = 0;
float flowRate;
unsigned long flowMilliLitres;
unsigned int totalMilliLitres;
float flowLitres;
float totalLitres;
long wakeup = 0; 
void IRAM_ATTR pulseCounter()
{
  pulseCount++;
}
  
void setup()
{
  Serial.begin(115200);
  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
  //display.setContrast (0); // dim display

//  display.display();
//  delay(2000);
  display.clearDisplay();// Clear the buffer.
  delay(10);
 
  pinMode(SENSOR, INPUT_PULLUP);
 
  pulseCount = 0;
  flowRate = 0.0;
  flowMilliLitres = 0;
  totalMilliLitres = 0;
  previousMillis = 0;

  digitalWrite(SENSOR, HIGH);
  attachInterrupt(digitalPinToInterrupt(SENSOR), pulseCounter, RISING);
}
 
void loop()
{
  currentMillis = millis();
  if (currentMillis - previousMillis > interval) 
  {
    //noInterrupts();
    
    pulse1Sec = pulseCount;
    pulseCount = 0;

    //interrupts();
 
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - previousMillis)) * pulse1Sec) / calibrationFactor;
    previousMillis = millis();
 
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    flowLitres = (flowRate / 60);
 
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;
    totalLitres += flowLitres;
    
    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(float(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space
 
    display.clearDisplay();
    
    display.setCursor(10,0);  //oled display
    display.setTextSize(1);
    display.setTextColor(SH110X_WHITE);
    display.print("Water Flow Meter");
    
    display.setCursor(0,20);  //oled display
    display.setTextSize(2);
    display.setTextColor(SH110X_WHITE);
    display.print("R:");
    display.print(float(flowRate));
    display.setCursor(100,28);  //oled display
    display.setTextSize(1);
    display.print("L/M");
 
    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.print("mL / ");
    Serial.print(totalLitres);
    Serial.println("L");
 
    display.setCursor(0,45);  //oled display
    display.setTextSize(2);
    display.setTextColor(SH110X_WHITE);
    display.print("V:");
    display.print(totalLitres);
    display.setCursor(100,53);  //oled display
    display.setTextSize(1);
    display.print("L");
    display.display();
  }
}

Here is my setup

Anyone please help why I am not getting the accurate values.

Regards
RJ

The flow range starts at 1lire/min , below that it will be in error or may not start or be very repeatable. What flow rate do you have ?
Accuracy is stated as +- 10% , that is probably +- 3 litres/min !

It is well worth just counting pulses with a basic sketch and doing a manual calculation of water passed - you need to do that to identify where the error lies .
Try having a higher head of water too and do the test over a big volume passed.

Why have you set the sensor pin written high as though an output - don’t think you need that .
Are you missing pulses whilst the display updates or you print .

Any use ?

Thank you so much for your reply.

I think i need to do that.

I am going to connect this sensor with RO water dispenser to calculate the water, so its output pipe will be thin and i guess prressure will be not much.

I will check that.

No, I am not missing any pulses.

Its changing fast

What you really want is far from clear. Is it volume, is it rate, or is it both? The only thing that might be clear is that you expect readings displayed once every second, or thereabouts. If that is the case, I defy you to read it anyway. These hall-effect sensors must be tailored to the anticipated flow. The small size in the pic suggests you may be doing that.

Generally, they are pretty accurate over a reasonable period, and this can be checked most easily by confirming the volume - even though the rate is all over the place. What this suggests is that you are simply reading the rate too often - as well as with considerable difficulty. If you need rate, you might be better off averaging it over several readings.

I also suspect your code is not only bloated but also wasting time by printing stuff in the loop that you shouldn't be. The line

    display.print("Water Flow Meter");

in the loop is probably indicative of a raft of slack-arsed sins. On that matter, there may be a better choice of library. I'm not familiar with your display but there may be an equivalent of
SSD1306Ascii.h
SSD1306AsciiAvrI2c.h
available for it which makes more sense than the graphics library I believe you are using.

You may get some value from the below

/**
 * Water Flow Gauge FOSTERS 20X4

 *
 * Uses a hall-effect flow sensor to measure the rate of water flow 
 * Copyright 2009 Jonathan Oxer <jon@oxer.com.au>
 * Copyright 2009 Hugh Blemings <hugh@blemings.org>
 *
 */

#include <LiquidCrystal_I2C.h>
#include "Wire.h"

LiquidCrystal_I2C lcd(0x27,20,4); 

byte sensorInterrupt = 0;  // 0 = pin 2; 1 = pin 3
byte sensorPin       = 2; //

float calibrationFactor = 6.71;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;

int  second, minute, hour, weekDay, monthDay, month, year;
int daily, maxflow, yesterday;

void setup()
{
    Wire.begin();
  lcd.init();
   delay(2000);

  lcd.clear();
        lcd.backlight(); 
      lcd.setCursor(0,2);
      lcd.print(calibrationFactor);
      delay(2000);
    
      lcd.setCursor(0, 0);
      lcd.print("Flow: ");
      lcd.setCursor(11, 0);   
      lcd.print("L/min");
      
      lcd.setCursor(0, 1);
      lcd.print("Total: ");
      lcd.setCursor(14, 1);   
      lcd.print("Litres");
      lcd.setCursor(0, 3);
      lcd.print("    FOSTERS");
      
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount          = 0;
  flowRate            = 0.0;
  flowMilliLitres          = 0;
  totalMilliLitres         = 0;
  oldTime             = 0;

  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

void loop()
{
  if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
   
    detachInterrupt(sensorInterrupt);

    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    oldTime = millis();

   flowMilliLitres = (flowRate / 60) * 1000;

   totalMilliLitres += flowMilliLitres;

    lcd.setCursor(6, 0);

    if(int(flowRate) < 10)
    {
      lcd.print(" ");
    }
    lcd.print(flowRate);   
    lcd.setCursor(7, 1);
    lcd.print(int(totalMilliLitres / 1000));

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

byte bcdToDec(byte val)  {
  // Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}


1 Like

I don't think that small outlet pipe is a good idea, I think you are just asking for trouble. If you need the smaller pipe, make the change further down the line.

I just want to calculate the volume.

These things can be altered.

I just got one thing that i am using YFS201 which is 1/2 inch

I am planning to use YFS401 which is 1/8 inch.

I think it will do

That would be a very good idea, it could be a major cause of your problem. I know you have said you are not missing any pulses, but what I don't know is how you would know that. I don't really know what you are doing, but the last line of your Setup rather suggests you are trying to bat for two different teams at the same time.

yea, i guess.

I guess some pulses are being missed.

hello mr nick how i can initialise the totalmillilitre valeurs

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.