Keyboard Code

Hello I have a question concerning a project I'm making. I'm trying to make a custom keypad. So I wrote some code and wanted to ask if it makes sense so far. And what's the best way to map custom keys to keycombos or hotkeys?

#define col1 2
#define col2 3
#define col3 4
#define row1 5
#define row2 6
#define row3 7
#define row4 8
int keys[3][4];
int row;
int column;

void setup() {
 pinMode(col1, OUTPUT);
 pinMode(col2, OUTPUT);
 pinMode(col3, OUTPUT);
 pinMode(row1, INPUT_PULLUP);
 pinMode(row2, INPUT_PULLUP);
 pinMode(row3, INPUT_PULLUP);
 pinMode(row4, INPUT_PULLUP);
 row = 0;
 column = 0;
}

void loop() {
 for (row = 0; row < 3; row++)
 {
   digitalWrite(row, HIGH);
   for (column = 0; column < 4; column++)
   {
     keys[row][column] = digitalRead(column);
   }
   digitalWrite(row, LOW);
 }
 
}

Please read the advicing topics telling "Hoe to use the Forum", "Hoe to attach code" etc. Attach wiring diagram.
Runt the code and tell what happends.

Railroader:
Please read the advicing topics telling "Hoe to use the Forum", "Hoe to attach code" etc. Attach wiring diagram.
Runt the code and tell what happends.

Well I think I attached the code the right way. And I don't have a wiring diagram but my question is only about code. I'm using an arduino pro micro.
The code compiles properly. But is my code efficient? And I don't know how to use the stuff I programmed so far to make working keys...
Maybe there is an older thread about this?

No, that's not the way to attach code. Read the advice!
Your code is reading hardware so wiring means a lot. I don't want to guess that You have made the same mistake as many new members.
Compiles…… Even shit compiles. The compiler has no idea of what You want the code to do. so forget that.
Find out what You what stuff You've got and want You want to do with it. Many things can be used as anchor for the boat but this has too less of weight.

Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".
OR
http://forum.arduino.cc/index.php/topic,148850.0.html.

Have you tried the keypad library?
https://playground.arduino.cc/Code/Keypad/

This lets you allocate symbols to the keys you detect from the matrix.

Tom... :slight_smile:

Railroader:
Please read the advicing topics telling "Hoe to use the Forum", "Hoe to attach code" etc. Attach wiring diagram.
Runt the code and tell what happends.

Bad night at home trying to blot out Covid? :cold_sweat:

Railroader:
No, that's not the way to attach code. Read the advice!
Your code is reading hardware so wiring means a lot. I don't want to guess that You have made the same mistake as many new members.
Compiles…… Even shit compiles. The compiler has no idea of what You want the code to do. so forget that.
Find out what You what stuff You've got and want You want to do with it. Many things can be used as anchor for the boat but this has too less of weight.

I attached my code the way it says in the advice.

herrybertpotter:
I attached my code the way it says in the advice.

Thank you. usually any updates you should be putting in a new post.
Have you looked at the keypad library?
Tom... :slight_smile:

TomGeorge:
Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".
OR
http://forum.arduino.cc/index.php/topic,148850.0.html.

Have you tried the keypad library?
Arduino Playground - Keypad Library

This lets you allocate symbols to the keys you detect from the matrix.

Tom... :slight_smile:

Ok thank you I'll try using the keypad library.

herrybertpotter:
The code compiles properly. But is my code efficient?

Possibly. You don't necessarily need an array; I don't think that you need it. And initialising row and column to zero in setup() is not needed as global variables are initialised to zero by default and you initialise them again in the for loops. The use of int is also not efficient. Bytes for row and column will do as their values are always less than 256 and always positive.

As TomGeorge mentioned above, there is a Keypad library.

herrybertpotter:
And I don't know how to use the stuff I programmed so far to make working keys...

The below is based on your original code.

You need a two-dimensional array to map your key presses to keys that you will send to a PC. You will also need to include the Keyboard library which allows you to use the pro Micro as a HID.

# include <Keyboard.h>

byte keyMap[3][4] =
{
  {'a', 'b', 'c', 'd'},
  {'0', '1', '2', '3'},
  {'w', 'x', 'y', 'z'},
};

const byte safetyPin = A0;

...
...

void setup()
{
  ...
  ...
  
  pinMode(safetyPin, INPUT_PULLUP);
}

void loop()
{
  // only do anything when the safetyPin is LOW
  if(digitalRead(safetyPin) == HIGH)
  {
    return;
  }


  for (row = 0; row < 3; row++)
  {
    digitalWrite(row, HIGH);
    for (column = 0; column < 4; column++)
    {
      Keyboard.print(keyMap[row][column]);
    }
    digitalWrite(row, LOW);
  }
}

Code not compiled or tested.

The safetyPin mechanism is there to prevent code mistakes from spamming the PC with characters; you would not be the first one that comes for help for this reason. In the above, you will have to wire A0 to ground to complete the loop().

Be very careful when using Keyboard.press(); don't forget to use Keyboard.release() or Keyboard.releaseAll() after those. Note that the PC will remember what was pressed till you release it, even if you disconnect the Micro Pro.

This code is clearly wrong. You are writing to pins 0 through 2 and reading from pins 0 through 3! You should definitely switch to using the Keypad library. Start with the HelloKeypad example.

void loop() {
 for (row = 0; row < 3; row++)
 {
   digitalWrite(row, HIGH);
   for (column = 0; column < 4; column++)
   {
     keys[row][column] = digitalRead(column);
   }
   digitalWrite(row, LOW);
 }
}

johnwasser:
This code is clearly wrong. You are writing to pins 0 through 2 and reading from pins 0 through 3! You should definitely switch to using the Keypad library. Start with the HelloKeypad example.

void loop() {

for (row = 0; row < 3; row++)
{
  digitalWrite(row, HIGH);
  for (column = 0; column < 4; column++)
  {
    keys[row][column] = digitalRead(column);
  }
  digitalWrite(row, LOW);
}
}

You're right i did not notice that thank you. I want to use pins 2-4 as outputs and pins 5-8 as input. Also should I use pull-down resistors instead of pull-ups? This way I´m not sure if it works. So would this work?

//pins 5-8 as input-pulldowns
void loop() {
 for (row = 0; row < 3; row++)
 {
   digitalWrite(row+2, HIGH);
   for (column = 0; column < 4; column++)
   {
     keys[row][column] = digitalRead(column+5);
   }
   digitalWrite(row+2, LOW);
 }
}

sterretje:
Possibly. You don't necessarily need an array; I don't think that you need it. And initialising row and column to zero in setup() is not needed as global variables are initialised to zero by default and you initialise them again in the for loops. The use of int is also not efficient. Bytes for row and column will do as their values are always less than 256 and always positive.

As TomGeorge mentioned above, there is a Keypad library.

The below is based on your original code.

You need a two-dimensional array to map your key presses to keys that you will send to a PC. You will also need to include the Keyboard library which allows you to use the pro Micro as a HID.

# include <Keyboard.h>

byte keyMap[3][4] =
{
 {'a', 'b', 'c', 'd'},
 {'0', '1', '2', '3'},
 {'w', 'x', 'y', 'z'},
};

const byte safetyPin = A0;

...
...

void setup()
{
 ...
 ...
 
 pinMode(safetyPin, INPUT_PULLUP);
}

void loop()
{
 // only do anything when the safetyPin is LOW
 if(digitalRead(safetyPin) == HIGH)
 {
   return;
 }

for (row = 0; row < 3; row++)
 {
   digitalWrite(row, HIGH);
   for (column = 0; column < 4; column++)
   {
     Keyboard.print(keyMap[row][column]);
   }
   digitalWrite(row, LOW);
 }
}



Code not compiled or tested.

The safetyPin mechanism is there to prevent code mistakes from spamming the PC with characters; you would not be the first one that comes for help for this reason. In the above, you will have to wire A0 to ground to complete the loop().

Be very careful when using Keyboard.press(); don't forget to use Keyboard.release() or Keyboard.releaseAll() after those. Note that the PC will remember what was pressed till you release it, even if you disconnect the Micro Pro.

Ok thank you :slight_smile:

I could not get your code working (in a short time) as intended so here is something based on the keypad library.

Before you use below, start simple with an adjusted version of the custom keypad code of the Keypad library and serial prints so you know which key is which.

Next study below and adjust to you needs; I've tried to demonstrate the different options (normal print, macros, special keys).

Code tested on a Leonardo with 3x4 keypad.

/*
  Demo code of Keyboard.press and Keyboard.print including use with macros.
  Based on the custom keypad code, uses Keyboard.press and Keyboard.print
  
  Macro keys are 1, 2 and 3; tailored to Notepad++
  Two special keys, <esc> and left <ctrl>; all supported keys can be found in  Keyboard.h
  The other keys of the keypad just send the key

  Safety:
  A0 needs to be connected to ground else keypress / print will not be send
  If not, all hanging keys will be released and no keypress / print will be send to the PC
*/

#include <Keypad.h>
#include <Keyboard.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns
//define the cymbols on the buttons of the keypads
char keyMap[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {(char)KEY_ESC, 'a', (char)KEY_LEFT_CTRL}
};
byte rowPins[ROWS] = {4, 5, 6, 7};  //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 9, 10};    //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);

const byte safetyPin = A0;
const byte ledPin = LED_BUILTIN;


void setup()
{
  pinMode(safetyPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  // safety net
  if (digitalRead(safetyPin) == HIGH)
  {
    // indicate safety activated
    digitalWrite(ledPin, HIGH);
    // release all keys that might be hanging
    Keyboard.releaseAll();
    return;
  }

  digitalWrite(ledPin, LOW);

  byte key = customKeypad.getKey();

  // if a key is pressed
  if (key != NO_KEY)
  {
    // test for normal keys
    if (key < 0x80)
    {
      switch (key)
      {
        // 'delete all' macro
        case '1':
          Keyboard.press(KEY_RIGHT_CTRL);
          Keyboard.press('a');
          Keyboard.release(KEY_RIGHT_CTRL);
          Keyboard.press(KEY_DELETE);
          break;
        // 'undo' macro
        case '2':
          Keyboard.press(KEY_RIGHT_CTRL);
          Keyboard.press('z');
          Keyboard.releaseAll();          // or Keyboard.release(KEY_RIGHT_CTRL)
          break;
        // "hello world" macro
        case '3':
          Keyboard.print("Hello world");
          break;
        default:
          Keyboard.press(key);
          break;
      }
    }
    else
    {
      // keys defined in Keyboard.h will directly be handled
      Keyboard.press(key);
    }
  }
}

Keypad used:

sterretje:
I could not get your code working (in a short time) as intended so here is something based on the keypad library.

Before you use below, start simple with an adjusted version of the custom keypad code of the Keypad library and serial prints so you know which key is which.

Next study below and adjust to you needs; I've tried to demonstrate the different options (normal print, macros, special keys).

Code tested on a Leonardo with 3x4 keypad.

/*

Demo code of Keyboard.press and Keyboard.print including use with macros.
  Based on the custom keypad code, uses Keyboard.press and Keyboard.print
 
  Macro keys are 1, 2 and 3; tailored to Notepad++
  Two special keys, and left ; all supported keys can be found in  Keyboard.h
  The other keys of the keypad just send the key

Safety:
  A0 needs to be connected to ground else keypress / print will not be send
  If not, all hanging keys will be released and no keypress / print will be send to the PC
*/

#include <Keypad.h>
#include <Keyboard.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns
//define the cymbols on the buttons of the keypads
char keyMap[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {(char)KEY_ESC, 'a', (char)KEY_LEFT_CTRL}
};
byte rowPins[ROWS] = {4, 5, 6, 7};  //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 9, 10};    //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);

const byte safetyPin = A0;
const byte ledPin = LED_BUILTIN;

void setup()
{
  pinMode(safetyPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop()
{
  // safety net
  if (digitalRead(safetyPin) == HIGH)
  {
    // indicate safety activated
    digitalWrite(ledPin, HIGH);
    // release all keys that might be hanging
    Keyboard.releaseAll();
    return;
  }

digitalWrite(ledPin, LOW);

byte key = customKeypad.getKey();

// if a key is pressed
  if (key != NO_KEY)
  {
    // test for normal keys
    if (key < 0x80)
    {
      switch (key)
      {
        // 'delete all' macro
        case '1':
          Keyboard.press(KEY_RIGHT_CTRL);
          Keyboard.press('a');
          Keyboard.release(KEY_RIGHT_CTRL);
          Keyboard.press(KEY_DELETE);
          break;
        // 'undo' macro
        case '2':
          Keyboard.press(KEY_RIGHT_CTRL);
          Keyboard.press('z');
          Keyboard.releaseAll();          // or Keyboard.release(KEY_RIGHT_CTRL)
          break;
        // "hello world" macro
        case '3':
          Keyboard.print("Hello world");
          break;
        default:
          Keyboard.press(key);
          break;
      }
    }
    else
    {
      // keys defined in Keyboard.h will directly be handled
      Keyboard.press(key);
    }
  }
}




Keypad used:
![](https://hobbytronics.co.za/content/images/thumbs/0005509_sealed-membrane-4x3-button-key-pad-with-sticker_300.jpeg)

Ok thank ypu I´ll try that out