Counting Pulses with a Flow meter

Good morning everyone,

I am very new to Arduino, and have been given a project that, from what I see, requires years of experience. Basically I need to calculate how much water is flowing through a pipe. I am using a _______ Flow meter, that produces pulses from what I understand. I have done the wiring from an outlet to a converter, which drops the voltage down from 110 volts to 24 volts. I than wired the PulseOut wire to drop to 5 volts to be plugged into the arduino Leonardo that I am using.

I guess my question is how can I write a program to “count” the pulses per sometime? I did a lot of reading on the forum the last couple of days and still cannot piece together a code that will allow me to count the pulses, which I can than convert to gallons per minute. I am assuming I will have to use some interrupts, or pulseIn functions, and use the PWM ports. I just do not understand how they piece together.

And maybe I am having troubles connecting to the correct ports to read pulses. Do I use PWM ports or serial data ports or another? I am very confused.

Here is a small code I pieced together, that I thought might work, but turned out it did not.

/*
 * HardwareCounting sketch
 *
 * uses pin 5 on 168/328
 */
const int hardwareCounterPin = 5; // input pin fixed to internal Timer
const int ledPin = 13; 
const int samplePeriod = 5000; // the sample period in milliseconds
unsigned int count;
int calc;

#include <LiquidCrystal.h>
#include <Wire.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
 Serial.begin(9600);
 pinMode(ledPin,OUTPUT);
 // hardware counter setup (see ATmega data sheet for details)
 TCCR1A=0; // reset timer/counter control register A
  lcd.begin(16, 2);
  // Print a message to the LCD.
} 
void loop()
{
 digitalWrite(ledPin, LOW);
 delay(1000);
 digitalWrite(ledPin, HIGH); 
 // start the counting
 bitSet(TCCR1B ,CS12); // Counter Clock source is external pin
 bitSet(TCCR1B ,CS11); // Clock on rising edge 
 delay(samplePeriod);
 // stop the counting 
 TCCR1B = 0; 
 count = TCNT1;
 TCNT1 = 0; // reset the hardware counter
 if(count >= 0)
 
 calc= (count);
 Serial.print (calc, DEC);
 Serial.println(" Pulse\r\n");

 lcd.setCursor(0, 1);
  // print the number of seconds since reset:
 lcd.print(calc, DEC);
 lcd.println(" Pulse\r\n");
}

Thank you guys/girls for any help!

Zack

Forgot to add the type of flow meter…

I added a picture of the meter, maybe that will make it easier to understand.

I think you will be better off using an interrupt unless you know how long the pulse takes

connect your sensor outputting 5V to pin 2 (Interrupt 0), so you will have to rejigger your LCD pins. Since you are not using it in the code, you should be OK . There are comments in the code for you to understand…

Try something like this (not tested):

#include <LiquidCrystal.h>
#include <Wire.h>

const int hardwareCounterPin = 2; // Interrupt 0 is pin2
const int ledPin = 13; 
const unsigned long samplePeriod = 5000UL; // the sample period in milliseconds
unsigned long startTime;
unsigned int pulseCount = 0;
unsigned long startFlash;
unsigned long flashTime = 250UL;
boolean flashToggle = false;
int lastPulseCount = 0;
int calc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);// initialize the LCD library with the numbers of the interface pins

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  lcd.begin(16, 2);
  // Print a message to the LCD...?
  attachInterrupt( 0, wasPulse, RISING);
  startTime = millis();
} 
void loop()
{
  if (flashToggle) flashLED();  //ledPin will flash for 250ms each pulse.
  if (pulseCount > lastPulseCount) // if you detect a pulse, initiate a flash
  {
    startFlash = millis();
    flashToggle = true;
    lastPulseCount = pulseCount;
  }
  if (millis() - startTime >= samplePeriod)  // this will 'wait' for samplePeriod and then calculate the rate without using a delay 
  {
    calculateGPM();
  }
}

void calculateGPM()
{
  int pulses = pulseCount;  // start to ignore any more interrupts
  Serial.print("there were this many pulses: ");
  // do the math to convert pulses to GPM
  Serial.println (pulses);
  // Print to your LCD  here...
  startTime = millis();
  pulseCount = 0; //reset the pulseCount variable and return to loop() function
}

void flashLED()
{
  digitalWrite(ledPin, HIGH);  // turn led on
  if (millis() - startFlash >= flashTime)
  {
    digitalWrite(ledPin, LOW);
    flashToggle = false; //after timer expired, turn led off
  }
}

void wasPulse()
{
  pulseCount++;  //the interrupt increments the counter, that is it and all it should do.
}

BulldogLowell,

I tried the code, and I still cannot get a pulse read back. I have an LCD attached for future versions, I am trying to make it portable. I changed the LCD code around to allow DIGITAL Pin 2 to be open, and I plugged my 5v positive into the port. And I grounded the sensor through the Arduino. I did make some adjustments to the code and I will attach below, but I was wondering what else I could try? I personally waited too long to start on this project and I am in a crunch to finish as soon as possible.

Do I need an LED attached?

Thank you for taking time to try and help! I really appreciate it!

Zack

#include <LiquidCrystal.h>
#include <Wire.h>

const int hardwareCounterPin = 2; // Interrupt 0 is pin2
const int ledPin = 13; 
const unsigned long samplePeriod = 10000UL; // the sample period in milliseconds
unsigned long startTime;
unsigned int pulseCount = 0;
unsigned long startFlash;
unsigned long flashTime = 250UL;
boolean flashToggle = false;
int lastPulseCount = 0;
int calc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);// initialize the LCD library with the numbers of the interface pins

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  lcd.begin(16, 2);
  // Print a message to the LCD...?
  attachInterrupt( 0, wasPulse, RISING);
  startTime = millis();
} 
void loop()
{
  if (flashToggle) flashLED();  //ledPin will flash for 250ms each pulse.
  if (pulseCount > lastPulseCount) // if you detect a pulse, initiate a flash
  {
    startFlash = millis();
    flashToggle = true;
    lastPulseCount = pulseCount;
  }
  if (millis() - startTime >= samplePeriod)  // this will 'wait' for samplePeriod and then calculate the rate without using a delay 
  {
    calculateGPM();
  }
}

void calculateGPM()
{
  int pulses = pulseCount;  // start to ignore any more interrupts
  Serial.print("Gallons per Minute: ");
  // do the math to convert pulses to GPM
  Serial.println (pulses*.08);
  // Print to your LCD  here...
  
 lcd.setCursor(0, 1);
 lcd.println("Gallons Per Minute: ");
 lcd.setCursor(0, 0);
 lcd.print(pulses*.08);
  
  startTime = millis();
  pulseCount = 0; //reset the pulseCount variable and return to loop() function
}

void flashLED()
{
  digitalWrite(ledPin, HIGH);  // turn led on
  if (millis() - startFlash >= flashTime)
  {
    digitalWrite(ledPin, LOW);
    flashToggle = false; //after timer expired, turn led off
  }
}

void wasPulse()
{
  pulseCount++;  //the interrupt increments the counter, that is it and all it should do.
}

zlander: BulldogLowell,

I tried the code, and I still cannot get a pulse read back. I have an LCD attached for future versions, I am trying to make it portable. I changed the LCD code around to allow DIGITAL Pin 2 to be open, and I plugged my 5v positive into the port. And I grounded the sensor through the Arduino. I did make some adjustments to the code and I will attach below, but I was wondering what else I could try? I personally waited too long to start on this project and I am in a crunch to finish as soon as possible.

Do I need an LED attached?

Thank you for taking time to try and help! I really appreciate it!

Zack

it is blinking the on-board led connected to pin13,

your leonardo has different interrupts than my Uno:

External Interrupts: 3 (interrupt 0), 2 (interrupt 1), 0 (interrupt 2), 1 (interrupt 3) and 7 (interrupt 4). These pins can be configured to trigger an interrupt on a low value, a rising or falling edge, or a change in value. See the attachInterrupt() function for details.

so if you are on Pin2, you need to change this:

attachInterrupt( 0, wasPulse, RISING);

to this instead:

attachInterrupt( 1, wasPulse, RISING);

sorry about that!!!

are you sure that the sensor outputs 5V? did you verify with a multimeter?

I would comment out all of the LCD stuff until you get the Serial output right.

add a debug line here and see if you get a pulse:

if (pulseCount > lastPulseCount) // if you detect a pulse, initiate a flash
  {
    Serial.println("PULSE DETECTED");
    startFlash = millis();
    flashToggle = true;
    lastPulseCount = pulseCount;
  }

if you have a voltage, and are detecting it, well that't progress....

it is blinking the on-board led connected to pin13, (you are using an Uno?).

are you sure that the sensor outputs 5V? did you verify with a multimeter?

I am using a leonardo, and the led on the board flashes every 10 seconds. I assume that's when a reading has been taken.

I have verified that, there is 5v going in. I am going to check the pulses with a oscilloscope later and double check.

Thank you!

zlander:

it is blinking the on-board led connected to pin13, (you are using an Uno?).

are you sure that the sensor outputs 5V? did you verify with a multimeter?

I am using a leonardo, and the led on the board flashes every 10 seconds. I assume that's when a reading has been taken.

I have verified that, there is 5v going in. I am going to check the pulses with a oscilloscope later and double check.

Thank you!

OK, check the interrupt pin too... it is supposed to be 1 for pin 2. I showed where above^^

What is the frequency you measure on the scope.

Sorry to leave you guys hanging on the topic.

So what I have determined is that the flow meter I was using didn't output pulses correctly, and the oscilloscope reflected that. The scope could not find a range to center on because the meter was producing small waves, than wide waves and back to small.

I tested another meter we had laying around and the code produced a line of steady numbers, that were close enough to start initial testing. I think I want to increase the time elapsed for counting to something like one minute to allow for more accurate data (hopefully).

I have made some alterations to the code to allow for a LCD print, which allows me to make the whole setup portable, and will allow me to create my own controller to plug onto the flow meters to spot check them as needed.

I will re-release the code once I have it completed for my setup, and all alterations are complete.

Thank you all!