Using a matrix keyboard with TcMenu is straightforward, we use the IoAbstraction Keyboard Manager component to handle the keyboard, along with a custom listener for tcMenu that feeds the menu manager with appropriate events upon key presses. This library allows you to connect your keyboard either using Arduino pins, or any supported IoAbstraction such as the I2C PCF8574 or MCP23017.
Before proceeding, it is recommended that you wire up your keyboard in accordance with the above linked keyboard manager page and any documentation that came with the keyboard. Before proceeding, fully test the keyboard using the packaged IoAbstraction example sketch.
Once tested you can either set up the matrix keyboard automatically using tcMenu Designer, or manually if you need custom control over how it is set up.
From code generator window click on the input plugin and select the following:
Once selected the plugin will give various options, you can choose if you want the keyboard support along with a rotary encoder. We’ll now discuss the various configuration options:
These two character codes will be used to simulate next and back, giving a similar feel to up/down buttons. They can be set to -1 for none.
These are mandatory, the “enter” key simulates activating editing and moving into sub menus etc. The del key resets to previous menus and holding it goes back to root.
Defines the arrangement of keys in relation to rows and columns. There are a few standard layouts that the designer supports, choose the layout for your keyboard.
These must be defined, they are the pins on which the rows and columns are connected, and the row pins MUST be output capable. If you use interrupt mode, the column pins must be capable of raising interrupts, as there will be no polling.
Here you can indicate that the wires from the keyboard are connected directly to device pins, or are wired through an I2C device, or other supported type of extended device.
These define the time before repeat key starts, and then the interval between each repeat. These values are specified in milliseconds.
If set to true, the keyboard manager will not poll, and will rely on any change in the button state raising an interrupt. Therefore, the column pins must be able to raise CHANGE interrupts. Without this option, the class will poll every 50 milliseconds for changes.
It is possible to set up a rotary encoder alongside the keyboard support, to do this simply enable the rotary encoder by ticking “Rotary encoder needed”. Once enabled, the properties for the encoder will be enabled.
Here we define the pins on which the encoder is connected, for the A and B pins and also the center button (select). Depending on wire length, no external pull-ups may be needed.
Here you can indicate that the wires from the encoder are connected directly to device pins, or are wired through an I2C device, or other supported type of extended device.
The switches
class controls all encoders and buttons not on the keyboard, it can either poll or use interrupts, here you can define that.
There are many types of encoder, most of the cheap encoders I use for testing are full cycle, and I’ve made that the default. However, if your encoder is otherwise, select the other option.
Include the required header at the top of your sketch:
#include <tcMenuKeyboard.h>
Globally declare the variables required at the top of the sketch:
// Either manually declare a keyboard layout or use one of the standard ones.
MAKE_KEYBOARD_LAYOUT_3X4(keyboardLayout)
// or MAKE_KEYBOARD_LAYOUT_4X4(keyboardLayout)
// Now declare the keyboard manager
MatrixKeyboardManager keyboard;
// Lastly, we declare the tcMenu keyboard listener, that listens to keypresses
// and performs the right actions in the menu. If this one doesn't do the right
// thing, you can write your own / extend this one.
MenuEditingKeyListener menuKeyListener;
Then create a setupKeyboard
function that will initialise the keyboard:
void setupKeyboard() {
// set up the pin mappings for the rows and columns.
keyboardLayout.setRowPin(0, 22);
keyboardLayout.setRowPin(1, 23);
keyboardLayout.setRowPin(2, 24);
keyboardLayout.setRowPin(3, 25);
keyboardLayout.setColPin(0, 26);
keyboardLayout.setColPin(1, 27);
keyboardLayout.setColPin(2, 28);
// initialise telling the library it's wired on Arduino pins, with given layout
// and listener, you could change the IOdevice to an I2C one for example.
keyboard.initialise(ioUsingArduino(), &keyboardLayout, &menuKeyListener);
//keyboard.initialise(ioUsingArduino(), &keyboardLayout, &menuKeyListener, interruptMode);
// repeat the pressed key after 850ms every 350ms
keyboard.setRepeatKeyMillis(850, 350);
}
Then at the end of setup, call the function you created above:
void setup() {
// ... your other setup stuff ...
setupKeyboard();
}
That’s it, your menu will be controllable by the keyboard. We’ll now discuss how it works: