Matrix keypad and interrupts

Hi all,

looking for a quick advise on the following topic.

I have a Mega controlling a thermal solar unit. Lots of relays, temperature sensors, timers, several displays on it, and a keypad to control & modify things.
The whole thing works well in its current incarnation including the keypad. However because the keypad poll gets slower with other stuff the mc needs to do with more and more things I am adding the pad became less and less responsive.

I could add a diode chain and tie it to a single interrupt pin, but because the 4 column pins are already on interrupt capable pins I thought I could use those as direct interrupts.

Hardware:
Arduino Mega
4x4 keypad: http://img04.taobaocdn.com/imgextra/i4/44390641/T201uyXeBaXXXXXXXX_!!44390641.jpg

With the code below it works on the 1st keypress perfectly, subsequent keystrokes produce an interrupt but return an empty character, and after some further 5 to 10 strikes it reads it again correctly (once).

#include <PWM.h>
#include <Shifter.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <EEPROM.h>
#include "EEPROMAnything.h"
#include <PinChangeInt.h>
#include <Average.h>
#include <MemoryFree.h>
#include <avr/wdt.h>//watchdog! resets ardo if hangs DOES NOT WORK ON MEGA with original bootloader
#include <SPI.h>//SD Modul Com
#include <SD.h>//SD Funktionen
#include <Wire.h>//LCD
#include <LiquidCrystal_I2C.h>//LCD
#include <OneWire.h>//Tempsens
#include <DallasTemperature.h>//Tempsens
#include <DS1307RTC_drift.h>//Clock
#include <Time_drift.h>//Uhrzeit
#include <Keypad.h>
...
void setup() {
byte rowPins[ROWS] = {35, 34, 33, 32}; //connect to the row pinouts of the keypad 
byte colPins[COLS] = {A10, A11, A8, A9}; //connect to the column pinouts of the keypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);//initialize an instance of class NewKeypad
...
  //interrupt chrck - col - input high; 
  pinMode(A10, INPUT_PULLUP);
  pinMode(A11, INPUT_PULLUP);
  pinMode(A8, INPUT_PULLUP);
  pinMode(A9, INPUT_PULLUP);
  
  //row output LOW
  pinMode(35, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(32, OUTPUT);
  digitalWrite (35, LOW);
  digitalWrite (34, LOW);
  digitalWrite (33, LOW);
  digitalWrite (32, LOW);
  
  //interrupt col pins
  PCintPort::attachInterrupt(12, &key_inter, CHANGE);//another interrupt - unrelated to keypad
  PCintPort::attachInterrupt(A10, &key_poll, FALLING);
  PCintPort::attachInterrupt(A11, &key_poll, FALLING);
  PCintPort::attachInterrupt(A8, &key_poll, FALLING);
  PCintPort::attachInterrupt(A9, &key_poll, FALLING);

...

void key_poll()
{
  PCintPort::detachInterrupt(A10);
  PCintPort::detachInterrupt(A11);
  PCintPort::detachInterrupt(A8);
  PCintPort::detachInterrupt(A9);

  customKey = customKeypad.getKey();
  Serial1.println(customKey);//debug
  pinMode(35, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(32, OUTPUT);
  digitalWrite (35, LOW);
  digitalWrite (34, LOW);
  digitalWrite (33, LOW);
  digitalWrite (32, LOW);
  pinMode(A10, INPUT_PULLUP);//keypad
  pinMode(A11, INPUT_PULLUP);
  pinMode(A8, INPUT_PULLUP);
  pinMode(A9, INPUT_PULLUP);
  delayMicroseconds(15000);
  PCintPort::attachInterrupt(A10, &key_poll, FALLING);
  PCintPort::attachInterrupt(A11, &key_poll, FALLING);
  PCintPort::attachInterrupt(A8, &key_poll, FALLING);
  PCintPort::attachInterrupt(A9, &key_poll, FALLING);
  return;
}

I tried "waitkey()", delays, and then something like this in the interrupt routine:

// int counter = 0;
  //while (customKey == NO_KEY || counter < 1000)
  //{
    //customKey = customKeypad.getKey();
    //counter = counter + 1;
    //delayMicroseconds(1);
  //}

but this does freeze the µ-c.
I would now go forward and throw out the keypad library and see if I can get a simple scanning algorithm together to detect keypresses unless someone tells me I am missing something else ...

Best regards,

-Thomas

Connecting 4 diodes the the columns then to an interrupt pin will make things more responsibly.

Yes - this would have been the solution in the first place.
However I wanted to use the existing hardware therefore used the 4 existing interrupt pins.

Best,

-T

I threw out the keypad library and did the scanning algorith manually - works perfectly.

Basically just 4 blocks of 4 if's reading the rows while one of the 4 cols is low.

-T

Does this tread still hold true?

I'm trying to build a simliar IoT device with a ESP8266 which has less inputs. I Was going to do the 3x4 keyboard via I2C and then just poll it. Seems better than an interrupt?

You can use a pcf8574 i2c chip to scan a 4x4 keypad. The chip has an interrupt pin that you can connect to the mcu so you do not have to continually poll to detect keypresses. To use it this way, you would initially set up the 4 column outputs as high and the 4 row outputs as low. When a key is pressed, one of the column outputs would be pulled low, causing an interrupt. The mcu would then read back the data and detect which column the pressed key is in. It would then write data back to the pcf chip to make the columns low and the rows high. A second read of the data would allow the row of the pressed key to be determined.