Counting pulses

Hi, Wondering if I can call upon thoughts for the most elegant way to count pulses in a given timeframe? I'm trying to count how many times a digital pin goes high in a five second period without using interrupts? All thoughts greatly appreciated :slight_smile:

point5:
Hi, Wondering if I can call upon thoughts for the most elegant way to count pulses in a given timeframe? I'm trying to count how many times a digital pin goes high in a five second period without using interrupts? All thoughts greatly appreciated :slight_smile:

Would that be a continuous stream of pulses and checking for pulse count in every five second sample period, or just a once in while check for the number of pulses in a five second window?

Lefty

the most elegant way

Wearing a silk smoking jacket, reclining on a chaise longue, sipping Krug from a Lalique goblet.

AWOL ..... how did you that's what I'm doing right now :slight_smile: ..... if only I could carry it off !

Retrolefty, it would simply be counting the number of pulses in a 5 second period once in a while (let's say 5 minutes).

somthing like get the current milies time
endtime = milies + xxxxx
while (milies < endtime)
{ readpin readsignalstate
if (readsignalstate!=lastState){count++;lastState=readsignalState;}

}

something like a switch case thing like

val = digitalRead(pin)
switch (val)
{
case low:
break;
case high:
count += 1;
break;
}

EDIT: Or like not bad, with an actual if statement to associate low with 1 and high with 2, but this won't affect your code or slow anything down.

Thanks folks.... perhaps I was wrong about interrupts. I have run out of external interrupts but I see one can use pin change interrupts with this Library: Arduino Playground - PinChangeInt. I figured that if I use the milli timer to give me a 5 second slot I could then enable (attach) the interrupt at the start of the 5 seconds, with each interrupt causing a ++ count, and dettach the interrupt at the end of the 5 second slot to stop counting.

Perhaps the concept is OK but my coding is poor so it is not working :frowning:

The pulses look like the attached image.

Thoughts on how to properly code the concept above would be great... here is what I have done:

void reportAnemometer() {
  
  currentTime = millis();
  loopTime=(currentTime+5000);
  if(currentTime <= loopTime)
  {attachInterrupt(PIN1, &windPulse, RISING);
}
  else
  {detachInterrupt(PIN1);
   loopTime=0;}
 
  WindSpeed = (wPulse/ 5) * 2.4; //2.4 K/h for one switch closure per second
  Serial.print("WindSpeed: ");
  Serial.println(WindSpeed);
  wPulse=0;
}

  void windPulse() {
  wPulse ++;
  Serial.println("Wind Pulse");
}

IMAGE004.jpg

It is useful if you post all your code.
Like the declarations of the volatile-qualified variables you increment in your ISRs.

Serial.print() relies on interrupts being enabled. During your ISR, they are not. Don't use Serial.print() in an ISR.

Thanks folks, here is the fully and updated code - currently it is reporting about 250 pulses each time with the anemometer staionary - I guess the IF loop is firing the false interrupts?

#include <PinChangeInt.h>
#define PIN1 7
volatile float WindSpeed = 0;
volatile int wPulse=0;
unsigned long currentTime;
unsigned long loopTime;

void setup() 
{
  Serial.begin(9600);
  Serial.println("Starting...");
  pinMode(PIN1, INPUT);
  digitalWrite(PIN1, HIGH);
  delay(1000);  
}

void loop()
{
  reportAnemometer();  
  delay(5000); 
}

void reportAnemometer()
{
  currentTime = millis();
  loopTime=(currentTime+5000);
  if(currentTime <= loopTime)
  {attachInterrupt(PIN1, &windPulse, RISING);
}
  else
  {detachInterrupt(PIN1);
   loopTime=0;}
  
  WindSpeed = (wPulse/ 5) * 2.4; //2.4 K/h for one switch closure per second
  Serial.print("wPulse: ");
  Serial.println(wPulse);
  Serial.print("WindSpeed: ");
  Serial.println(WindSpeed);
  wPulse=0;
  WindSpeed=0;
}

  void windPulse()
{
  wPulse ++;
}
  {attachInterrupt(PIN1, &windPulse, RISING);

The first argument to the attachInterrupt() function is the interrupt number. Interrupt 0 is associated with pin 2 and interrupt 1 is associated with pin 3, on a 328-based Arduino. There is no interrupt 7 on any Arduino.

  if(currentTime <= loopTime)
  {attachInterrupt(PIN1, &windPulse, RISING);
}
  else
  {detachInterrupt(PIN1);
   loopTime=0;}

Fix this lousy layout. Each { should have no code after it. The } goes on its own line.

  currentTime = millis();
  loopTime=(currentTime+5000);
  if(currentTime <= loopTime)

How can the if test ever fail to be true? if(currentTime <= currentTime + 5000) will always be true, for all values of 5000.

Hi Paul,

Thanks for the info. I think the <PinChangeInt.h> library allows pins change interrupts to be used on other Arduino pins, not just D2 & D3?

As the loopTime is set before the IF, is it not executed just once each time the reportAnemometer() function is called? Perhaps there is a better way?

As the loopTime is set before the IF, is it not executed just once each time the reportAnemometer() function is called?

Yes, loopTime is set just once per call to reportAnemometer(). So?

You are setting loopTime to currentTime + 5000, then comparing that value to currentTime. Of course, currentTime is going to be less than currentTime + 5000, for all values of currentTime. And, for all values of 5000.

I think the <PinChangeInt.h> library allows pins change interrupts to be used on other Arduino pins, not just D2 & D3?

It does. It does NOT use the attachInterrupt() function. It uses, instead, the attachInterrupt() method of the PCintPort class. They are not the same thing, at all.

Thanks Paul, I see your point :-).... I'm getting there I think - see below. The main issue now seems to be a very high pulse count - much too high - which I figure must be to do with bounce? Any ideas how to fix this?

#include <PinChangeInt.h>
#define PIN1 7
uint8_t latest_interrupted_pin;
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
volatile float WindSpeed = 0;
volatile int wPulse=0;
unsigned long currentTime;
unsigned long loopTime;

void windPulse()
{
  wPulse ++;
}


void setup()
{
  pinMode(PIN1, INPUT);
  digitalWrite(PIN1, HIGH);
  Serial.begin(9600);
  Serial.println("Starting...");
}

void loop()
{
  reportAnemometer();  
  delay(15000); 
}

void reportAnemometer()
{ 
  Serial.println("Measuring");
  currentTime = millis();
  loopTime=(currentTime+5000);
  Serial.print("currentTime: ");
  Serial.println(currentTime);
  Serial.print("loopTime: ");
  Serial.println(loopTime);
  while(loopTime >= currentTime)
{
  PCintPort::attachInterrupt(PIN1, &windPulse, RISING);
  currentTime = millis();
}
  PCintPort::detachInterrupt(PIN1);
  loopTime=0;
  WindSpeed = (wPulse/ 5) * 2.4; //2.4 K/h for one switch closure per second
  Serial.print("wPulse: ");
  Serial.println(wPulse);
  Serial.print("WindSpeed: ");
  Serial.println(WindSpeed);
  wPulse=0;
  WindSpeed=0;
  Serial.println("Finished");
}
  while(loopTime >= currentTime)
{
  PCintPort::attachInterrupt(PIN1, &windPulse, RISING);
  currentTime = millis();
}

Why do you need to keep attaching the interrupt?

Since you want to do nothing except count pulses for 5 seconds, I see no reason not to use delay(). Interrupts still file during delay().

Hmmmm... you are quite right :slight_smile:

Now this is working much better - thank you, I think I'm there.

void reportAnemometer()
{ 
  Serial.println("Measuring");
  currentTime = millis();
  Serial.print("currentTime: ");
  Serial.println(currentTime);
  PCintPort::attachInterrupt(PIN1, &windPulse, RISING);
  delay(5000);
  PCintPort::detachInterrupt(PIN1);
  WindSpeed = (wPulse/ 5) * 2.4; //2.4 K/h for one switch closure per second
  Serial.print("wPulse: ");
  Serial.println(wPulse);
  Serial.print("WindSpeed: ");
  Serial.println(WindSpeed);
  wPulse=0;
  WindSpeed=0;
  Serial.println("Finished");
}