Don't Count if button is held for more than 100mS

is there a simple way to stop the counter if the button being pressed (I'm my case a hall sensor in HIGH position) for a period, I'm using this code for a simple flow meter to count the pulses which works great, unless the impeller stops in a High position, this then causes the code to keep counting which can cause an issue if I'm not watching,

I am aware there is already quite a few codes out there for flow meters, but I'm trying specifically to count pulses and averages to calculate formulas for different sensors.



// this constant won't change:
const int  buttonPin = 34;    // the pin that the pushbutton is attached to
const int ledPin = 5;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by checking the modulo of the
  // button push counter. the modulo function gives you the remainder of the
  // division of two numbers:
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

If you want to track time, you will have to introduce another variable that records the time[millis()] when a transition happens (LOW->HIGH or HIGH->LOW)] and then use that to determine how long you have been in a given state and act accordingly.

Check out the Blink Without Delay example in the IDE (File->examples->02.digital->Blink Without Delay) to see an example. Try to incorporate that concept into your code. If/when you get stuck, post your best effort here and people will help

Thank you will give this a go :slight_smile:

Also, the code you posted will only increment the counter 1 time if the sensor is held for more than 100msec since it counts transitions. It should not "keep counting"

You already have the state change detection code so you only count the signal when it goes from LOW to HIGH. It will not count just because the signal stays HIGH.

If your code is counting rapidly it is because the impeller has stopped on the edge between ON and OFF. I would have expected the Hall sensor to have some hysteresis. If that is the case you can add debounce timing to ignore the bounces.

  static unsigned long lastStateChangeTime = 0;
  if (buttonState != lastButtonState && millis() - lastStatChangeTime > DebounceInterval) {
   lastStateChangeTime = millis();
    // if the state has changed, increment the counter
1 Like

very very school boy error, i changed the code but never uploaded :see_no_evil: epic fail

thanks all yes the original code is running

Hi @mattyra .
Is there any reason not to use interrupt?

RV mineirin

sure, iv not really got my head around them,

when i tried it kept stopping other sections of the code from running,

Hi @mattyra ,
try this one ans say results.

//  Interrupt pin Mega, Mega2560, MegaADK
//  2, 3, 18, 19, 20, 21
//  (pins 20 & 21 are not available to use for interrupts
//  while they are used for I2C communication)

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 5;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
bool flag = false;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(buttonPin), myCounter , RISING);
}
void myCounter()
{
  buttonPushCounter++;
  flag = true;
}

void loop() {
  // read the pushbutton input pin:
  if (flag == true)
  {
    Serial.println("on");
    Serial.print("number of button pushes: ");
    Serial.println(buttonPushCounter);
    flag = false;
  } else {
    // if the current state is LOW then the button went from on to off:
    Serial.println("off");
  }

  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

this works in as much as it says off - when i spin the senor the number jumps in to the 1000s on the button count

You need to disable interrupts, make a copy of buttonPushCounter and then enable interrupts to reliably run that code. You also need to declare buttonPushCounter as volatile so the compiler does the right thing. flag does not need this since it is a single byte variable

//  Interrupt pin Mega, Mega2560, MegaADK
//  2, 3, 18, 19, 20, 21
//  (pins 20 & 21 are not available to use for interrupts
//  while they are used for I2C communication)

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 5;       // the pin that the LED is attached to

// Variables will change:
volatile int buttonPushCounter = 0;   // counter for the number of button presses
volatile bool flag = false;

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(buttonPin), myCounter , RISING);
}
void myCounter()
{
  buttonPushCounter++;
  flag = true;
}

void loop() {

  int buttonPushCounterCopy;

  noInterrupts();
  buttonPushCounterCopy = buttonPushCounter;
  interrupts();
  
  if (flag == true)
  {
    Serial.println("on");
    Serial.print("number of button pushes: ");
    Serial.println(buttonPushCounterCopy);
    flag = false;
  } else {
    // if the current state is LOW then the button went from on to off:
    Serial.println("off");
  }

  if (buttonPushCounterCopy % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}
1 Like