🎁📬❄️📦Adafruit Holiday Shipping Deadlines 2019: Please place all UPS 2 Day orders by 11am Monday, December 16 📦❄️📬🎁
0

wake from keypad interrupt but doesn't run reliably
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

wake from keypad interrupt but doesn't run reliably

by flyingblindonarocketcycle on Wed Nov 27, 2019 10:48 am

I have been learning HEAVILY from http://www.gammon.com.au/forum/?id=11497&reply=4#reply4 and https://forums.adafruit.com/viewtopic.php?f=25&t=59392#p329418
I am trying to wake the itsybitsy from sleep with a key press AND have the code use that waking key press as a valid input. What I have done works but not reliably. The first key press usually works but after going to sleep, it seems almost random when a key press is going to wake up the chip AND be used as an input. When powered with a 9v battery, I can hook up a current meter and see that the chip does wake up like expected every time.

How do I trouble shoot this? PS I am aware that pin change interrupts will not work for pin 12. I need to rewire my keypad but for now I am assuming I can just ignore the fact that it will use the top row of buttons as interrupts.

Thanks

Code: Select all | TOGGLE FULL SIZE
#include <Keypad.h>
#include <avr/sleep.h>
#include <avr/power.h>

const byte ROWS = 4;
const byte COLS = 3;
const byte ledPin = 13;

char keys[ROWS][COLS] =
  {
    {'1', '2', '3'},
    {'4', '5', '6'},
    {'7', '8', '9'},
    {'*', '0', '#'},
  };

byte rowPins[ROWS] = {12,10,11,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {3,2,1}; //connect to the column pinouts of the keypad
 
// number of items in an array
#define NUMITEMS(arg) ((unsigned int) (sizeof (arg) / sizeof (arg [0])))

  // Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

// turn off interrupts until we are ready
ISR (PCINT0_vect)
  {
  PCICR = 0;  // cancel pin change interrupts  *not sure what/why to do this*
  //detachInterrupt(0);
  }

void setup ()
  {
  byte i;
  pinMode (ledPin, OUTPUT);

    for (i = 0; i < NUMITEMS (rowPins); i++)
    {
    enablePinInterupt(rowPins [i]);
    }

  }

void enablePinInterupt(byte pin)
{
    *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
    PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
    PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the

}

// set pins as keypad library expects them
void reconfigurePins ()
  {
  byte i;
 
  for (i = 0; i < NUMITEMS (colPins); i++)
    {
    pinMode (colPins [i], OUTPUT);
    digitalWrite (colPins [i], HIGH);
    }

  for (i = 0; i < NUMITEMS (rowPins); i++)
    {
    pinMode (rowPins [i], INPUT_PULLUP);
    }

  }

void goToSleep ()
  {
  byte i;
   
  // set up to detect a keypress
  for (i = 0; i < NUMITEMS (colPins); i++)
    {
    pinMode (colPins [i], OUTPUT);
    digitalWrite (colPins [i], LOW); 
    } 

  for (i = 0; i < NUMITEMS (rowPins); i++)
    {
    pinMode (rowPins [i], INPUT_PULLUP);
    } 
   
   // now check no pins pressed (otherwise we wake on a key release)  *I don't understand why this is needed but the code does NOTHING with out this*
   for (i = 0; i < NUMITEMS (rowPins); i++)
    {
    if (digitalRead (rowPins [i]) == LOW)
       {
       reconfigurePins ();
       return;
       }
    } 
 
  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_enable();

//enable interrupt pins before going to sleep so you can wake up
   for (i = 0; i < NUMITEMS (rowPins); i++)
    {
    enablePinInterupt(rowPins [i]);
    }   
   
   sleep_mode();
 
 sleep_disable();
  reconfigurePins ();
   
  }
 
void loop ()
  {
   
   byte key =  kpd.getKey();

  // confirmation we woke - flash LED number of times
  // for the appropriate pin (eg. pin 1: one time)
  for (byte i = 0; i < (key - '0'); i++)
    {
    digitalWrite (ledPin, HIGH);
    delay (250);
    digitalWrite (ledPin, LOW);
    delay (250);
    }

  goToSleep();
   
  }

flyingblindonarocketcycle
 
Posts: 12
Joined: Fri Aug 02, 2019 6:41 pm

Re: wake from keypad interrupt but doesn't run reliably

by adafruit_support_mike on Thu Nov 28, 2019 3:06 am

Just to confirm, which ItsyBitsy are you using?

adafruit_support_mike
 
Posts: 59708
Joined: Thu Feb 11, 2010 2:51 pm

Re: wake from keypad interrupt but doesn't run reliably

by flyingblindonarocketcycle on Thu Nov 28, 2019 10:08 am

I have the 5v version.

flyingblindonarocketcycle
 
Posts: 12
Joined: Fri Aug 02, 2019 6:41 pm

Re: wake from keypad interrupt but doesn't run reliably

by adafruit_support_mike on Fri Nov 29, 2019 1:55 am

What micrcontroller?

adafruit_support_mike
 
Posts: 59708
Joined: Thu Feb 11, 2010 2:51 pm

Re: wake from keypad interrupt but doesn't run reliably

by flyingblindonarocketcycle on Fri Nov 29, 2019 7:36 am

I'm sorry but I don't know how to answer your question. I thought the ItsyBitsy 32u4 was the microcontroller.

https://learn.adafruit.com/introducting-itsy-bitsy-32u4/

flyingblindonarocketcycle
 
Posts: 12
Joined: Fri Aug 02, 2019 6:41 pm

Re: wake from keypad interrupt but doesn't run reliably

by adafruit_support_mike on Sat Nov 30, 2019 12:42 am

We have versions of the ItsyBitsy that use the ATmega32u4, the SAMD21, and the SAMD51. The last two are 32-bit microcontrollers whose interrupt systems are completely different from the '32u4. The code you posted uses the ATmega interrupt scheme, and I wanted to make sure you were using the appropriate device.

For the 32u4, the microcontroller has to wake up to handle the interrupt, so the most appropriate place to capture the signal that woke the CPU will be in the interrupt handler. If you store the value of the interrupt register, it will at least tell you which row caught the signal. Then you can scan the three columns in that row immediately after the microcontroller wakes up to locate the key that's been pressed.

adafruit_support_mike
 
Posts: 59708
Joined: Thu Feb 11, 2010 2:51 pm

Re: wake from keypad interrupt but doesn't run reliably

by flyingblindonarocketcycle on Sat Nov 30, 2019 9:33 am

I put a delay in the sleep routine that seems to have fixed it. After calling enablePinInterupt() I use delay(50) before calling sleep(). This seems to be important. Does the enablePinInterupt need a little time to finish before putting the chip to sleep? I thought the call would have to be complete before it returned and then called the sleep function.

Cheers
-fboarc

flyingblindonarocketcycle
 
Posts: 12
Joined: Fri Aug 02, 2019 6:41 pm

Re: wake from keypad interrupt but doesn't run reliably

by adafruit_support_mike on Tue Dec 03, 2019 2:41 am

Shutting off a CPU's clock can do lots of things that are hard to predict.

The ATmega32u4 uses registers to control chip functions, but it takes time for the peripheral circuits to respond to a register being set. Code that sets a register then returns is easy to write and executes quickly. Code that waits for the system to respond and verifies success before returning is harder to get right, and takes longer to run.

adafruit_support_mike
 
Posts: 59708
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.