Problems with flow based automatic liquid filler

Hello fellas, I write this looking if I can get help for a project i'm making.

I wanna make an automatic liquid filler where you can input X liters to dispense, and the basis for measuring volume will be a hall effect flow meter (YF-S201 in my case).

So, as a first major step I wanted to dispense exactly 1 liter, but I've ran into a hair pulling problem, the sensor, according to the datasheet, sends a certain amount of PWM pulses depending on the flow, measuring the flow of my pump manually, I get around 4.3 Litres per minute, however the output pulses of the sensors are all over the place, for the flow I measured, I should be getting around 40-50 pulses per second. On this pic I recorded some pulses per second readings on the serial monitor, and as you can see, they're definitely not lining up to the real flow.

REgistry2

This makes the arduino code detect a liter way faster than intended, making me only get about 400-700 ml of real liquid served.
I've already tried several code approaches to measure water flow through the flow meter pulses, and I also doble checked all my connections. I tried to buy a replacement flow meter, but the problem persists, so i'm all out of options here.

Here is a drawn circuit diagram of my project so far, hope it helps, also, here is one of my builds, it's messy for now, wanted to make it a lot more clean once I get it working.



And here is one of my versions of the code for getting the volume thru the flow readings. This one was made for recording the pulse readings but same principle as other versions, polling the flow meter for a certain amount of time and getting the current flow and volume values.

volatile int NumPulsos; //Variable for measuring pulses
int PinSensor = 2;    //Sensor connected to pin 2, interrup pin on UNO
float factor_conversion=7.5; //Conversion factor from YF-S201 datasheet
float volumen=0;//Se inicializa la variable de volumen
long dt=0; //variación/diferencia de tiempo por cada repeticion
long t0=0; //millisegundos pasados despues de repeticion anterior
int PinBoton = 7; //Pin for polling the trigger button
int PinBomba = 8;//Pin for pump activation via relay
int LEDpin = 13;
void ContarPulsos ()  //Interrup routine for when a pulse is received from the flow meter
{ 
  NumPulsos++;  //incrementamos la variable de pulsos
} 


int ObtenerFrecuecia() //Function for calculating frequency
{
  int frecuencia;
  noInterrupts();
  NumPulsos = 0;   //Pulse numer is reset
  interrupts();    //Enable interrupts
  delay(1000);   //We poll the flow meter for 1 second
  noInterrupts(); //Disable interrupts
  frecuencia=NumPulsos; //We register the number of pulses on 'frecuencia'
  return frecuencia;
}

void setup() //Funcion de configuracion inicial
{ 
  Serial.begin(9600);
  pinMode(PinBomba,OUTPUT); 
  pinMode(PinBoton,INPUT_PULLUP);
  pinMode(LEDpin,OUTPUT); 
  attachInterrupt(digitalPinToInterrupt(2),ContarPulsos,RISING);//Se declara la interrupcion al pin 2 (indicado como 0), la funcion que se ejecutara en la interrupcion, y que reaccionara hacia un flanco hacia arriba
  //Serial.println ("Para reiniciar el contador de litros envie una 'R' en serial monitor"); 
  t0=millis();//Se inicializa t0
  digitalWrite(PinBomba,HIGH);
} 

void loop ()    
{
 // if (Serial.available()) {
 //   if(Serial.read()=='r')
 //   volumen=0;//Se restablece el volumen si recibimos 'r'
 // }
  if(digitalRead(PinBoton) == LOW){ //Poll the pushbutton
   digitalWrite(LEDpin,HIGH);  
   delay(500);
  }else{ //When the button is pressed
    do{ //Loop for checking volume and update the flow
  digitalWrite(PinBomba,LOW);
  digitalWrite(LEDpin,LOW);
  float frecuencia=ObtenerFrecuecia(); //We get our pulse frequency
  interrupts();
  float caudal_L_m=frecuencia/factor_conversion; //Flow is calculated in L/m
  dt=millis()-t0; //We calculate time difference
  t0=millis();//t0 is reset
  volumen=volumen+(caudal_L_m/60)*(dt/1000); // volume(L)=flow(L/s)*time(s)
  Serial.println(frecuencia); //For testing purposes we only output the current pulse frequency

  }while(volumen < 1); //When the volume reaches 1 liter, stop the filling process
   digitalWrite(PinBomba,HIGH);
   digitalWrite(LEDpin,HIGH);
   volumen = 0;
   delay(1000); //We wait 1 second before we can trigger the pump again
  }
  }

Thanks for reading!

I suspect that the flowmeter output may be open collector. That means that there needs to be a pullup on pin 2 ( the sensor pin). Try the internal pullup (pinMode INPUT_PULLUP).

pinMode(PinSensor ,INPUT_PULLUP);

Put a serial print in to display the number of pulses per second before any math.

There needs to be a driver for that relay coil and a flyback diode or you are likely to lose pin 8.

Your button pin has the internal pullup enabled, but, in the schematic, is wired to Vcc with a pulldown resistor. What is it?

There are many tutorials on the net for using that sensor with Arduino. Search for "YF-S201 arduino".

I would write a simple code to count pulses and report.
Using millis(),

Capture millis() value
no interrupts, simply count to something like 1000 pulses
Capture millis() value and subtract the initial millis().
delay 2 seconds and repeat

See if the flow pulses are consistent. No interrupts just plain counting.

You could do it the inverse, count pulses for 2 or 10 seconds etc.

Note millis() are not perfect but they are stable.

Sadly I tried INPUT_PULLUP and results are still the same.
I did put a flyback diode parallel to the water pump, it's the little thing besides the square saying "PUMP" on the drawing.

Oh and about the PULL_UP on button pin, sorry, that was something I put back when I simulated a button by having a jumper connecting button pin and ground, and when I opened it, it would take it as a press, already removed it from the current versions.

Let's be clear about how you should wire a switch - or an open-collector sensor (which it seems the YF-S201 is not).

Connect the switch between the Arduino pin and ground. Specify pinMode for that pin as INPUT_PULLUP.

This will effectively connect an approximately 47k resistor in the microcontroller between the pin and Vcc. When the switch is closed, the pin will be LOW, otherwise it will be HIGH.

You may need to add a lower value - such as 5 K or even 1k - pullup resistor between the pin and Vcc if the switch connects by relatively long cables or if there is a risk of leakage due to moisture in the wiring. You can still use INPUT_PULLUP of course.

Why connect it to ground rather than Vcc - 5 V? mostly because it is safer not to have the 5 V supply connecting anywhere where it can be avoided in case of accidental short circuits and potential pick-up of interference. And also because the pull-up function is deliberately provided by design in the microcontroller.

Hi,
How consistent is the flow, does it pulse?
In other words is the pump a circulation type pump or a pulse type pump?

You are using an electric pump, it has a magnetic field, keep it as far away from the flow sensor.
Also keep its power supply wires away from the control and sensor.

Here is the manual; TTL output.
YFS201manual.662398285.pdf (143.2 KB)

Are you drawing water from a container then letting the outlet of the flow sensor back into the container?
Have you got the water flowing through the meter in the right direction?
Google;

YF-S201 arduino sketch

Also check the codes here, it appears to be shorter than yours.

Tom.... :grinning: :+1: :coffee: :australia:

If that is what you want, which is far from clear, I suspect your flow meter is inapprpriate.
While the RATE is all over the place, the overall QUANTITY at 4.3 l/min with that sort of sensor can be very good - within 1% of a big buck commercial unit - measured over 300 litres. This implies that the average rate must be pretty good too.

For short bursts, you might be better off with a Swissflow sf800, which I think has 6200 pulses/litre.