[TriEmbed] 32u4 hardware interrupts and wake behaviors

Alex Davis alexd at matrixwide.com
Fri Mar 9 07:37:42 CST 2018


Following on my sleep/wake issues with the Feather M0, I have switched to the Feather 32u4. The 32u4 is less flexible with regards to external pin change interrupts, so I have kept things simple and just went with hardware interrupts INT2 and INT3.

I’m using <avr/sleep.h> and have no trouble waking the micro on external interrupt.

The problem comes with polling the input used for the interrupt to detect button presses. I would like to wake on pin LOW (button tied to ground) and then time how long the button is pressed down. This way accidental button presses will be less likely to turn the device on.

The code looks like this - simplified with LEDs to show what it is doing vs my actual code:

  // red LED on until button is pressed
  digitalWrite(RED_LED, HIGH);

  // spin around until the button is pressed
  while (digitalRead(BUTTON_0) == HIGH);

  // red LED off
  digitalWrite(RED_LED, LOW);
  // blue LED on
  digitalWrite(BLUE_LED, HIGH);
  
  // wait a bit to settle bouncing
  delay(50);
  // start button timer
  buttonTime = (unsigned long)millis();  
  // see if the button is held down long enough
  while (digitalRead(BUTTON_0) == LOW)
  {
    // if the button is held down LONG_CLICK_MS or more
    if (((unsigned long)millis() - buttonTime) > LONG_CLICK_MS)
    {
      digitalWrite(BLUE_LED, LOW);
    }
  }
  digitalWrite(RED_LED, HIGH);

This works as expected when it has not woke from an interrupt on BUTTON_0 (INT2). However, if I wake from INT2 (detaching it as soon as I wake) and run it, it will spin around forever in the second while loop until the button is released. It is as though Arduino pin 0 (PD2/INT2) being high somehow breaks millis(). It is not a case of millis() alone being broken after waking, as I can use it as a delay loop right after waking with no issue. I just can not combine it with polling the PD3 pin.

My work around for the time being is to wake on INT2 (pin 0 or PD2) and then look for a long press on pin 1 or PD3. It requires me to have the second button, though.

Interestingly enough, the exact same <avr/sleep.h> code and millis() loop wake/long button press detect routine works fine on an ATTINY85 (as used in my UV meter business card).

I NEED TO BUY A DEBUGGER!!!

|\ |  (¯  \/ |¯\  |V| |\ ¯|¯ |¯) | \/ | | | |¯\ (¯   /¯  /\ |V|
|-||_ (_  /\ |_/ @| | |-| |  | \ | /\ |^| | |_/ (_ . \_  \/ | |







-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.triembed.org/pipermail/triembed_triembed.org/attachments/20180309/d823528a/attachment.htm>


More information about the TriEmbed mailing list