# Solution needed for counting pulse inputs WITHOUT using Intterupts

I need a solution for counting pulse inputs WITHOUT using Intterupts. I am using an Arduino Mini Pro 3v3 with the AtMega 328P processor.

I would like to count the amount of pulses that occur in 1sec.

FYI I have tried many solutions but i am hoping one of you will have the one i need.

Hi!
What is the amount of pulses You want to Count during 1 sec? Max, min?

It might change later currently it is 50/sec and that is steady

Okey.
50 pulses per second give a time slot of 20 mS per pulse.
I don't know the exact limits of the Arduino so my answer might be a bit unscertain. Can an Arduino receive pulses into any counter that can be read?

To me it looks like polling could work. Count pulse flanks using the function millis during one second. This will make the controller totaly occupied during the measuring time of one second.

An other alternative could be using an external counter that is reset, timestamped in the Arduino and started. Then stopped after 1000 millis and read.

Anything new in this?

jball:
I need a solution for counting pulse inputs WITHOUT using Intterupts. I am using an Arduino Mini Pro 3v3 with the AtMega 328P processor.

I would like to count the amount of pulses that occur in 1sec.

FYI I have tried many solutions but i am hoping one of you will have the one i need.

Either way, your pulses cannot go higher than 3.3 volts.

If so, you can connect to any digital pin and look for a low condition followed by a high condition. That set of conditions equal ONE pulse.

Paul

You can set the timers of an Arduino to external clock signal, and use them to count your pulses.

Timer1 and Timer2 are best for this (Timer0 is used by the millis() function and other Arduino specific functions, so don't use that timer if you want to use milis()). Note that both timer0 and timer2 are 8-bit so roll over at 256, timer1 is 16-bit rolling over at 65536.

FYI I have tried many solutions

Why not tell us which ones you have tried? And post the code (in code tags). Then we won't waste our time telling you about stuff you've already tried.

Pete

This earlier posting by jball is relevant http://forum.arduino.cc/index.php?topic=545347.15

After trying to count pulses on a flow meter with sub optimal code he has now decided to abandon interrupt techniques.

``````interrupts();           // starts interupt
delay(1000);            //waits 1 sec
noInterrupts();         // ends interupt
``````

Trying to use polling or external clock sources on timers would be a better tackled after standard pulse counting interrupt code was tried.

``````volatile unsigned long  count = 0;
unsigned long copyCount = 0;

unsigned long interval = 1000;//one second

void setup()
{
Serial.begin(115200);
Serial.println("start...");

pinMode(2,INPUT_PULLUP);
attachInterrupt(0, isrCount, RISING); //interrupt signal to pin 2
}

void loop()
{
{
// disable interrupts,make copy of count,reenable interrupts
noInterrupts();
copyCount = count;
count = 0;
interrupts();

Serial.println(copyCount);

}
}

void isrCount()
{
count++;
}
``````

And there I was... assuming it's yet another school assignment where an unusual/unsuitable solution is to be used to demonstrate the teacher you can do it.

At 20 ms pulses, unless you need to know exactly when they happen or so, you shouldn't even need interrupts. Just poll the pin and do state checking.

At 20 ms pulses, unless you need to know exactly when they happen or so, you shouldn't even need interrupts. Just poll the pin and do state checking

As far as I know, the hall sensor flow rate sensors put out pretty short pulses which are happening every 20ms at his flow rates. It really is an appropriate use of an interrupt.

Agreed. I was thinking more in the 20 ms on/20 ms off line for 20 ms pulse. That's indeed a case for interrupts.

Nevertheless it should be quite straightforward to implement.

jball:
It might change later currently it is 50/sec and that is steady

50/sec is 20ms but is that 50ms HIGH then 50ms LOW over and over or is it a very short blip of LOW every 50ms?

Using direct port read you can monitor the line more than 50 times a millisecond to watch for 20ms pulses going by like turtles. Mitsubishi has a white paper with led to led communications where data 0 is 2 to 4 HIGH reads and data 1 is 7 to 10 HIGH reads, short vs long pulse. Doing that they were able to achieve "rock solid" led to led 250 cps bidirectional comes at range of 5cm or less. PDA's and remotes could talk up close for the cost of a led and a resistor and some code.

You see they sensed he real world redundantly to be sure of their results. And you have the speed to do the same.

Without seeing the code that the OP has so far produced, it is difficult to propose a tailored solution.
I would, however, not be so quick as the OP to rule out using an interrupt, and would favour something similar to the way that @Cattledog has already suggested, maybe where the interrupt service routine incorporates a bit of debouncing (for the case that the pulses are ragged) and maintains a counter. In the loop (or with a timer), periodically calculate the number of pulses received in unit time to determine the pulse rate. It should be very simple. If there are reasons why an interrupt based solution is incompatible with the existing code, then those issues have to be addressed.

We’re also assuming OP’s pulses are clean.
It may be necessary to filter/cleanup the pulses to avoid miscounting stray edges

6v6gt:
If there are reasons why an interrupt based solution is incompatible with the existing code, then those issues have to be addressed.

The reason my interrupt solution only works in theory/serial monitor is when i connect my wireless transmitter to send the pulse data no data will be sent because i use the noIntterupts() function and this stops all interrupts including the useful background interrupts used to send bytes through the serial hardware.

jball:
The reason my interrupt solution only works in theory/serial monitor is when i connect my wireless transmitter to send the pulse data no data will be sent because i use the noIntterupts() function and this stops all interrupts including the useful background interrupts used to send bytes through the serial hardware.

That does not make sense.

I have a project managing the speed of a small DC motor that produces pulses at about 3 millisec intervals and they are detected by an interrupt. The program also receives wireless data and uses a PID calculation to adjust the PWM value to hold the speed constant.

Post your program if you want help.

...R

That's just poor programming.

First of all: why would you even want to disable interrupts for an extended period?
Secondly: if you want to disable a specific interrupt, do that.

In most programs, the only reason to use noInterrupts() is to copy a value that is updated by an ISR to a new variable, after which interrupts() is called switching all interrupts back on.

wvmarle:
if you want to disable a specific interrupt, do that.

How would can i disable a specific Interrupt?

Sorry, I am green

``````const int pin = 2;              //pin for pulse input
const int SETP = 1;             //(1/SETP)=K factor (user set on flowmeter)
const int numReadings = 10;     // the number of readings to be averaged
const int t = 10;               // the amount of time in between seiral print

volatile unsigned long  count = 0;       //interupt service routine variable

unsigned long pulse = 0;
unsigned long interval = 1000;//one second

int total = 0;                           // the running total
int average = 0;                         // the running average
int GpM;                        // variable for solving Gsllons per Minute
int a=0;                //variable for sending message every so often
int test = 21;

int i;
int n =10;

boolean joinAccept = false;

String inputString = "";         // a String to hold incoming data
boolean stringComplete = false;  // whether the string is complete

void setup() {

// initialize serial communications at 57600 bps:
Serial.begin(57600);      // initialize LoRa module communications

// reserve 200 bytes for the inputString:
inputString.reserve(200);

// setting up the LM-210 LoRa module control pins:
pinMode(3, OUTPUT); // module P1 pin
pinMode(4, OUTPUT); // module P2 pin

// P1=0 and P2=0 : module active mode (Mode 1)
digitalWrite(3, LOW); // module P1 pin
digitalWrite(4, LOW); // module P2 pin

pinMode(pin, INPUT_PULLUP);  //set pulse pin as input

//digital pin interupt (triggered everytime pin goes from low to high)
attachInterrupt(0, isrCount, RISING);

//intialize all the readings to 0:
{
}

Serial.println (255, HEX); // wake-up LM-130 from sleep mode

for (i = 0; i < n; i++)
{serialEvent();
Serial.println (i);
if (joinAccept == 1) i=n;
delay (1000);
}
Serial.print ("joinAccept = ");
Serial.println (joinAccept);
if (joinAccept == 0) { loraconfig(); }
if (joinAccept) { Serial.println ("no lora config needed");}
}

void loop() {

{
// disable interrupts,make copy of count,reenable interrupts
noInterrupts();
pulse = count;
count = 0;
interrupts();
int pulse3 =pulse/3;
Serial.print("AAT2 Tx=2,uncnf,");
Serial.println(pulse3,HEX);
}

GpM = pulse * 60 * SETP;        //calculates gallons per minute

for (i = 0; i < n; i++)
{
serialEvent();
//Serial.println (i);
delay (300);
}

fr_average();
// Serial.print("AAT2 Tx=2,uncnf,");

//Serial.println(test,HEX);
// delay(10000);

return;
}

void fr_average()
{
//advance to the next postion in the array:

// if we are at the end of the array...
//...wrap around to the beginning/start the readings over:
}

//calculate the average:
// send it to the computer every minute
if (a >= t)
{
Serial.print("AAT2 Tx=2,uncnf,");         // LoRaWAN port 2, unconfirmed,
{
Serial.print(0, HEX);
}
//Serial.println( "GpM");
delay(1000);       // delay in between readings for stability
a=0;
}
else {a++;}
}

void isrCount()              //Interupt Service Routine
{
count++;               //increases pulse count every time the interupt occurs (which is every time the pulse goes from low to high)
}

void serialEvent() {
while (Serial.available()) {
// get the new byte:
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
if (inChar == '\n') {
stringComplete = true;
SerialParse ();
}
}
}

void loraconfig()
// this initializes the LM-110 LoRa module to TTN LoRaWAN OTAA
{

//Serial.println("AAT1 Reset"); delay (5000); //assume successful join to TTN network
// set join mode = OTAA, ADR=0, DutyCycle=on)
Serial.println("AAT2 JoinMode=1"); delay (50);
Serial.println("AAT2 DutyCycle=1"); delay (50);

//Set 8 channel TX frequencies for TTN USA
Serial.println("AAT2 Tx_Channel=0,903900000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=1,904100000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=2,904300000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=3,904500000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=4,904700000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=5,904900000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=6,905100000,30,1,0"); delay (50);
Serial.println("AAT2 Tx_Channel=7,905300000,30,1,0"); delay (50);

// set AppEui & AppKey
Serial.println("AAT2 AppEui=Not_for_you"); delay (50); //TTN Application ID: Not_for_you

Serial.println("AAT2 AppKey=Also_not_for_you"); delay (50); //Device ID: Also_not_for_you

Serial.println("AAT1 Save"); delay (5000);

// save and reset;
Serial.println("AAT1 Reset"); delay (1000); //assume successful join to TTN network

}

void SerialParse () {
// print the string when a newline arrives:
if (stringComplete) {
Serial.println(inputString);
if(inputString.indexOf("JOIN_NOT_ACCEPT") >= 0) {Serial.println("JOIN_NOT_ACCEPT action");signal_Led(1);};
if(inputString.indexOf("JOIN_ACCEPT") >= 0) {Serial.println("JOIN_ACCEPT action"); joinAccept = true; signal_Led(2);};
if(inputString.indexOf("Tx_ok") >= 0) {Serial.println("Tx_ok action"); signal_Led(3); i=10;};
if(inputString.indexOf("Tx_no_free_ch") >= 0) {Serial.println("Tx_no_free_ch action"); signal_Led(4);};
if(inputString.indexOf("Tx_not_joined") >= 0) {Serial.println("Tx_not_joined action"); signal_Led(5);};
if(inputString.indexOf("Tx_noACK") >= 0) {Serial.println("Tx_noACK action"); signal_Led(6);};

//INPUT DATA WAS PARSED, SO WE GET BACK TO INITIAL STATE.
inputString = "";
stringComplete = false;
}
}

void signal_Led(int n) {

for (i = 0; i < n; i++)
{
digitalWrite(13, HIGH);
delay (500);
digitalWrite(13, LOW); //  LED off;
delay (500);
}
}
``````

jball:
How would can i disable a specific Interrupt?

Sorry, I am green

Usually the same way you enabled that specific interrupt, with the disable counterpart of the function or register call you used. See documentation. detachInterrupt() is one such function. You switched it on, so you can switch it off.

That leaves the question: why?