Keypad: changing button commands with a lever switch

Hello,
I'm working with a Leonardo and a 4x4 flat keypad where each button is working as a macro (e.g. CTRL - V).
I'm using the Keypad library by Stanley and Brevig and it already contains a sketch that works perfectly, but now I need to expand the set of macros and I would like to use a "second set" by putting a physical switch/toggle (the one with a lever) that is directly wired to the board GND and pin10. The board is connected to the PC through a USB cable.

The library contains a sketch (DynamicKeypad) that does exactly this, but it relies only on the keypad itself: the set of macros is switched by holding a key on the pad. The integrated led shows which set is active. But I have my board inside a box and I would prefer to have a switch that I can use to toggle between the two sets.

Even though I'm not a programmer, I was able to put together a code that should do this, and it works when the switch is on the "OFF" position. When I turn it ON, however, the results are not consistent. Let's say that set A has letters, and set B has numbers. A is ON and B is OFF. When the switch is OFF, I only have numbers, but when I turn it ON, letters are mixed up randomly with numbers (I tried pressing the buttons at different intervals, and even by closing the circuit by just having the two wires (pin10 and GND) touch directly (which I don't know if it's a big no no), and used different cables and pins).

This is the code (the sets are simplified, using letters and numbers instead of macros). Any suggestions?

// ----------------------------
// Standard Libraries
// ----------------------------

#include "Keyboard.h"
// Library with a lot of the HID definitions and methods
// Can be useful to take a look at it see whats available
// https://github.com/arduino-libraries/Keyboard/blob/master/src/Keyboard.h

// ----------------------------
// Additional Libraries - each one of these will need to be installed.
// ----------------------------

#include <Keypad.h>
// This library is for interfacing with the 4x4 Matrix
//
// Can be installed from the library manager, search for "keypad"
// and install the one by Mark Stanley and Alexander Brevig
// https://playground.arduino.cc/Code/Keypad/

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

// the library will return the character inside this array
// when the appropriate button is pressed.
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'},
};

byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int buttonState = 0;

void setup() {
  Serial.begin(9600);
  Keyboard.begin();
  pinMode(10, INPUT); //is this necessary?
}

void loop() {
  buttonState = digitalRead(10);
  if (buttonState == HIGH) {
    a_keypad();
  }
  else if (buttonState == LOW) {
    b_keypad();
  }
}

void a_keypad() {
  char key = keypad.getKey();
  if (key) {
    Serial.println(key);
    switch (key) {
      case '1':
        Keyboard.print("a");
        break;
      case '2':
        Keyboard.print("b");
        break;
      case '3':
        Keyboard.print("c");
        break;
      case '4':
        Keyboard.print("d");
        break;
      case '5':
        Keyboard.print("e");
        break;
      case '6':
        Keyboard.print("f");
        break;
      case '7':
        Keyboard.print("g");
        break;
      case '8':
        Keyboard.print("h");
        break;
      case '9':
        Keyboard.print("i");
        break;
      case '0':
        Keyboard.print("j");
        break;
      case '*':
        Keyboard.print("k");
        break;
      case '#':
        Keyboard.print("l");
        break;
      case 'A':

        break;
      case 'B':

        break;
      case 'C':

        break;
      case 'D':

        break;
    }

    delay(100);
    Keyboard.releaseAll(); // this releases the buttons
  }
}

void b_keypad() {
  char key = keypad.getKey();
  if (key) {
    Serial.println(key);
    switch (key) {
      case '1':
        Keyboard.print("1");
        break;
      case '2':
        Keyboard.print("2");
        break;
      case '3':
        Keyboard.print("3");
        break;
      case '4':
        Keyboard.print("4");
        break;
      case '5':
        Keyboard.print("5");
        break;
      case '6':
        Keyboard.print("6");
        break;
      case '7':
        Keyboard.print("7");
        break;
      case '8':
        Keyboard.print("8");
        break;
      case '9':
        Keyboard.print("9");
        break;
      case '0':
        Keyboard.print("0");
        break;
      case '*':
        Keyboard.print("'");
        break;
      case '#':
        Keyboard.print("#");
        break;
      case 'A':

        break;
      case 'B':

        break;
      case 'C':

        break;
      case 'D':

        break;
    }

    delay(100);
    Keyboard.releaseAll(); // this releases the buttons
  }
}

Have you tested the switch on pin 10 separately, to make sure it works? How is it wired?

By the way, have you ever heard of the "principle of exclusion"? It means roughly, if something is true, it can not be false. :slight_smile:

Since an output is digital, if it is HIGH it cannot be simultaneously LOW. So

  if (buttonState == HIGH) {
    a_keypad();
  }
  else if (buttonState == LOW) {
    b_keypad();
  }

is really just

  if (buttonState == HIGH) {
    a_keypad();
  }
  else {
    b_keypad();
  }

Also, why do you have 100ms delay() statements in there? It shouldn't be necessary to debounce the switches, as the keypad library should do that.

Thanks. The second "if" was probably left there after I tried something else and I forgot to remove it afterwards.
The delay() was included in a sketch I found on the net that I used for this project.

Regarding the connection, I'm using a 3 pins switch (see attachment). The GND wire is soldered to the central pin and the pin10 wire is soldered to one of the lateral pins. The wires go into the board directly (the wires end with preinstalled plugs).

To test the logic of the sketch, I've tried a simple Blink sketch with the same structure (although simplified):

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(10, INPUT);
}

// the loop function runs over and over again forever
void loop() {
  if (digitalRead(10) == HIGH) {
  digitalWrite(LED_BUILTIN, HIGH);
  }
  else {
  digitalWrite(LED_BUILTIN, LOW);
  }                  
}

And it's probably some bad wiring (or a bad switch) because I'm seeing a sliiiight flickering on the led.
I'll try changing the switch and wires (should I add something, or the direct wiring is fine?)

Removing "bad code" as part of the equation should help me find the issue here, so if you don't see any other problem with the code, I can focus on the hardware :slight_smile:

Thanks again!

change  pinMode(10, INPUT);
to

  pinMode(10, INPUT_PULLUP);

Cheers!

Looks like it works just by adding INPUT_PULLUP as you suggested, even with the old wiring!
Again, thanks!!

Yes, it's because I/O pins configured for INPUT are "floating", i.e. such a high resistance that the voltage on them is randomly susceptible to nearby electrostatic fields, and has no definite default state. The internal pull up resistor provides a reference default voltage equal to the supply voltage, so that an unconnected pin will read, HIGH.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.