Programmable Macropad V2

54K667128

Intro: Programmable Macropad V2

In this Instructable I will walk through how I build my new and improved Macropad. I made one a while back and it has always had some things I would like to improve on it. The main one being the location of the state LEDs. When redesigning the case I figured why not take a look at the whole thing and see if I can do a better job. So I did.

This macropad is capable of 10 buttons per layout and up to 16 layouts in total. If you can do it I'll be impressed. It also has a click rotary encoder, that has a fixed function, volume and play/pause.

In this version I am sticking with an Arduino Pro Micro, and adding another button on. While I was reading I also decided to use diodes just like a really keyboard. This also makes coding a bit easier as a lot of libraries already exist for this.

I won't spend a lot of time on why I made the changes I did, but I'll touch on it here and there throughout. Honestly they both work great. I just wanted a new challenge.

STEP 1: Case

As with any project I like to get the case started first. Especially when printing one, as it takes a while and I only need to slice and load the file and the printer does the rest. Here is a link to the case that I designed for this project: https://www.thingiverse.com/thing:4792978

This project does necessitate the at least the top of the case being done before moving on as all of the parts need to be clipped into the top and then soldered together.

You don't need to print a case for this. You can use what ever you have access too.

For this case design I would recommend checking the dimensions on your keys, LEDs, and encoder before printing the whole thing.

STEP 2: Assemble the Top

The begins by installing all the switches into the plate. The best fit on the switches is a bit tight, that way you can remove any key caps and the switch won't pull out.

After adding the switches bend the ground leg of the LED down at a right angle and place them into their spots at the bottom of the plate with the bend leg on the outside.

If your encoder came with header pins, like mine did, you will need to remove them before you can put the encoder in place as the pins run into the switches. To do that use your snips to clip the plastic that holds them all together and then remove them one at a time using a soldering iron to heat the pin and solder and a pair of pliers to pull the pin out. Once the pins have been removed you can put the encoder in place and attach it. It may also be easier to wait until you have soldered the wires onto the encoder before putting it in place.

STEP 3: Soldering

Soldering this is the hardest part.

Each of the switches needs a diode and a wire. We are basically making a grid wires with a switch and diode at each intersection. The diodes help in case more than one switch is pressed at a time. I've attached a circuit layout that I used (or pretty close). The pins aren't hugely important, as they can easily be swapped in the code later. Make sure that you avoid pin 0 and 1 (RX and TX) as I think they are used to communicate with the computer; tying into them might be weird.

There are 3 pins that are important. They are the pins from the encoder. The encoder will work best if the moment tracking pins connected to interrupt capable pins on the Micro. On the Pro Micro attached to pin 2 and 3. They are important as they track the movement of the encoder. If you have the same encoder I do they are the DT and CLK pins. The encoder I have also needs +5v to work, so the power needs to run from the RAW pin. The RAW pin exposes the +5v coming from the USB port. All other pins will run at 3.3v.

STEP 4: Code

Now the fun part. For this version I am breaking the code down into a lot more functions. Functions are useful as the make it a lot easier to keep each section of your code small. By making each section smaller, its easier to follow.

The main thing to remember with functions is that each function should only do 1 thing. The other thing to remember is why write code many times when you can wrap it in a function and use it a bunch of times.

I've attached the code below and if you are interested I have an in depth walk through in the next step.

For the actual key functions I've left a few in Layout2() for you to look at. With this code always remember when sending key strokes make sure that you release any keys you press. Some of the functions like .send() do release the keys they press but .press() does not. Use .releaseAll() to release pressed keys.

You can change the pin numbers at the top to what you have used.

#include <Keypad.h>
#include <Encoder.h>
#include <Bounce2.h>
#include "HID-Project.h"
//Keypad buttons
int R1 = 6;
int R2 = 5;
int R3 = 21;
int R4 = 20;
int C1 = 7;
int C2 = 8;
int C3 = 9;
const byte ROWS = 4;
const byte COLS = 3;
char keys[COLS][ROWS] = {
{'X','7','4','1'},
{'*','8','5','2'},
{'-','9','6','3'}
};
byte rowPins[ROWS] = {R1, R2, R3, R4};
byte colPins[COLS] = {C1, C2, C3};
Keypad kpd = Keypad( makeKeymap(keys), colPins, rowPins, COLS, ROWS);

//State LED pins
int S1 = 15;
int S2 = 14;
int S3 = 16;
int S4 = 10;
const int numStates = 4;
const int States[numStates] = {S1, S2, S3, S4};
int currentState = 0;

int lastDebounceTime = 0;
const int debounceTime = 50;

//Encoder
int SW = 19;
int DT = 2;
int CLK = 3;
Encoder volumeKnob(DT,CLK);
Bounce encoderButton = Bounce(SW,10);
int timeLimit = 500;
long oldPosition = -999;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);

for (int i = 0; i < numStates; i++){
pinMode(States[i], OUTPUT);
digitalWrite(States[i], LOW);
}

pinMode(CLK, INPUT_PULLUP);

Keyboard.begin();
//Consumer.begin();

Serial.print("Ready");

StartAnimation();
digitalWrite(States[currentState], HIGH);
}

void StartAnimation(){
int waitTime = 250;
digitalWrite(S1, HIGH);
delay(waitTime);
digitalWrite(S2, HIGH);
delay(waitTime);
digitalWrite(S3, HIGH);
delay(waitTime);
digitalWrite(S4, HIGH);
delay(waitTime);
digitalWrite(S1, LOW);
delay(waitTime);
digitalWrite(S2, LOW);
delay(waitTime);
digitalWrite(S3, LOW);
delay(waitTime);
digitalWrite(S4, LOW);
delay(waitTime);
return;
}

void ChangeState(){
digitalWrite(States[currentState], LOW);
currentState++;
if (currentState == numStates){
currentState = 0;
}
digitalWrite(States[currentState], HIGH);
//Serial.print("State Changed. Current State: "); Serial.println(currentState);
delay(100);
return;
}

void Layout1(char button){
switch(button){
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;
};
}//
void Layout2(char button){
switch(button){
case '1'://
break;
case '2'://
break;
case '3'://
break;
case '4'://
break;
case '5'://
break;
case '6'://Return
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
break;
case '7'://Escape
Keyboard.press(KEY_ESC);
Keyboard.releaseAll();
break;
case '8'://
break;
case '9'://
break;
};
}

void Layout3(char button){
switch(button){
case '1':
Keyboard.print('7');
break;
case '2':
Keyboard.print('8');
break;
case '3':
Keyboard.print('9');
break;
case '4':
Keyboard.print('4');
break;
case '5':
Keyboard.print('5');
break;
case '6':
Keyboard.print('6');
break;
case '7':
Keyboard.print('1');
break;
case '8':
Keyboard.print('2');
break;
case '9':
Keyboard.print('3');
break;
};
}

void Layout4(char button){
switch(button){
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;
};
}

void loop() {
//check the key matrix first
char key = kpd.getKey();
if(key) {
switch(key){
case '*':
ChangeState();
break;
case '-':
Keyboard.press(KEY_RIGHT_CTRL);
Keyboard.press('s');
delay(10);
Keyboard.releaseAll();
break;
default:
switch(currentState){
case 0:
Layout1(key);
break;
case 1:
Layout2(key);
break;
case 2:
Layout3(key);
break;
case 3:
Layout4(key);
break;
}
}
}

//check the encoder button
if(encoderButton.update()) {
if(encoderButton.fallingEdge()) {
int fall = millis();
while(!encoderButton.update()){}
if(encoderButton.risingEdge()){
int rise = millis();
//Serial.println(rise - fall);
if(rise - fall > timeLimit){
Consumer.write(MEDIA_NEXT);
Serial.print("Next");
} else {
Consumer.write(MEDIA_PLAY_PAUSE);
Serial.print("Play/Pause");
}
}
Keyboard.releaseAll();
}
}

//check encoder rotation
long newPosition = volumeKnob.read();
if(newPosition != oldPosition){
Serial.print(newPosition);

if((newPosition - oldPosition) > 0) {
//volumeup
Serial.println("volume up");
Consumer.write(MEDIA_VOLUME_UP);
} else {
//volumedown
Serial.println("volume down");
Consumer.write(MEDIA_VOLUME_DOWN);
}
oldPosition = newPosition;
Keyboard.releaseAll();
delay(200); //a delay of 200 seems to be the sweet spot for this encoder.
}
}

STEP 5: Code Walk Through

Ok, here is a more in depth walkthrough of the code for this project. As a warning I have no qualifications to teach anyone how to code. I just know how to google and use the Arduino forums and Stack Overflow.

I will do my best to walk through as simply as I can but leave a comment if you feel like I missed something.

There are a few main points when coding for general good coding practice:

  • Don't write code someone else has written better
  • Don't declare pin numbers in more than one place
  • Use good variable names
  • Functions should do only 1 thing
  • Use debugging everywhere to find errors
  • The error is usually a spelling mistake

To start with we are hitting the first bullet: don't write code someone has written better. Basically, use the libraries that smart computer people have written for us plebs to use Arduinos. In this sketch we are using 4 libraries, Keypad, Encoder, Bounce2, and HID-Project. Keypad will take care of setting up and scanning our key button matrix as well as deboncing the button presses so we only need to worry about dealing with a key press not figuring out what key was pressed/if a key was pressed. Encoder will take care of our encoder and tracking the postion of the encoder. As someone who as written an Arduino encoder function before, don't bother, it is hard and confusing. Bounce2 is a lot like Keypad but it will look at individual buttons, I use this on the encoder button as I want a short and long press function for it. And finally HID-Project will allow us to send keyboard keys as well as windows media keys, like play/pause and control the volume.

#include <Keypad.h>
#include <Encoder.h>
#include <Bounce2.h>
#include "HID-Project.h"

With those ready we can start to use them. Up first, is the keypad/key matrix. The first few lines define the pins that each row/pin is connected to. Next we define the size of our button matrix. I have 4 rows and 3 columns. Next we define the array of button symbols. I used the same number and symbol that are on the key caps for mine. After that we create an array of the pin numbers for the rows and columns. Finally we create a Keypad object called kpd to keep track of all the buttons in our keypad. A big note here, as I only have 11 buttons not 12 setting it up this way creates a phantom button, the one labeled X. This button will never be pressed as there is no switch there. In theory you could wire the encoder button here but I chose not to.

//Keypad buttons
int R1 = 6;
int R2 = 5;
int R3 = 21;
int R4 = 20;
int C1 = 7;
int C2 = 8;
int C3 = 9;
const byte ROWS = 4;
const byte COLS = 3;
char keys[COLS][ROWS] = {
{'X','7','4','1'},
{'*','8','5','2'},
{'-','9','6','3'}
};
byte rowPins[ROWS] = {R1, R2, R3, R4};
byte colPins[COLS] = {C1, C2, C3};
Keypad kpd = Keypad( makeKeymap(keys), colPins, rowPins, COLS, ROWS);//Keypad Object

Now to setup the LEDs. Similar to the keypad we just did we start with defining our pin numbers. Then note the number of states we have. In my case I went with 4 but you could do up to 16 with only 4 LEDs. As I mentioned before: if you can remember 144 different key commands be my guest, I'm not that smart. Next we collcet the pin numbers in an array called States, this will allow us to cycle through the state LEDs without needing to keep track of the pin names/numbers only the current state. Also note here that in C++ arrays start at 0, so in the States array there are 4 elements, one for each LED, the first one S1 is the 0th element and S2 is the first. All the way up to S4 which is the 3rd element. Finally in this section we tell the code what state to start in, I chose 0, but you could chose what ever layout you want.

//State LED pins
int S1 = 15;
int S2 = 14;
int S3 = 16;
int S4 = 10;
const int numStates = 4;
const int States[numStates] = {S1, S2, S3, S4};
int currentState = 0;

Encoder time. Here just like before we tell the code what pins to use. Then we create an Encoder object with our encoder tracking pins, in my case DT and CLK. Again this will work best if these are interrupt capable pins.

After we setup the encoder we setup the encoder button as a Bounce object. This will take care of the button press for us making it easy to see when its press and for how long. Then as I want the button to have a short and long press I set the time limit for a long press. I chose 500ms as it felt like a good amount. Finally we give the encoder a starting position, basically where to start counting its positions from. This number has no impact on how the encoder functions.

//Encoder
int SW = 19;
int DT = 2;
int CLK = 3;
Encoder volumeKnob(DT,CLK);
Bounce encoderButton = Bounce(SW,10);
int timeLimit = 500;
long oldPosition = -999;

Almost to the fun stuff, but we still gotta do some setup(). This is really just starting a bunch of processes to run in the background that we can use latter.

First here we start eh Serial output, I use this for debugging. It's really easy to add a .println() to see if something is working.

Next we use a for() loop to go through our States array we made. We just need to set them up as an output and then make sure they are turned off.

Next setup the encoder button as an input using the Micros internal pull-up resistor.

Now we start a Keyboard object/process (not exactly sure) so we can sent key strokes to the computer.

Next print out that we are ready and play the StartAnimation() on the LEDs.

Finally we set the current state that we declared earlier, 0, to high to turn the LED on.

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
for (int i = 0; i < numStates; i++){
pinMode(States[i], OUTPUT);
digitalWrite(States[i], LOW);
}
pinMode(CLK, INPUT_PULLUP);
Keyboard.begin();
Serial.print("Ready");
StartAnimation();
digitalWrite(States[currentState], HIGH);
}

Yay, the first fun part of the code. This is the StartAnimation. It is not needed at all but I think its fun so here it is. What we do is turn an LED on then wait, turn on the next, until they are all on. Then turn them off in the same order. You could do this with 2 for loops, one turning them on and the next turning them off.

void StartAnimation(){
int waitTime = 250;
digitalWrite(S1, HIGH);
delay(waitTime);
digitalWrite(S2, HIGH);
delay(waitTime);
digitalWrite(S3, HIGH);
delay(waitTime);
digitalWrite(S4, HIGH);
delay(waitTime);
digitalWrite(S1, LOW);
delay(waitTime);
digitalWrite(S2, LOW);
delay(waitTime);
digitalWrite(S3, LOW);
delay(waitTime);
digitalWrite(S4, LOW);
delay(waitTime);
return;
}

Up next, we are going to start setting up functions to use in our main loop(). These might not make a ton of sense out of order, check the main loop to see where the are used.

So what do we need to do when state button is pressed. To write this function I looked at what I need to do and did each step. We need to turn off the current LED, so we do that first. Now we need to change the currentState and we do that by adding one. C++ has a handy feature where we can use currentState++ to add one to the current state. Now there is an issue here, we could end up with a currentState that is larger than our numStates, well the same but that's too big because the array only goes to 3 remember. What we can do here is check to see if our numStates is equal to our currentState, if it is, reset the current state to 0. Now we can turn on the new state LED and head back to the main code.

void ChangeState(){
digitalWrite(States[currentState], LOW);
currentState++;
if (currentState == numStates){
currentState = 0;
}
digitalWrite(States[currentState], HIGH);
delay(100);
return;
}

Next we have a function for each layout out. So one for each state. I do a weird thing here where I number the states staring at 1 while the currentState starts at 0. I find it easier to keep track of but do what makes sense for you.

This function takes in one variable of a char type and we call it button. This variable only exists in this function. With that button we can figure out what to send to the computer. I am using a switch case statement here, it removes the needs to have a bunch of if else statements. For this layout I just send the numbers like a num pad. In the main code on the last step you can see a few other functions like copy/past. As there is one of these for each layout, that are the same except for the key strokes, I am only going to put the one here.

void Layout1(char button){
switch(button){
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;
};
}

Loop time. The loop for this has 3 jobs, check if we pressed a button, check if we pressed the encoder button, and check if we rotated the encoder. For each of these it can then know what to do with the functions we just covered.

In the loop the first thing we do is get any kep pressed from the keypad and then use the if statement to find if it was the state key, and use the changeState function we wrote above, if it was the save key we send the save command (this has its own key as it was appering on bascially all my layouts so I gave it its own button). If it isnt either of those buttons it must be a function button so we can use another switch case based on the current state and go to the right state Layout function.

void loop() {
//check the key matrix first
char key = kpd.getKey();
if(key) {
switch(key){
case '*':
ChangeState();
break;
case '-':
Keyboard.press(KEY_RIGHT_CTRL);
Keyboard.press('s');
delay(10);
Keyboard.releaseAll();
break;
default:
switch(currentState){
case 0:
Layout1(key);
break;
case 1:
Layout2(key);
break;
case 2:
Layout3(key);
break;
case 3:
Layout4(key);
break;
}
}
}

With the buttons out of the way now we need to see if the encoder button was pressed. We can use the Bounce fucntions to check, first .update() will tell us that there is an update on this button. With that info we check for a falling edge, is the signal on the pin going from high to low. If it is, mark the time, now wait until there is another update for the button, and make sure its the button going from low to high, it as been released, again mark the time. Now we can compare the time difference and decicde if we need to send the next track function or the play/pause function. Note that here we have to use Consumer rather than Keyboard. I don't really know why, but it works this way.

   //check the encoder button
if(encoderButton.update()) {
if(encoderButton.fallingEdge()) {
int fall = millis();
while(!encoderButton.update()){}
if(encoderButton.risingEdge()){
int rise = millis();
//Serial.println(rise - fall);
if(rise - fall > timeLimit){
Consumer.write(MEDIA_NEXT);
Serial.print("Next");
} else {
Consumer.write(MEDIA_PLAY_PAUSE);
Serial.print("Play/Pause");
}
}
Keyboard.releaseAll();
}
}

And the last thing we need to do is to see if the encoder has been rotated. Here we again use the Encoder functions to read the location of the knob and set it into the newPosition. If that is not the same as the oldPosition that we set waaaaay up there then we can find the difference between the two. If the difference is posotive we need to increase the volume otherwise decrease the volume. I added a delay here as without one the volume would rocket in either direction.

  //check encoder rotation
long newPosition = volumeKnob.read();
if(newPosition != oldPosition){
Serial.print(newPosition); if((newPosition - oldPosition) > 0) {
//volumeup
Serial.println("volume up");
Consumer.write(MEDIA_VOLUME_UP);
} else {
//volumedown
Serial.println("volume down");
Consumer.write(MEDIA_VOLUME_DOWN);
}
oldPosition = newPosition;
Keyboard.releaseAll();
delay(200); //a delay of 200 seems to be the sweet spot for this encoder.
}
}

You did it. You made it to the end. Like I said at the top I have not qualifiation to teach about this. I recommend you use this code as a starting point and work on it. Also feel free to break it, learn by doing. The full code will still be here to copy if you modify and it breaks.

STEP 6: Final Assembly

After that code walk through this should be a breeze.

Run your USB cord through the opening in the bottom of the case and plug it into the arduino. Upload your code if you haven't and test it out.

When you are ready use the hardware to screw the top on to the base.

If you are using the feet, flip the case over and add a lil foot on each corner.

You're done! Take a step back and admire your work. Its something we don't do often enough, you built a thing! A real thing, a hole project that you can set on your desk and show off. Be proud of what you've made.

91 Comments

Hi bro, I'm a little confused in the soldering area, what do the numbers in the picture mean? Why is it different from pro micro, in pro micro I can't find the numbers 19, 20, 21, etc. Please help me with the soldering
Hey, I can't figure out how to get HID Working:

In file included from /home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/KeyboardAPI.h:29:0,
from /home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/DefaultKeyboardAPI.h:27,
from /home/joosl/Arduino/libraries/HID-Project/src/SingleReport/BootKeyboard.h:30,
from /home/joosl/Arduino/libraries/HID-Project/src/HID-Project.h:50,
from /home/joosl/Arduino/projects/macro pad/macro pad.ino:4:
/home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/../KeyboardLayouts/ImprovedKeylayouts.h:54:21: note: #pragma message: Using default ASCII layout for keyboard modules
#pragma message "Using default ASCII layout for keyboard modules"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/../KeyboardLayouts/ImprovedKeylayouts.h:73:25: error: expected identifier before '=' token
KEY_H = 11,
^
/home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/../KeyboardLayouts/ImprovedKeylayouts.h:73:25: error: expected '}' before '=' token
/home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/../KeyboardLayouts/ImprovedKeylayouts.h:73:25: error: expected unqualified-id before '=' token
/home/joosl/Arduino/libraries/HID-Project/src/SingleReport/../HID-APIs/../KeyboardLayouts/ImprovedKeylayouts.h:521:1: error: expected declaration before '}' token
};
^

exit status 1

Compilation error: exit status 1

I get this message every time i want to compile.
I checked the hid files, and the errors were in random lines.
maybe an issue with the different text formats of linux? If so, how do i change it?

Hi there,
That’s a weird issue. I would recommend trying a previous version hid-project.
Thanks for the quick feedback.
I tried using versions 2.7 and 2.6.2, but i still get the same error.
I also tried it on Windows, which also didn't change anything
Hi! Nice project! Had a blast building it!
Tho I have one question; The keys don't seem to function. I've been trying a lot, even double checked the diodes polarity, as well as where the buttons connect on the Pro Micro. The rotary knob and its switch work perfectly fine however.

Do I possibly need to mind any form of polarity on the switches pins possibly? Or did I indeed solder the diodes in the wrong way, where in my case the black stripe faces away and towards the Arduino?
hey I have made a modified version of this pad and used a0, a1, a2 pins for DT, SW, CLK. how the pin will be defined? (may be 16, 17 ,18 ??) and my program is having issues i have used you code with pin defined as 16,17,18 but program aurdino ide is showing this (image attached) and my macro board is working fine without encoder code.
Hi there,
Sorry for the slow response.
It looks like the issue is in the line above the highlighted one. I would guess its the name volumeKnob. Make sure that name is defined or replace it with the new name if you changed it.
I built a similar pad a while ago (https://imgur.com/gallery/oHPNs) and wanted to try out your case-based code, but I'm getting lots of compile errors:

1. The Nico-HOOD library doesn't seem to work. What version are you using?
2. There's a switch between INT and BYTE for the pins.
3. There's HMTL in your #includes

Can I ask what version of the HID-Project library you're using?
Unfortunately it just doesn't compile for me, because of the HID-Project library. I use that library in other sketches with no issue, so there must be some sort of conflict in the sketch (or between the four libraries you're using:
[code]
In file included from c:\documents\arduino\libraries\hid-project\src\keyboardlayouts\improvedkeylayouts.h:52:0,
from c:\documents\arduino\libraries\hid-project\src\hid-apis\KeyboardAPI.h:29,
from c:\documents\arduino\libraries\hid-project\src\hid-apis\defaultkeyboardapi.h:27,
from C:\Documents\Arduino\libraries\HID-Project\src/SingleReport/BootKeyboard.h:30,
from C:\Documents\Arduino\libraries\HID-Project\src/HID-Project.h:50,
from C:\Documents\Arduino\Macropad_v1\Macropad_v1.ino:6:
c:\documents\arduino\libraries\hid-project\src\keyboardlayouts\ImprovedKeylayoutsUS.h:43:25: error: expected identifier before '=' token
KEY_H = 11,
^
c:\documents\arduino\libraries\hid-project\src\keyboardlayouts\ImprovedKeylayoutsUS.h:43:25: error: expected '}' before '=' token
c:\documents\arduino\libraries\hid-project\src\keyboardlayouts\ImprovedKeylayoutsUS.h:43:25: error: expected unqualified-id before '=' token
c:\documents\arduino\libraries\hid-project\src\keyboardlayouts\ImprovedKeylayoutsUS.h:491:1: error: expected declaration before '}' token
};
^
exit status 1
Error compiling for board Arduino Micro.
[\code]
That's very strange. It looks like its an issue within HID-Project not with the code. I would try updating HID-Project to the most recent version and trying again.
I decided to revisit this since your keypad made it into the newsletter (congratulations!) Unfortunately, despite installing multiple versions of the Arduino IDE and the HID-project library, I still can't compile the code due to the huge (I mean HUGE) list of errors, which all have NICO-Hood's library as the root cause.
Are you able to include the current list of errors?
When it compiles for me I get a decent amount of orange text, but it has never caused issues for me. I am currently using HID-Project verison 2.8.2.
Can't compile... Keypad.h no such file
Used hid project library 2.8.2 and 2.6.0 but none worked
Hi Wow,
This is error is caused by not including the Keypad.h library. Make sure that all the libraries are included though the library manger.
In fact, I was checking this out on a different computer than where I wrote the code and got this error, after including Keypad it went away. You do have to scroll a bit, I've included a screen shot of the one that I use.
I did exactly the same as you did (except the rotary encoder part, I unuse the encoder code), the code works on compiling and uploaded into the pro-micro, the LEDs are working, but the button wont trigger the key on pc, is there any preparation for the pro-micro so it can be used to access the pc keyboard? (im using push buttons btw, not keyboard switches)
Hi,
You shouldn’t need to do anything special to get your computer to recognize the macropad as a keyboard.
Two things I think might be casing the issue.
Make sure to either comment out or delete all the encoder code, I think it might be getting hung up trying to check the encoder.
Are the push buttons latching or are they just momentary switches?
Hy, thanks for your reply.
I have rechecked and the problem it can't trigger any key is the circuit diagram, and i have fixed that and try it with common keypad program (without hid libraries) and the key arrays are good, I try it both in arduino pro micro and arduino uno and it works just fine. But i retry using your code with the rotary code commented out and it still won't work. So i decided to develop a code myself and now it works, it can trigger the key on pc. But i have an issue, the button from keypad library just trigger once/click even though im holding the button. It's different with the button that connected from pin directly to the ground methode (input_pullup) where it can trigger high/low as long as i still pressing the button. any suggestion?

ps:im so sorry if my english is bad and hard to understand, i hope you get what i mean, hehe
Hi!
This is very good idea, to have some additional keys beside regular PC keyboard.
I want to make it too.

However, I stucked at the beginning with compiling author's sketch.
I constantly got error like:

#error HID Project can only be used with an USB MCU.
^~~~~
exit status 1
Error compiling for board Arduino Nano.

I got the same error for Micro Pro or Mega 2650 or Uno boards too.
I use last IDE v1.8.16 and all libraries, which are used were updated by IDE.

Can you explain how did you compile your sketch, please?

Thanks in advance!

Br,
Andreo
More Comments