Two Flow meters on one interrupt pin

Hello i am trying to use more than one flow meter on one interrupt pin. I have followed the write up (http://forum.arduino.cc/index.php/topic,8548.0.html) and successfully got both flow meter working to count liters per hour separately. I was wondering how i could configure it to count two flow meters on the same interrupt pin. (only one flow meter will be working at one time). I tried hooking the flow meters up in parallel and it works, but sometimes it doesn't. It is very sporadic on reading the meters, sometimes it works and sometimes it doesn't which i dont understand, from my understanding the meters send 5v on the signal line and the arduino counts in and displays it in the serial monitor. When it is in parallel it works but there are times when it seems like the meter isnt sending out a signal, until I unhook the other meter and it works perfect again. My question is why does it work sometimes and randomly not work?
Thank you in advance for your time.
(I'll attach the code i used below)

// reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com
// Code adapted by Charles Gantt from PC Fan RPM code written by Crenn @thebestcasescenario.com
// http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com

volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;                               
int hallsensor = 2;    //The pin location of the sensor

void rpm ()     //This is the function that the interupt calls 
{ 
  NbTopsFan++;  //This function measures the rising and falling edge of the 

hall effect sensors signal
} 
// The setup() method runs once, when the sketch starts
void setup() //
{ 
  pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
  Serial.begin(9600); //This is the setup function where the serial port is 

initialised,
  attachInterrupt(0, rpm, RISING); //and the interrupt is attached
} 
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop ()    
{
  NbTopsFan = 0;      //Set NbTops to 0 ready for calculations
  sei();            //Enables interrupts
  delay (1000);      //Wait 1 second
  cli();            //Disable interrupts
  Calc = (NbTopsFan * 60 / 7.5); //(Pulse frequency x 60) / 7.5Q, = flow rate 

in L/hour 
  Serial.print (Calc, DEC); //Prints the number calculated above
  Serial.print (" L/hour\r\n"); //Prints "L/hour" and returns a  new line
}

You need to know what the electrical properties of the meters' outputs are. Do the meters each drive the output high and low to generate the pulse, or do they rely on the external circuit pulling it low until the meter drives it high, or vice versa?

How long does your ISR take to run?

How long does each flowmeter pull the pin HIGH for each pulse?

What happens if the second flowmeter pulls the pin HIGH while the first flowmeter hasn't gone LOW yet? Answer: you'd miss the pulse.

Are you really so short on pins you can't give each flowmeter it's own input pin?

speedjayg:
My question is why does it work sometimes and randomly not work?

I recognise that you say only one flow meter will be working at one time, but I still think the real question is - why would you want to do this?

This particularly in view of the fact that you have already gotten the turbines to work individually. You can bet your problem is hardware and no amount of programming will fix it.

First i want to thank you all for the fast replies. I plan on using this in a project in where i use 6+ flow meters on one arduino board, so i want to use 2+ on each interrupt pin but i first want to get it working with just two before i even start adding more to the board. I know the Arduino uno only has two interrupt pins(I know the Mega has six but i plan on using more than six if possible) and this is a hall effect flow sensor, which from my understanding could only count RPM's with the interrupt. I was testing this earlier and had the two flow meter signal wires connected to the interrupt pin and i would test each flow meters at seperate times, giving adequate time inbetween tests to make sure the interrupt has finished then i would try it on the other one. Sometimes they would both work the way I imagined it would work, but just when i thought it would work perfect they would stop working like there was a short and it wasn't reading anything from the flow meter, 2 minutes later everything would work fine. So i know this method works but i must be missing something. Any ideas?
Thanks again.

speedjayg:
I know the Arduino uno only has two interrupt pins

Actually, any or all of the pins can be attached to interrupts:

http://playground.arduino.cc/Main/PinChangeInt

using a PCF8574 - Arduino Playground - HomePage -
you can connect its INT pin to the Arduino IRQ pin 2 and 3 giving you 16 IO lines monitored for pulses.
When the interrupt comes in you read the PCF8574 gettin the state of 8 bits at once,
mask them to see which pins have changed and which counters to update

demo sketch could look like:

//    FILE: PCF8574_int.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: 
//    DATE: 14-12-2013
//     URL:
//
// Released to the public domain

#include "PCF8574.h"
#include <Wire.h>

PCF8574 PCF_38(0x38);


unsigned long  lastTime = 0;
volatile unsigned long count[8];

void setup()
{
  Serial.begin(115200);
  Serial.println("\nTEST PCF8574 Interrupt\n");

  attachInterrupt(0, catchChange, CHANGE);
}

void loop()
{
  // once per second
  if (millis() - lastTime >= 1000)
  {
    lastTime += 1000;
    for (uint8_t i=0; i< 8; i++) 
    {
      Serial.print(',');
      Serial.print(count[i]);
    }
    Serial.println();
   }
}

void catchChange()
{
  static uint8_t last = 0xFF;
  uint8_t tmp = TWBR;
  TWBR = 2; // speed up I2C;
  uint8_t value = PCF_38.read8();
  TWBR = tmp;
  
  uint8_t v = (last ^ value) & value; // which pins are changed since last time from LOW to HIGH 
  last = value;

  uint8_t mask = 0x01;
  for (uint8_t i=0; i< 8; i++)
  {
    if (v & mask) count[i]++;
    mask <<= 1;
  }
}

Hello thank you for the excellent idea i plan on using it i just need to verify some items as i am a little confused on how the wiring diagram works. I was looking at the data sheet ( http://www.taydaelectronics.com/datasheets/A-905.pdf)

you can connect its INT pin to the Arduino IRQ pin 2 and 3 giving you 16 IO lines monitored for pulses

So i hook pin 13 on the PCF8574 on pin 2 and 3 on the arduino? Also i have two flow meters right now where would i hook them up on the PCF8574? on pin 1-7 and 9-12?
Also thank you for the demo code but how would i differentiate between and store the amount of flow (liters per hour) in two different variables so i can use them later in the code ( from each water flow meter). Thank you so much for your help and i appreciate the time you take to help.

This flow meters have open-collector outputs. When you connect them in parallel, if either is pulling its output LOW then LOW is what you get. You oly get HIGH if neither is pulling the output LOW. So if one of the flow meters is stopped and pulling its output LOW, you won't see anything from the other one.

If you can spare one Arduino pin for each flow meter, then the simplest approach is to use a separate pin for each one, and use pin change interrupts. You can get a pin change interrupt on every pin.

If you can't spare so many niput pins, either use the PCF8574 device already mentioned, or a 74HC4051 multiplexer.

Hello thanks for the write up dc42. From what i understood i could only measure the RPM of the hall effect sensor with a external interrupt. I have no problem sparing pins as i am using the mega and have plenty not in use, But the Mega only has 6 external interrupts and i would like to use more than that. I tried using PinChangeInt libary (http://playground.arduino.cc/Main/PinChangeInt) but i dont think it is compatible with the mega as i used the example code

#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>
 
#define PIN 15  // the pin we are interested in
volatile byte burp=0;    // a counter to see how many times the pin has changed
byte cmd=0;     // a place to put our serial data
 
void setup() {
  Serial.begin(9600);
  Serial.print("PinChangeInt test on pin ");
  Serial.print(PIN);
  Serial.println();
  pinMode(PIN, INPUT);     //set the pin to input
  digitalWrite(PIN, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(PIN, burpcount,RISING); // attach a PinChange Interrupt to our pin on the rising edge
// (RISING, FALLING and CHANGE all work with this library)
// and execute the function burpcount when that pin changes
  }
 
void loop() {
  cmd=Serial.read();  
  if (cmd=='p')
  {
    Serial.print("burpcount:\t");
    Serial.println(burp, DEC);
  }
  cmd=0;
}
 
void burpcount()
{
  burp++;
}

and it did not work with the mega. Maybe what you are mentioning is a different method? Any help would be much appreciated, I have many spare pins that can be used i just thought they needed to be the external interrupt pins specified by arduino.
Thank you for your time and help.

The readme file in the pin change int library says this:

NOTE: I don't have a Mega, so I rely on you to give me error (or working) reports!
To sum it up for the Mega: No Port C, no Port D. Instead, you get Port J and Port K. Port B remains.
Port J, however, is practically useless because there is only 1 pin available for interrupts.
Most of the Port J pins are not even connected to a header connector. Caveat Programmer.

Looking at the code for the pin change interrupt library, I think it may be incorrect for digital pins 14 and 15. There are 2 port J pins that can generate pin change interrupts, not one as the note (above) says. Also the pin change interrupt numbers for port J start at an odd offset into a byte, and I'm not sure the code is designed to support that (It's poorly commented so I'm not sure how it is supposed to work). I suggest you try one of the port B pins (digital pins 10-13 and 50-53), or one of the port K pins (analog pins A8-A15) instead.

Btw in my earlier reply I said that you can get a pin change interrupt on every pin; however that is not true for the Mega.

Thank you for further investigation that the library doesn’t work with Mega. I plan on working with the PCF8574 chip but now my question remains How would the wiring diagram look for the flowmeter to the PCF8574? So would I hook pin 13 on the PCF8574 (datasheet http://www.taydaelectronics.com/datasheets/A-905.pdf) on pin 2 and 3 on the arduino? Also where would i hook up the two flow meters on the PCF8574? on pin 1-7 and 9-12? Also from the demo code provided earlier

//    FILE: PCF8574_int.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: 
//    DATE: 14-12-2013
//     URL:
//
// Released to the public domain

#include "PCF8574.h"
#include <Wire.h>

PCF8574 PCF_38(0x38);


unsigned long  lastTime = 0;
volatile unsigned long count[8];

void setup()
{
  Serial.begin(115200);
  Serial.println("\nTEST PCF8574 Interrupt\n");

  attachInterrupt(0, catchChange, CHANGE);
}

void loop()
{
  // once per second
  if (millis() - lastTime >= 1000)
  {
    lastTime += 1000;
    for (uint8_t i=0; i< 8; i++) 
    {
      Serial.print(',');
      Serial.print(count[i]);
    }
    Serial.println();
   }
}

void catchChange()
{
  static uint8_t last = 0xFF;
  uint8_t tmp = TWBR;
  TWBR = 2; // speed up I2C;
  uint8_t value = PCF_38.read8();
  TWBR = tmp;
  
  uint8_t v = (last ^ value) & value; // which pins are changed since last time from LOW to HIGH 
  last = value;

  uint8_t mask = 0x01;
  for (uint8_t i=0; i< 8; i++)
  {
    if (v & mask) count[i]++;
    mask <<= 1;
  }
}

how would i differentiate between and store the amount of flow (liters per hour) in two different variables so i can use them later in the code ( from each water flow meter). I really appreciate the help with this i have never worked with a 8 bit I/O expander before and am thankful for all the help.

speedjayg:
Thank you for further investigation that the library doesn't work with Mega.

Strange, as I can compile it for a MEGA without problems.
.. Can you give me the error message(s) you get? (compile time)
-- or is the error runtime? (I do not have a MEGA nearby to test.
Is it with the proposed sample code?
You might try to remove the TWBR lines (these set the clock of the I2C bus)

I plan on working with the PCF8574 chip but now my question remains How would the wiring diagram look for the flowmeter to the PCF8574? So would I hook pin 13 on the PCF8574 (datasheet http://www.taydaelectronics.com/datasheets/A-905.pdf) on pin 2 and 3 on the arduino?

Yes, and be sure to have a common ground.

Also where would i hook up the two flow meters on the PCF8574? on pin 1-7 and 9-12?

you can use one of the P0 and P1 line, and connect P2..P7 all to GND so they will not give false interrupts.

Also from the demo code provided earlier
...
how would i differentiate between and store the amount of flow (liters per hour) in two different variables so i can use them later in the code ( from each water flow meter). I really appreciate the help with this i have never worked with a 8 bit I/O expander before and am thankful for all the help.

The code example give catches a change in one of the P0..P7 lines and the ISR increases the right counter in an array of 8 counters. If you use 2 flowmeters there should be only 2 counters incremented.
These counters you can converts to liters passed since start and by holding the previous value you can calculate the difference giving you the flow;.

speedjayg:
Thank you for further investigation that the library doesn't work with Mega.

Did you read all of my reply? That's not what I said. What I said was that I suspected it wouldn't work on pin 15 (even though pin 15 supports a pin change interrupt), and I suggested you try the other pins I listed instead.

speedjayg:
I plan on working with the PCF8574 chip

Seems a strange thing to do when the Mega provides more than enouh pins for you, with pin change interrupts on 25 of them. Even if you can't get the pin change interrupt library working, writing the code to handle pin change interrupts just for your flow meters would probably be easier than adapting your code to use the PCF8574.

I tested it on the pins you said dc42 and PinChangeInt did work on the pins you specified and that will be a good way for the flow meters I have now, however i already ordered some PCF8574 and they are shipped, Thanks to robtillaart I now have a better understanding on how to hook up the chip to the arduino board. I hook pin 13 on the PCF8574 on pin 2 and 3 of the arduino, then i hook the flow meters to pin p0-p7 while grounding the other pins i don’t use. The code is the only thing i am having a hard time to understand. The code that i was using was

// reading liquid flow rate using Seeeduino and Water Flow Sensor from Seeedstudio.com
// Code adapted by Charles Gantt from PC Fan RPM code written by Crenn @thebestcasescenario.com
// http:/themakersworkbench.com http://thebestcasescenario.com http://seeedstudio.com

volatile int NbTopsFan; //measuring the rising edges of the signal
float Calc;                              
int hallsensor = 2;    //The pin location of the sensor
float Total = 0;


void rpm ()     //This is the function that the interupt calls
{
  NbTopsFan++;  //This function measures the rising and falling edge of the
}
// The setup() method runs once, when the sketch starts
void setup() //
{
  pinMode(hallsensor, INPUT); //initializes digital pin 2 as an input
  digitalWrite(hallsensor, HIGH);
  Serial.begin(9600); //This is the setup function where the serial port is
  attachInterrupt(0, rpm, RISING); //and the interrupt is attached
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop ()    
{
  NbTopsFan = 0;      //Set NbTops to 0 ready for calculations
  sei();            //Enables interrupts
  delay (1000);      //Wait 1 second
  cli();            //Disable interrupts
  Calc = ((NbTopsFan * 60 / 7.5) / 60); //(Pulse frequency x 60) / 7.5Q, = flow rate
  Total += Calc;
  Serial.print (Calc, DEC); //Prints the number calculated above
  Serial.print (" Ounces/Liters\r\n"); //Prints "L/hour" and returns a  new line
  Serial.print (Total, DEC);
  Serial.print ( "Total Liters\r\n");
}

I know that works with the arduino now i was curious how i could get the same effect with the PCF8574 and the example code provided

//    FILE: PCF8574_int.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: 
//    DATE: 14-12-2013
//     URL:
//
// Released to the public domain

#include "PCF8574.h"
#include <Wire.h>

PCF8574 PCF_38(0x38);


unsigned long  lastTime = 0;
volatile unsigned long count[8];

void setup()
{
  Serial.begin(115200);
  Serial.println("\nTEST PCF8574 Interrupt\n");

  attachInterrupt(0, catchChange, CHANGE);
}

void loop()
{
  // once per second
  if (millis() - lastTime >= 1000)
  {
    lastTime += 1000;
    for (uint8_t i=0; i< 8; i++) 
    {
      Serial.print(',');
      Serial.print(count[i]);
    }
    Serial.println();
   }
}

void catchChange()
{
  static uint8_t last = 0xFF;
  uint8_t tmp = TWBR;
  TWBR = 2; // speed up I2C;
  uint8_t value = PCF_38.read8();
  TWBR = tmp;
  
  uint8_t v = (last ^ value) & value; // which pins are changed since last time from LOW to HIGH 
  last = value;

  uint8_t mask = 0x01;
  for (uint8_t i=0; i< 8; i++)
  {
    if (v & mask) count[i]++;
    mask <<= 1;
  }
}

I know now i can have more that 6 interrupts on the Mega and it may seem like a strange thing to try and use the PCF8574 but i would like to use and learn how to use these wonderful chips as i may use them in the future and others may as well.
I appreciate all the help so far and helping me work out my problem, and I will be grateful of any further help.

I have been trying to work with the PCF8574 and have found that i i only need to hook up pin 2 (on the arduino) to pin 13 (on the PCF8574) i also found that i needed to add pin 2 as a input, but i still am getting no reading from the interrupt pin. I have been working on this and cant seem to get anywhere, any help would be appreciated. I will post the code and the way i hooked up the flow meter to the PCF8574.

//    FILE: PCF8574_int.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE: 
//    DATE: 14-12-2013
//     URL:
//
// Released to the public domain

#include "PCF8574.h"
#include <Wire.h>

PCF8574 PCF_38(0x38);


unsigned long  lastTime = 0;
volatile unsigned long count[8];
int hallsensor = 2;

void setup()
{
  Serial.begin(115200);
  Serial.println("\nTEST PCF8574 Interrupt\n");
  pinMode(hallsensor, INPUT);
  attachInterrupt(0, catchChange, RISING);
}

void loop()
{
  // once per second
  if (millis() - lastTime >= 1000)
  {
    lastTime += 1000;
    for (uint8_t i=0; i< 8; i++) 
    {
      Serial.print(',');
      Serial.print(count[i]);
    }
    Serial.println();
   }
}

void catchChange()
{
  static uint8_t last = 0xFF;
  uint8_t tmp = TWBR;
  TWBR = 2; // speed up I2C;
  uint8_t value = PCF_38.read8();
  TWBR = tmp;
  
  uint8_t v = (last ^ value) & value; // which pins are changed since last time from LOW to HIGH 
  last = value;

  uint8_t mask = 0x01;
  for (uint8_t i=0; i< 8; i++)
  {
    if (v & mask) count[i]++;
    mask <<= 1;
  }
}

first check is if the interrupt are coming in,

I simplified the code a bit

//    FILE: PCF8574_int.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.00
// PURPOSE:
//    DATE: 14-12-2013
//     URL:
//
// Released to the public domain

#include "PCF8574.h"
#include <Wire.h>

PCF8574 PCF_38(0x38);  // <<<<<<<<<  is this the right address?  do not forget to set the address line right

unsigned long  lastTime = 0;
volatile unsigned long count[8];
const int hallsensor = 2;

void setup()
{
  Serial.begin(115200);
  Serial.println("nTEST PCF8574 Interruptn");
  pinMode(hallsensor, INPUT);
  attachInterrupt(0, catchChange, RISING);
}

void loop()
{
  // once per second
  if (millis() - lastTime >= 1000)
  {
    lastTime += 1000;
    for (uint8_t i=0; i< 8; i++)
    {
      Serial.print(',');
      Serial.print(count[i]);
    }
    Serial.println();
   }
}

void catchChange()
{
  count[0]++;  // minimalistic check
}

Directly monitoring (even dozens of these) without interrupts would not significantly add to the overall error of measurement. The drawback is that you would need to time-stamp the readings and this would consume more memory.

The measurement time is 1 second     1000.000000 ms
At 75 Hz max, the pulse period is      13.333333 ms
The 3% error represents: (+/-)          0.400000 ms
8 MHz Arduino clock period              0.000125 ms

For example, if it took 100 clock cycles to directly measure (read, count and timestamp) 25 sensors, then the overall error would be 0.4125 ms = +/- 3.09%.
Calculation of all flows (litres/hour) could be done after the 1 second measurement is done.

I have it wired up exactly as i have it posted in the diagram and used the shortened code and there is no interrupts coming through. On the serial monitor it is just reading 0's. I even tried it with another PCF8574. Do i have the right chip to be doing this i am using a PCF8574AP i noticed on the datasheet (http://www.taydaelectronics.com/datasheets/A-905.pdf) there is a PCF8574P could that be my problem? and dlloyd the measurement of these would need to be somewhat precise but do you know a way to monitor the flow without using interrupts? I would like to get this chip figured out but if there is another way i would be glad to hear about it.