Flow sensor math

I have this flow sensor.

http://www.seeedstudio.com/depot/G12-Water-Flow-Sensor-Enclosure-p-1915.html

This is the only specs on it.

Mini. Wokring Voltage: DC 4.5V
Max. Working Current: 15mA (DC 5V)
Working Voltage: DC 5V~24V
Flow Rate Range: 1~30L/min
Flow Pulse: F(Hz)=(5.0*Q)±3% Q=L/Min
Load Capacity: ≤10mA (DC 5V)
Operating Temperature: ≤80℃
Liquid Temperature: ≤120℃
Operating Humidity: 35%~90%RH
Water Pressure: ≤1.75MPa
Storage Temperature: -25~+ 80℃
Storage Humidity: 25%~95%RH

Notice Flow Pulse: F(Hz)=(5.0*Q)±3% Q=L/Min

I wrote this code. When I gently blow into it, I'm getting ~300 L/minute. It doesn't seem right, too much. Maybe if I take out the *60? That'll get me down to single digits.

unsigned long duration;

void setup() {
  Serial.begin(9600);
  // put your setup code here, to run once:
  pinMode(7, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  duration = pulseIn(7, HIGH);
  Serial.print(duration);
  Serial.println(" microsecond");
  Serial.print(1000000UL/duration*60/5.0);
  Serial.println(" L/min");
  
}

mistergreen:
I'm getting ~300 L/minute. It doesn't seem right, too much.

It is probably right and you are getting a reading like that because you are disobeying the instruction not to blow through it. These things don't rotate very quickly. The pulse rate is usually written on the side and I believe it is usually one pulse per revolution.

Ah thanks. I'll just have to really hook it up to my aquarium filter to see.

I find flow rate impossible to use and maybe best done with an average of ten readings. Flow quantity can be very accurate.

In your code, you are using PulseIn() to determine the duration of the pulse. This is just telling you the amount of time the magnet is in front of the sensor and is related to the speed of rotation and the physical geometry of the sensor/magnet.

This is not the correct way to use this sensor. You need to count the number of pulses in a second and divide by 5 to get the flow rate. Use an interrupt to count pulses. Here is an example which counts pulses for a second. As Nick says, averaging may be helpful. Depending on your flow rate, you may want to change the time period for the counting. Adjust the flow rate math accordingly.

Reading the flow rate sensor is very similar to all the rpm/tachometer examples you will find.

volatile unsigned int  count = 0;

unsigned int copyCount = 0;

unsigned long lastRead = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("start...");

  attachInterrupt(0, isrCount, RISING); //interrupt signal to pin2
}

void loop()
{
  if (millis() - lastRead >=1000) //read interrupt count every second
  {
    lastRead = millis();
    // disable interrupts,make copy of count;reenable interrupts
    noInterrupts();
    copyCount = count;
    count = 0;
   interrupts(); 
   
    Serial.println(copyCount);//counts per second = Hz; divide by 5 for Flow rate l/min
  }
}

void isrCount()
{
  count++;
}

Thanks cattledog. I've seen the interrupt method for flow sensors. It wanted to see if I can do without since it requires attach, detach, resetting the counter. It's a bit of a hassle.

So that's why I took a million divided by microsecond pulseIn to get hertz. I've tried both and the result output seems to be the same. I'll do physical testing soon. Oh, I think I see. Having code in the loop() might vary depending on how much code need to be executed. An interrupt would be free of that.

Yeah, an average would be helpful too since I've notice the rate jumps around irratically.

So that's why I took a million divided by microsecond pulseIn to get hertz.

Mathematically, this cannot be correct, and is dependent upon the physical geometry of the sensor and magnet. Think of the sensor rotation in degrees/second. Suppose the flow sensor is rotating at 1 Hz. If the magnet physically takes up one degree of arc, it will be in front of the sensor for 1 degree out of 360 and you will get a pulse length of 1/360th of a second. If the magnet takes up 10 degrees of arc it will be in front of the sensor for a different pulse length, i.e. 10/360th of a second.

I believe you could calibrate pulse length to counts for a given sensor. You could also measure pulse length HIGH and pulse length LOW during a rotation to work out the geometry, but I think that interrupts are a more straight forward way to go.

Oh, another issue with interrupt is it can only run one at a time on the atmega. I need to run multiple at the same time. Does anybody know if that can be done with the due?

Oh, another issue with interrupt is it can only run one at a time on the atmega. I need to run multiple at the same time. Does anybody know if that can be done with the due?

I don't know anything about the Due, but on the Atmega's multiple interrupts are always running and there is a documented hierarchy which determines the order in which the isr is executed when multiple interrupts are working.

I would assume the Due knows how to handle multiple isr's being called as well.

See Nick Gammon

If you prefer using pulseIn, try this:

unsigned long durHigh, durLow, durPulse;

void setup() {
  Serial.begin(115200);
  pinMode(7, INPUT);
}

void loop() {
  durHigh = pulseIn(7, HIGH);
  durLow = pulseIn(7, LOW);
  durPulse = durHigh + durLow;
  Serial.print(durPulse);
  Serial.println(" microsecond");
  Serial.print(1000000UL / (durPulse * 5));
  Serial.println(" L/min");
}