Count Pulses from Water Meter and Open Valve Every 'N' pulses

I would like to find out if the following requirements can be achieved with an Arduino Uno.

  • Count pulses generated by a flow meter without missing any pulses and totalize the water that has moved through the meter. Every pulse must be counted otherwise the flow will not be accurate. Pulses are TTL and every pulse represents X amount of water.
  • Turn valve on and off every 'N' number of pulses and have 'N' settable using push buttons like up down and enter etc.
  • Calculate flow rate in gallons per minute by counting number of pulses in a given time period then display results on a LCD like this https://www.sparkfun.com/products/9568.

The pulses could be counted with an external interrupt. However, I think in order to display the flow rate on an LCD the external interrupt would have to be disabled so the arduino can successfully write a command to the LCD using serial communication (learned that one from experience). If the interrupt is disables then the potential of missing pulses exists. Turning on a valve should be easy and almost instantaneous by connecting a transistor to a digital output, I'm not too concerned about the feasibility of this part of the project. I think other digital inputs can be used using the pin change command to detect button pushes.

Is there an internal counter I could use or would I have to possibly figure out how to connect an external counter? Thanks for any feedback.

  1. use interrupts to not miss pulses

did something for a KWH meter - Arduino Playground - EEM12L-32AKWhMonitoring -

Think most of your needs are explained on the tutorial section (buttons lcd), so I advice to spend some evenings there and learn by going through the tutorials.

Start simple and build up functionality gradually

Thanks for your reply robtillaart.

I understand that interrupts do not miss pulses. However, it is my understanding that if you're in the middle of outputting a command on the serial communication pin, then you detect an interrupt, the output command gets halted mid sentence so to speak so the interrupt routine can run run which causes the command being written to the LCD to be messed up resulting in the LCD displaying garbage. Feel free to correct me if any of my assumptions are incorrect.

That is why an interrupt should be short as

void IRQ()
{
counter++;
}

and your LCD will never notice.

If its true that a routine that short wouldn't affect the serial communication then it is a great and simple solution. That is pretty much all the interrupt routine would have to to. I could then check the value and reset the variable in the main loop at my leisure. Have you used this technique successfully before?

billions times if I count all the interrupts :slight_smile:

note that in the main code you must use interrupts() and nointerrupts() if you want to access this counter.
That prevents that the interrupt changes the value while you are accessing a multibyte var.

NoInterrupts() will disable interrupts, but the CPU will buffer 1 Interrupt so no pulse is lost

Thanks for the tip. I would not have thought to disable the interrupt to access data like that. I suppose the 'counter' in you example is an arbitrary variable or is there something special about the 'counter' string in the arduino IDE? I also have never heard that the cpu can buffer 1 interrupt before. Is there any documentation that explains more about this? I did search but didn't come up with much.

Edit: I suppose declaring the 'counter' variable as volatile only removes the need to turn the interrups of and on for the variable to be read if it is a single byte variable.

I suppose the 'counter' in you example is an arbitrary variable or is there something special about the 'counter' string in the arduino IDE?

arbitrary unsigned long (4 bytes) most of the times...

I also have never heard that the cpu can buffer 1 interrupt before. Is there any documentation that explains more about this?

IIRC it is in the atmel 328 datasheet (500+ pages). WHen there is an interrupt a special register is set so the CPU knows it must handle it. Because interrupts are disabled it may not do so. When interrupts are enabled again, the CPU can handle the "temporary blocked" interrupt.

Edit: I suppose declaring the 'counter' variable as volatile only removes the need to turn the interrups of and on for the variable to be read if it is a single byte variable.

The keyword volatile takes care that the variable is read from and written to memory every time it is accessed. This prevents that a var is optimized in a register temporary. It is used for variables that can be changed from outside the main program. This can be interrupts, but also if you have memory mapped IO you must declare such var as volatile too.