Best way to to set up 4x4 keypad for project

helllo , I have a project that I working through & it was pointed out in my code that I will have to change my wireing & code to make it work . MY original code has the keypad in 2,3,4,5,6,7,8,9 , with a interrupt coming in on pin 11 . It was pointed out that I can only have interrupts on pins 2 & 3 . SO heres my question . I spent a evening looking around , reading & watching some youtubes & it looks like I have 3 options .

  1. Move the keypad up to use pins 4-11 & put my interrupt in pin 2 & my PWM pin in pin 3 .
  2. Use one of the setups where you only use 2 wires for the keypad by using some resistors .
  3. Use one of these PCF8574 PCF8574T IO Expansion Board I/O Expander I2C Evaluation Develop Module , heres a link to one . https://www.amazon.com/HiLetgo-PCF8574T-Expansion-Expander-Evaluation/dp/B01ICN5JB6 .
    Which one of these 3 would be my best choice ?
    The project is to make a keypad operated controller for a MC-2100 Treadmill motor controller . I'll attach my code here in case anyone wants to see where the issue is .
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // replaced #include <Adafruit_LiquidCrystal.h>

LiquidCrystal_I2C lcd(0x27,20,4);   // replaced Adafruit_LiquidCrystal lcd(0x27,20,4)
const int pwmPin = 10;
const int tachoPin = 11;
const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;
char keys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte pin_rows[ROW_NUM] = {9, 8, 7, 6};
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);
long rpm = 0;
int maxRpm = 1500;
int targetRpm = 0;

void setup() {
  lcd.init(); // replaced lcd.begin(20, 4)
  pinMode(pwmPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(tachoPin), countRpm, RISING);
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
  lcd.backlight(); // added turn on LCD backlight
  lcd.setCursor(0, 0); // added move LCD cursor to column 0 row 0 
  lcd.print(" Uno Tredmill"); // added display Uno Treadmill on LCD display
  delay(2000); // added wait 2 seconds before continuing 
}

void countRpm() {
  rpm++;
}

void loop() {
  char key = keypad.getKey();
  if (key) {
    int numKey = key - '0';
    if (numKey >= 0 && numKey <= 9) {
      targetRpm = targetRpm * 10 + numKey;
    } else if (key == 'A') {
      analogWrite(pwmPin, rpmToDutyCycle(targetRpm));
    } else if (key == 'B') {
      analogWrite(pwmPin, 0);
      targetRpm = 0;
    } else if (key == 'C') {
      targetRpm++;
      analogWrite(pwmPin, rpmToDutyCycle(targetRpm));
    } else if (key == 'D') {
      targetRpm--;
      analogWrite(pwmPin, rpmToDutyCycle(targetRpm));
    }
    targetRpm = constrain(targetRpm, 0, maxRpm);
  }
  rpm = 0;
  delay(1000);
  lcd.setCursor(0, 0);
  lcd.print("Target RPM: ");
  lcd.print(targetRpm);
  lcd.setCursor(0, 1);
  lcd.print("Current RPM: ");
  lcd.print(rpm * 60);
  lcd.setCursor(0, 2);
  lcd.print("Duty Cycle: ");
  lcd.print(rpmToDutyCycle(targetRpm));
  lcd.setCursor(0, 3);
  lcd.print("Press A to start, B to stop");
}

int rpmToDutyCycle(int rpm) {
  return constrain(map(rpm, 0, maxRpm, 0, 255) * 0.85, 0, 255);
}
//END OF CODE

Thank you 
animal12

know which controller You use, what do You say?

Mc-2100 & a UNO
animal12

On an UNO there are more digital pins, 10 - 12. 13 is connected to the onboard LED. Use one of them instead of pin 2 and 3.

For that matter, analog pins A0->A5 can also be used as digital, as 14-19. So you have options.

Thanks ,, both of ya . SO this is the quote from my other thread , " Only pins 2 and 3 support interrupts". Maybe I'm misunderstanding , so its ok to split the keypad between the analog 0-5 & Digital 5-7 ?
I have to see if any of my books explain how to do that . That would probably be the simplest approach I think ?
thanks
animal12
animal

Every one of the four columns can be attached to any digital i/o pin.

Every one of the four rows can be attached to any digital i/o pin.

Ppl tend to use four in a row twice or eight in a row. There is no need to do.

Forget the one that uses resistors.

Don't use any i/o expander if you have the real i/o pins to spare.

a7

That's absolutely not true. You just need to use pin change interrupts, which work on all GPIO pins of the 328P.

So you set the four column lines to input_pullup, make sure all are in the same port, and enable pin change interrupts on those four lines. Then you set the row lines to output low. When a key is pressed, your ISR sets a flag that indicated a key has been pressed, and turns off any further interrupts on those pins. Then when your loop detects the flag, it changes the row pins back to inputs, and calls getKey from the Keypad.h library, which tells you which key was pressed.

Pin change interrupts are not explicitly dealth with in the Arduino IDE like the "hardware" interrupts are, but they definitely do exist.

What "other thread"?

Post # 50 . I quoted the text in 6 in this current thread" Best way to set up 4x4 keypad for project "
thread .
thanks
animal12

Thank you folks , I changed the code & it compiled fine . Hopefully in the next few days I will be able to make a test setup & see how things go before I hook it up to my MC-2100 motor Controller . I thought I had more than one MC-2100 controller But it looks like I only have one so I don't want to screw it up . I have some L2893D chips , so I should be able to make a test setup with one of those & a small motor . I will need a 20hz pwn output for the MC-2100 , I don't see that in the code , so I'm not as far as I thought .
thank you very much folks .
animal12

@animal12 Including pins 14->19. Though labelled on the board as A0->A5, they can also be used as digital pins using those numbers.
You have many options.

Sure. But for most new users, using a label that's context-correct helps. but you're right, those are the labels on the pins, which also helps. You and me, well...