Program using a button timer

Why isn't the following working? I want to push a button and that starts the timer. Once the timer is complete I want the serial monitor to print my line. I feel like this makes sense to me but I am new to arduino. I have piece this together from other code so there may be redundancies I am not seeing.

#include <Arduino.h>

//Define constants ------------------------------------
#define BTN 27
#define LED_PIN 13

//Setup variables ------------------------------------
volatile bool buttonIsPressed = false;

//Setup interrupt variables ----------------------------
volatile bool interruptCounter = false;
int totalInterrupts;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

//Initialization ------------------------------------
void IRAM_ATTR isr() {
buttonIsPressed = true;
timerRestart(timer);

}

void IRAM_ATTR onTime() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter = true;
portEXIT_CRITICAL_ISR(&timerMux);
}

void TimerInterruptInit() {
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTime, true);
timerAlarmWrite(timer, 10000000, true);
timerAlarmEnable(timer);
}

void setup() {

digitalWrite(LED_PIN, LOW);
pinMode(LED_PIN, OUTPUT);
pinMode(BTN, INPUT);
attachInterrupt(BTN, isr, RISING);
TimerInterruptInit();
Serial.begin(115200);
}

//Main loop ------------------------------------
void loop() {

if (CheckForButtonPress()) {
ButtonResponse();
if (CheckForTimeDone()) {
TimeDoneResponse();
}
}

}

//Functions -------------------------------------
bool CheckForTimeDone() {
if (interruptCounter) {
return true;
interruptCounter = false;
}
else
return false;
}

bool CheckForButtonPress() {
if (buttonIsPressed == true) {
return true;
}
else
return false;

}

void TimeDoneResponse() {
Serial.println("1 second has passed since the last button press!");
timerStop(timer);
}

void ButtonResponse() {
buttonIsPressed = false;
Serial.println("Pressed!");
delay(100);

}

Please follow the advice given in the link below when posting code. Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

What type of Arduino?

How is your button wired? Have you used a pull-up or pull-down resistor?

Try this:

#define BTN 27

void setup() {
  pinMode(BTN, INPUT);
  Serial.begin(115200);
}

void loop() {
  while (digitalRead(BTN) == LOW); //wait for button to be pressed
  Serial.println("Pressed!");
  delay(1000);
  Serial.println("1 second has passed since the last button press!");
  while (digitalRead(BTN) == HIGH); //if button is still pressed, wait for it to be released
}

should this be INPUT_PULLUP?

That depends on the answer to this question:

:man_shrugging:

I am using an esp32. I have a pull up resistor in my circuit and we are doing event driven programming so even though I know the code you posted works, I'm supposed to use the structure of the code I posted. :frowning:

OK. Given that then I see a few issues:

  1. In loop() you call CheckForTimeDone() within the conditional that checks for a button press. The problem is that ButtonResponse() sets the buttonIsPressed to false so once you call that you never call CheckForTimeDone() again.

  2. CheckForTimeDone() never sets interruptCounter to false because you return before that line of code is executed:

bool CheckForTimeDone() {
  if (interruptCounter) {
    return true;
    interruptCounter = false;
  }
  else
    return false;
}
  1. In general, you have an unnecessary number of small functions that make your code hard to read.

there's no need because the arduino processor has a built-in pullup resistor

does this require the use of interrupts?

is this for an Arduino?

  • pin 27 is not an interrupt on an Uno or Mega
  • where are these defined
    ** timerBegin()
    ** timerAttachInterrupt()
    ** timerAlarmEnable()
    ** timerRestart()
    ** timerStop()
  • if there's a pullup on the button pin and you want to detect the press, why is the interrupt configured for RISING, instead of FALLING
  • if "CheckForTimeDone() is called before 1 second has expired and is not called again, how can it recognize that a second has expired?

in general, interrupts are overkill for recognizing button presses pressed by humans because interrupts are intended to detect event very quickly or of short duration.

and recognizing that a second has elapsed doesn't suggest the need for a quick response

consider


//Define constants ------------------------------------
#undef MyHW
#ifdef MyHW
#define BTN     A1
#else
#define BTN     27
#endif

#define LED_PIN 13

#define ONE_SECOND  1000

//Setup variables ------------------------------------
byte          butState = HIGH;
unsigned long msecLst;

//Initialization ------------------------------------
void setup () {
    digitalWrite (LED_PIN, LOW);
    pinMode      (LED_PIN, OUTPUT);
    pinMode      (BTN, INPUT_PULLUP);

    Serial.begin (115200);
}

//Main loop ------------------------------------
void loop () {
    unsigned long msec = millis ();
    if ( (0 != msecLst) && (msec > msecLst))  {
        msecLst = 0;
        Serial.println ("1 second has passed since the last button press!");
    }

    byte but = digitalRead (BTN);
    if (butState != but)  {
        butState = but;
        delay (10);         // debounce

        if (LOW == but)  {
            msecLst = msec + ONE_SECOND;
            msecLst = 0 == msecLst ? 1 : msecLst;
            Serial.println ("Pressed!");
        }
    }
}

this was helpful, ty! I am trying to work out how to use functions which is why it is structured this way so I appreciate you not trying to rework the whole thing.

I have to use the interrupts

for the button or timer?

Why are you taking so final a stance? Is your loop so long that it misses a press because it's not polling the buttons frequently enough? Is it plagued by long, blocking delays? Or what else is happening?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.