Need Help with Getting Decimal Pulses for Flow Meter Readings

Hello everyone,

I am working on an in-line flow meter project and am having difficulty with the data readings since I am measuring the flow rate based on pulses. Is there a way to read pulses as decimals instead of integers? The flow rate data from my testing was 1.6 L/hr and 3.21 L/hr. The 1.6 L/hr corresponds to 1 pulse, and the 3.21 L/hr corresponds to 2 pulses when checked using the pulse counter. The flow rate obtained from another flow meter is within this range, so it is correct. However, I need an approximate and consistent value for the flow rate to create a calibration curve when doing manual testing. Does anyone have an idea of how I can achieve this? I used an Arduino UNO. Here is my code.

#include <max6675.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <RTClib.h>

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27, 20, 4);
RTC_PCF8523 rtc;

// for the data logging shield,I use digital pin 10 for the SD cs line
const int chipSelect = 10;

// The hall-effect flow sensor outputs 
// litre/minute of flow.

volatile float pulseCount;  


float flowRate;
float totalLiters;
float density;

unsigned long oldTime;


int thermoDO = 4;
int thermoCS = 5;
int thermoCLK = 6;
MAX6675 thermocouple (thermoCLK, thermoCS, thermoDO);


// File object for data logging
File dataFile;

void setup()
{
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);

    // Set up the LCD's number of columns and rows:
  lcd.init(); //initialize the lcd
  lcd.backlight(); //open the backlight

    //Initialize SD card
  if (!SD.begin(chipSelect)) {
    Serial.println("SD initialization failed!");
    return;
  }
    Serial.println("SD initialization done.");



      dataFile = SD.open("MANUAL", FILE_WRITE); 
    if (!dataFile) {
    Serial.println("Error opening data file.");
    return;

  }
  // Write header to file
  dataFile.println("Time, Flowrate (L/min), Volume (L), Temperature (°C), Density (kg/m3");
  dataFile.flush();
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);
  

  pulseCount        = 0;
  flowRate          = 0.0;
  totalLiters       = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a HIGH state change (transition from LOW
  // state to HIGH state)
  attachInterrupt(sensorInterrupt, pulseCounter, HIGH);
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
        
    // 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() - oldTime)) * pulseCount / 37.40;
// flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount / 2244.19)*3600;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = 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.
    totalLiters += flowRate / 60 * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    //totalLiters += flowRate;
    thermocouple.readCelsius(); //Data for temperature sensor.

    if(28 > thermocouple.readCelsius() >= 27);
     density = 840*(.9898 - (((27-thermocouple.readCelsius())*(0.9898-0.9890))/(27-28)));
    if(thermocouple.readCelsius() >= 30);
    if(29 > thermocouple.readCelsius() >= 28);
    density = 840*(.9890 - (((28-thermocouple.readCelsius())*(0.9890-0.9881))/(28-29)));
    if(thermocouple.readCelsius() >= 30);
    density = 840*(.9873 - (((30-thermocouple.readCelsius())*(0.9873-0.9847))/(30-33)));
    if(thermocouple.readCelsius() > 33);
    density = 840*(.9847 - (((33-thermocouple.readCelsius())*(0.9847-0.9839))/(33-34)));
    if(thermocouple.readCelsius() > 34);
    density = 840*(.9839 -(((34-thermocouple.readCelsius())*(0.9839-0.9830))/(34-35)));
    if(thermocouple.readCelsius() > 35);
    density = 840*(.9830 -(((34-thermocouple.readCelsius())*(0.9830-0.9822))/(35-36)));
    if(thermocouple.readCelsius() > 36);
    density = 840*(.9822 -(((34-thermocouple.readCelsius())*(0.9822-0.9813))/(36-37)));
    
          
    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(flowRate, 5);  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Volume: ");        
    Serial.print(totalLiters);
    Serial.print("mL"); 
    Serial.print("\t");       // Print tab space

    Serial.print("PULSE: ");        
    Serial.print(pulseCount);
    Serial.print("p/s"); 
    Serial.print("\t");       // Print tab space

    // Print temperature
    
    Serial.print("Temp: ");
    Serial.print(thermocouple.readCelsius());
    Serial.print("°C  ");
    Serial.print("\t");
    //Print Density

    Serial.print("Density: ");
    Serial.print(density);
    Serial.print("kg/m3");
    Serial.println("\t");
        
    // Write data to CSV file
    dataFile.print(millis() / 1000); // Time in seconds
    dataFile.print(",");
    dataFile.print(flowRate); // Flow rate
    dataFile.print(",");
    dataFile.print(totalLiters); // Volume
    dataFile.print(",");
    dataFile.print(thermocouple.readCelsius()); // Temperature
    dataFile.print(",");
    dataFile.println(density);
    dataFile.flush(); // Flush data to SD card
    dataFile.close();
    
    // LCD
    lcd.setCursor( 0, 0); // set the cursor to column 0, line 0
    lcd.print("Flow: ");
    lcd.print(flowRate);
    lcd.print(" L/min");   // Print the volumetric flow rate in Liters per minute:
    lcd.setCursor( 0, 1); // set the cursor to column 0, line 1
    lcd.print("Volume: ");        
    lcd.print(totalLiters);
    lcd.print(" mL");
    lcd.setCursor(0, 2); // Set the cursor to column 0, line 2
    lcd.print("Temp: ");
    lcd.print(thermocouple.readCelsius());
    lcd.print(" °C");
    lcd.setCursor (0,3);
    lcd.print("Density: ");
    lcd.print(density);
    lcd.print("kg/m3");
    
    // 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, HIGH);
  }
}
/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;}

That makes no sense at all. If you need an answer to your calculation that is in fractions, just divide by 10 or what ever fraction you need.

Can you elaborate on this? Pulses are detected, not read...


HIGH, or RAISING?


Please explain what you expect this instruction to do, perhaps you could include a sample calculation using estimated values for millis(), oldTime and pulseCount.


You really need to read about how an if sentence is constructed in c++, and how it works. For instance,

These are syntactically correct, but they have no effect at all and they certainly do not do what you expect them to.

Hello, I'm new to using C++. What I meant by this is that whenever I print the pulseCount, it only shows an integer like 1, 2, 3...


Is there a way to make it like 1.78 or with decimals, more precise.

The documentation on the"print()" tells all there is to know about printing the number of decimal places.

Hi,

Thank you for pointing out my mistakes in the code, really appreciate it.

  1. For "Is there a way to read pulses as decimals instead of integers?"
    I want to detect a more accurate pulseCount. So far, when I tried to test, it's only 1, 2, or 3 per reading in the Serial monitor. Are they always detected as whole numbers?
    I will try adding a format first, as suggested, and see if the result is still the same.

  2. I haven't fixed the note yet. I tried using FALLING, RISING, CHANGE, and HIGH to see if there would be a difference in the number of pulses detected.
    image

  3. I will try your suggestion. I will include "millis()", "oldTime", and "pulseCount" and see what values they show.
    image

  4. I've tried reading a bit about if functions, but there's not much out there like my code. I've created this; is it correct?

Which flowmeter?

Hi,

RS PRO Oval Gear Flow Meter, 0.01 L/min → 1 L/min

Yes.
Your sensor measures flow in pulses. It is obvious that Impulses can only be whole. Therefore, printing pulses with decimal places does not make any sense.
However, the flow calculated from the number of pulses can well be expressed in real numbers.

If you expect a help, please respect the forum rules and don`t show the code as an images.
Please read the forum guidelines to see how to make a good posts.

Hi,

Thank you very much for answering everyone. I will also read the forum rules as suggested.

You are trying to read Liters per minute to 5 decimal places, and compensate for thermal density changes with a very expensive and potentially very accurate flow meter, but with a 10 or 15 dollar hobby grade MCU? That kind of accuracy and repeatability requires a very precise time base which most Arduinos and kin probably don't have.
Does RS not have a display unit of a quality matching that flowmeter?

Is this the Flow Meter you have?
https://docs.rs-online.com/1c0d/A700000009334446.pdf

Please post your latest code. The use of a lengthy isr with calculations and communication is not the best way to go.

It would be good for you to read this excellent tutorial on using interrupts.
https://gammon.com.au/interrupts

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