Struggling to make this flowmeter work

Hi,
Very new to Arduino and trying to make this flowmeter work.
Everything works but the flowrate (L/min) is cumulative where I want it to be dynamic i.e rising and falling as it reads the pulses from the flowmeter

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

LiquidCrystal_I2C lcd(0x27, 16, 2);  // Change the address (0x27) based on your I2C module

const int flowSensorPin = 2;  // Flow sensor signal pin
volatile int pulseCount = 0;
float calibrationFactor = 7.5;  // Adjust this based on your sensor's specifications

void setup() {
  lcd.init();       // Initialize the LCD
  lcd.backlight();  // Turn on the backlight
  lcd.setCursor(0, 0);
  lcd.print("Flow: ");
  lcd.setCursor(0, 1);
  lcd.print("Total: ");

  pinMode(flowSensorPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(flowSensorPin), pulseCounter, FALLING);
}

void loop() {
  static unsigned long lastTime = 0;
  unsigned long currentTime = millis();

  if (currentTime - lastTime >= 1000) {
    float flowRate = pulseCount / calibrationFactor;
    float totalVolume = pulseCount / (calibrationFactor * 60);  // in liters

    lcd.setCursor(6, 0);  // Position cursor for flow rate
    lcd.print("      ");  // Clear previous value
    lcd.setCursor(6, 0);  // Position cursor again
    lcd.print(flowRate, 1);
    lcd.print(" L/min");

    lcd.setCursor(8, 1);    // Position cursor for total volume
    lcd.print("        ");  // Clear previous value
    lcd.setCursor(8, 1);    // Position cursor again
    lcd.print(totalVolume, 1);
    lcd.print(" L");

    lastTime = currentTime;
  }
}

void pulseCounter() {
  pulseCount++;
}

Any guidance greatly appreciated. As I stated I am very new to this.

So, what stops it from being dynamic? Did you write the code? perhaps you forgot to reset something back to zero after you used it.

1 Like

And look at forum guidelines and use code tags

If you read as @hammy suggests, you will find we like to look at code that hasn't been mangled.

An easy way to do this is to

First use the autoformat tool in the IDE to put your code into a standard format.

Then use the copy for forum tool in the IDE, and come back and just paste into a new sketch, or edit your post - select all the code in it and paste the formatted and for forum code you just got from the IDE.

Ppl will read mangled code, many more ppl will read code that looks like code

void setup() {

}

void loop() {

}

a7

Your flowrate and totalvolume calculation need some revision as both are calculated based on pulsecount ( which is incremental and never reset ) and one is the scaled value of the other ( which can't be )
Something like this seems better:

noInterrupts();
int p = pulseCount;
pulseCount = 0;
interrupts();
float flowRate = (p / calibrationFactor);
float totalVolume += p / (calibrationFactor * 60); // in liters

This does not take in consideration that each period is not exactly 1 second ( but avoids divisions )

P.S.
Consider that for few counts per second this is not the best approach

Thanks for that. Did not know about the autoformat tool

No copied it from the internet. As I said I am very new to this and trying to teach myself

Done. Edited original post.

I'm in transit. At a glance, your sketch is orientated to produce a result and publish it periodically.

To get more dynamic, you could reduce the period of the update, with appropriate changes to the calculations to reflect the reduced observation time.

I can't but it might be possible with things you are already doing to measure the time between two successive impulses from the flow meter, which is the extreme and most rapid possible way to see dynamic changes.

Instead of waiting one second or whatever and checking for how many, you cou,d time a certain small number like 1 or 15 pulses.

Instead of X pulses per second, you'd be using X seconds per pulse (or 5 or ten).

What is the frequency of the pulses at the maximum expected flow rate?

a7

You have the flowRate and totalVolume calculations crossed. The interrupt routine counts pulses for one second. You multiply the pulse count by the calibration factor which I presume converts the counts to liters that have been measured during that second. That value should be added to the flow total. It is not the flow rate.

The flow rate in liters per minute is calculated by multiplying the volume you measured in one second by 60.

One thing you should consider is that by multiplying the pulses every second and then adding to the total for your display you are also adding up the accumulated rounding error every second. If you simply keep track of the total pulses counted and then multiply that total count by the cal. factor when you write to the display you will have a more accurate total.

Fixed!
Did some looking around, found some other code and added some small tweaks for my needs.

Here is what worked perfectly

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

LiquidCrystal_I2C lcd(0x27, 16, 2);  // Change the address (0x27) based on your I2C module


volatile int flow_frequency; // Measures flow sensor pulses
float vol = 0.0,l_minute;
unsigned char flowsensor = 2; // Sensor Input
unsigned long currentTime;
unsigned long cloopTime;
const int GLED = 12; //Green Led connected to pin 12

void flow () // Interrupt function
{
   flow_frequency++;
}
void setup()
{
   pinMode(flowsensor, INPUT);
   pinMode(LED_BUILTIN, OUTPUT); // Use LED for output
   pinMode(GLED, OUTPUT); // Use LED for output
   digitalWrite(flowsensor, HIGH); // Optional Internal Pull-Up
   Serial.begin(9600);
  lcd.init();       // Initialize the LCD
  lcd.backlight();  // Turn on the backlight
   lcd.begin(16, 2);
   attachInterrupt(digitalPinToInterrupt(flowsensor), flow, RISING); // Setup Interrupt
   lcd.clear();
   lcd.setCursor(4,0);
   lcd.print("Crusher");
   lcd.setCursor(1,1);
   lcd.print("Oil Flow Check");
   delay(3000);
   currentTime = millis();
   cloopTime = currentTime;
   
}
void loop ()
{
   currentTime = millis();
   // Every second, calculate and print litres/hour
   if(currentTime >= (cloopTime + 1000))
   {
    cloopTime = currentTime; // Updates cloopTime
    if(flow_frequency != 0){
      // Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
      l_minute = (flow_frequency / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Rate: ");
      lcd.print(l_minute, 0);
      lcd.print(" L/m");
      l_minute = l_minute/60;
      lcd.setCursor(0,1);
      vol = vol +l_minute;
      lcd.print(" Vol: ");
      lcd.print(vol, 1);
      lcd.print(" L");
      flow_frequency = 0; // Reset Counter
      Serial.print(l_minute, DEC); // Print litres/hour
      Serial.println(" L/Sec");
      digitalWrite(LED_BUILTIN, LOW);  // turn the LED off
      digitalWrite(GLED, HIGH);  // turn the Green LED on 
    }
    else {
      Serial.println(" Flow rate = 0! ");
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Flow rate = 0! ");
      lcd.setCursor(0,1);
      lcd.print("Total Vol : ");
      lcd.print(vol, 0);
      lcd.print(" L");
      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on 
      digitalWrite(GLED, LOW);  // turn the Green LED off
    }
   }
}

Thank you for your help!

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