2

I have this project of a "phone". It consists of:

  • Arduino DUE,
  • 4x4 Keypad,
  • SD Data shield,
  • a phone receiver detect (on/off)
  • an Amp and a Speaker.

In the beginning, after the phone receiver is being picked, I am playing a .wav file of an intro on how to choose a language. And this .wav should be interrupted when the user presses the 4th row of a keypad (Buttons A/B/C/D). I only need one pin as far as I know, in this setup - pin 38 (Column 4 pin). As I understand, there is no proper way to declare a keypad input pin as an interrupt on DUE. Or is it?

So my question - how to wire a keypad input pin as an interrupt? I have read about wiring with a diode. But most of the threads lack any specifics.

Can someone push me in the right direction? Cheers!

Code:

#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte interruptPin = 22;  // your interrupt pin

byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

int keyCounter = 0;

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

int goIntoKeys = 0;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;


void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

//for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], INPUT_PULLUP);
//for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

 pinMode(hookPinA, INPUT_PULLUP);
  
 attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

// EIFR |= bit(INTF0); // clear INT0 interrupt flag

 attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); //test interrupt with a regular button

 pinMode(38, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(38), interruptToggle, RISING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1


}


int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
    //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
      Serial.print("HOOK OFF ");
      Serial.println(hookOffState);
        interruptState = 0;
        state = STATE_IDLE;
               }
               else if (hookOffState == 0) {
      Serial.print("HOOK ON ");
      Serial.println(hookOffState);
               }
        break;
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
      Serial.print("interrupt IDLE ");
      Serial.println(interruptState);
               if (interruptState == 1) {
         buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
               }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
               else {
      playSound("intro.wav");
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      Serial.print("interrupt LISTEN KEY ");
      Serial.println(interruptState);
      if (isKeyPressed()) {
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else {
      Serial.print("interruptStateF ");
      Serial.println(interruptState);
               buttonBeep();
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle(){
 if (digitalRead(hookPinA) == 1) {
  hookOffState = 1;
 }
  else  {
      hookOffState = 0;
  }
}

void interruptToggle() {
    interruptState = 1;
}

void kalba() {
  Serial.println("Kalba? Language? Valoda? Yazik?");
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  //goIntoKeys = 1;
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}


void keyDial() {    // LCD displays the number dialed in 3 slots.
  keypresses[keyCounter] = 0x00;//null-byte
  keypresses[keyCounter] = key;

  if (key != NO_KEY)   {
    Serial.println(keypresses[keyCounter]);
  }
}

void buttonBeep(){
      for (int j = 0; j < 200; j++) {
        for (int i = 0; i < 200; i++)
          analogWrite(DAC0, i);
        for (int i = 200; i >= 0; i--)
          analogWrite(DAC0, i);
      }
}

void backgroundHumm() {
      for (int j = 0; j < 256; j++) {
        for (int i = 0; i < 256; i++)
          analogWrite(DAC0, j);
          for (int j = 256; j >= 0; j--) {
            for (int i = 256; i >= 0; i--)
          analogWrite(DAC0, j);
      }
  }
}
 
void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;  

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
  {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {  
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
   if ( interruptState ) break;
     else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

The schematics (if you can call it that) below: enter image description here

EDIT: @Damago solution works! I just wanted to share here the solution for future searches. What you need to do is to get the 4th column of 4x4 keypad to work as an interrupt properly: Set all row pins as output and column pins as input with pullup.

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

Set row pins to low:

for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);

Attach the 4th column pin as interrupt:

attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

And of course, fix the syntax overall (it was a bit messy :) )

Full sketch below:

#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;
int keyCounter = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW); 
 pinMode(hookPinA, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
 attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}


int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
    //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        interruptState = 0;
        state = STATE_IDLE;
                      }
               else if (hookOffState == 0) {
               }
        break;
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
               if (interruptState == 1) {
         isKeyPressed(); //get the key input
         buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
               }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
               else {
      playSound("intro.wav");
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle() {     //detect a telephone receiver to be removed
hookOffState = digitalRead(hookPinA);
}

void interruptToggle() {
    interruptState = 1;
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}


void buttonBeep(){
      for (int j = 0; j < 200; j++) {
        for (int i = 0; i < 200; i++)
          analogWrite(DAC0, i);
        for (int i = 200; i >= 0; i--)
          analogWrite(DAC0, i);
      }
}

void backgroundHumm() {
      for (int j = 0; j < 256; j++) {
        for (int i = 0; i < 256; i++)
          analogWrite(DAC0, j);
          for (int j = 256; j >= 0; j--) {
            for (int i = 256; i >= 0; i--)
          analogWrite(DAC0, j);
      }
  }
}
 
void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;  

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
  {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {  
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
   if ( interruptState ) break;
   else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}
4
  • 1
    why do you require to use an interrupt?
    – jsotola
    Sep 7, 2021 at 22:52
  • It´s a button with PULLDOWN resistor
    – SBF
    Sep 8, 2021 at 6:41
  • The button showed in the top right of a drawing is for testing purposes only - it's not supposed to be there in a final project. Sep 8, 2021 at 14:19
  • ideal would be to play the sound without blocking and and have the loop() check the button
    – Juraj
    Sep 8, 2021 at 18:19

2 Answers 2

3

There is a bit of a problem here. You cannot simply use one diode. There voltage is present on the keyboard pins only during getKey() function evaluation.

The keyboard works this way: when you call a myKeypad.getKey(); then arduino does the following:

  • changes the first column from input (high impedance) to output
  • outputs 0V voltage to first column,
  • scans all rows if they are 0V (normally they are pulled up - you know what pullup is).
  • if any key in this column is pressed then the column voltage of 0V is pulling down the corresponding row voltage. That is there is a connection between row and column.

Here is the exact code:

    pin_mode(columnPins[c],OUTPUT);
    pin_write(columnPins[c], LOW);  // Begin column pulse output.
    for (byte r=0; r<sizeKpd.rows; r++) {
        bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
    }
    // Set pin to high impedance input. Effectively ends column pulse.
    pin_write(columnPins[c],HIGH);
    pin_mode(columnPins[c],INPUT);

It is not impossible to do this this way but it would require either modifying keyboard or creating a bit more complicated circuit. However it really does not make real sense.

I would do this different way: I would completely skip interrupt here. You are checking for a flag set inside interrupt:

if ( interruptState ) break;

I would directly check here for the voltage on a specific pin. You have to (simply):

  • set row pin (46 as far as I understand from your code) to output, and set it to low,
  • set column pins (all of them) to input-pullup - as I understand {44, 42, 40, 38}
  • check if any of those pins is 'LOW', if yes - then break;

As far as I understand the library you don't even have to revert any pins back, the library re-initializes the pins correctly on every GetKey()

If for any reason the operation above takes too long you can shorten it using direct port manipulation as in https://forum.arduino.cc/t/arduino-due-how-to-direrct-port-access/251656 but note, that it is not as simple on Arduino Due as on AVR based ones.

3
  • Thanks! For a moment I thought I have solved the issue completely! But not quite yet.. I have made the described changes, except I need pin 38 to be output and LOW. And row pins as input_pullup. The interrupt works! Sadly, the keypad no longer receives inputs for pressed keys in this way. Sep 8, 2021 at 14:16
  • "As far as I understand the library you don't even have to revert any pins back, the library re-initializes the pins correctly on every GetKey()" I guess I need to revert these pins back? But then - how to receive interrupts after reverting? Sep 8, 2021 at 17:40
  • I think your solution is the closest to solving my problem. Now I can interrupt the .wav file, but the input won't register which language key I've pressed... So basically I need to press twice to achieve the goal. Edited code in the main question:) Sep 11, 2021 at 13:48
1

If you want to use interrupts, it requires a separate pin to detect the falling edge on column 4 (pin 38). In the following example, I used pin 28 for the column 4 interrupt. These can be connected together via a 1K resistor to protect against pin 28 inadvertently outputting low while the other is outputting high.

Pin 38 is pulled low during the call of myKeypad.getKey() thus triggering the ISR.

Working copies are made of the variables that are updated in the ISRs. This will require changes to the state machine to process column4Pressed obtained from the ISR.

const byte hookPinA = 23;  // your interrupt pin
const byte interruptPin = 22;  // your interrupt pin

const byte column4InterruptPin = 28;  // Column 4 interrupt pin connected to column4Pin via a wire link. Could add a 1K series resistor to protect against short circuit to ground if it were output low when pin 38 is output high.
const byte column4Pin = 38;  // Column 4 pin connected to column4InterruptPin via a wire link.

// States updated by ISR.
volatile byte isr_hookOffState = 0;
volatile byte isr_interruptState = 0;
volatile bool isr_column4Pressed = false;

// Working copies of ISR data.
byte hookOffState = 0;
byte interruptState = 0;
bool column4Pressed = false;

// Use a single byte for the state variable and initialise it to OFF.
enum class State : byte
{
    OFF = 0,
    IDLE = 1,
    LISTEN_KEY = 2,
    PLAYER = 3
} state = State::OFF;

void setup()
{
    pinMode(hookPinA, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

    pinMode(interruptPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); // test interrupt with a regular button

    pinMode(column4InterruptPin, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(column4InterruptPin), interruptColumn4, FALLING);  // Triggered by pulling column 4 low, e.g. digitalWrite(column4Pin, LOW) or within myKeypad.getKey().
}

void loop()
{
    // Get a fresh copy of the ISR data and reset the interrupt state flag atomically
    // by temporarily disabling interrupts.
    cli();
    hookOffState = isr_hookOffState;
    interruptState = isr_interruptState;
    column4Pressed = isr_column4Pressed;
    isr_interruptState = 0;  // Reset to detect next interrupt.
    isr_column4Pressed = false; // Reset to detect next interrupt.
    sei();

    // Alternative method to test whether any button in column 4 is pressed.
    // This is how to do it without using interrupts.
    /*
    pinMode(column4Pin, OUTPUT);
    digitalWrite(column4Pin, LOW);
    column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
    digitalWrite(column4Pin, HIGH);
    pinMode(column4Pin, INPUT);
    */

    // Process the working copies of the ISR data.
    // You will need to change the state machine logic to process column4Pressed obtained from the ISR.

    switch (state)
    {
    case State::OFF:
        break;
    case State::IDLE:
        break;
    case State::LISTEN_KEY:
        break;
    case State::PLAYER:
        break;
    }
}

void hookOffToggle()
{
    isr_hookOffState = digitalRead(hookPinA);
}

void interruptToggle()
{
    isr_interruptState = 1;
}

void interruptColumn4()
{
    // Test whether any button in column 4 is pressed.
    isr_column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
}

Here is the Wokwi simulation which uses an Arduino Mega and pin 2 for the column 4 interrupt. Note that there is no protection resistor between pins 2 and 38. The Wokwi simulator will create a Value Change Dump (VCD) file for viewing in your favourite trace analyser:

Screenshot of Wokwi simulation of keypad interrupt

Alternatively, if you don't want to use interrupts, you could pull column 4 (pin 38) low and test the row pins for a logic low. See the commented code in loop().

6
  • What are cli(); and sei();? They are not declared in this scope. Sep 8, 2021 at 14:45
  • They clear and set the global interrupt flag to disable and enable interrupts. Try noInterrupts() and interrupts() instead. interrupts
    – tim
    Sep 8, 2021 at 15:19
  • Thanks, I have implemented all the changes, sadly no luck - nothing is being received through isr_column4Pressed. How I've connected 38 and 28 pins: ibb.co/RP65rzQ Sep 8, 2021 at 17:38
  • @GoldenMoose, what value of resistor are you using to connect pin 38 to pin 28? From your image it is 560K which is far too large. The I/O internal pull-up resistor range is 20K to 50K. The protection resistor should be large enough to limit the current to less than 20 mA if inadvertently one pin is high while the other is low. It also has to be low enough to drop a small voltage in comparison to the voltage across the internal pull-up resistor to be recognised as a logic low when pin 38 is pulled low, i.e. a voltage divider.
    – tim
    Sep 9, 2021 at 11:17
  • I have used 3.6k reistor. I have also tried it with different resistors/no resistor. Same result... Sep 9, 2021 at 14:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.