Trybotics Logo

Arduino Uno Macro Keyboard

DESCRIPTION

Hi there.

When using my pc with only a keyboard I've noticed that in some programs that it's just not enough. Now there are macro keyboard on the market, but the all have 1 big issue, they are only buttons! That's why I've decided to make one on my own to perfectly match my needs. It does not only have buttons, but a slider, rotary knob and intuitive control glove as well.

In this tutorial I will show how to make my customizable macro keyboard with the arduino uno (rev 3 and above) with selectable profiles. Using this tutorial, you will be able to make a keyboard with all kinds of buttons and sensors. My version has 5 buttons, 1 rotary potentiometer, 1 fader (slide) potentiometer, 1 on/off switch, a thumbpad for profile selection and as a twist I've added a glove controller using a flex sensor, but the beautiful thing about this project is that you can make it fit your own needs. do you like knobs? Add them. Buttons? throw 20 on it. Compass? Why not?

I will go over everything from the materials I've used to the tricks for using the arduino UNO for Serial communication and making a code for easy customization and editing.

Description:

For the electronics you will need:

  • Arduino Uno (rev 3 and up)
  • Breadboard
  • Arcade buttons x5
  • 2 way toggle switch
  • thumbpad
  • rotary potentiometer
  • slider potentiometer
  • 10kΩ resistor
  • jumper cables x31
  • flex sensor
  • Anything else you want to slap on this thing

Do note that there is a limited amount of digital and analog pins on the UNO, so look if it will all fit before buying.

For the case I've used:

  • plywood
  • a few nails
  • a multiplex block

Other materials and tools:

  • wood glue
  • spray paint
  • crayon
  • sanding machine
  • drill
  • soldering iron

Description:

Although it might look daunting, the wiring for this project is actually relatively simple, using basic wiring
for sensors. You might want to look at which thumbpad and slider potentiometer you are using, as it can
differ.

Description:

Arduino Uno is not made for using it as an USB HID device. With some tricks, however, you can make it work. You can do this by flashing custom keyboard firmware to the arduino with the program FLIP.

First of all you need to set your arduino to DFU mode. You can do this by connecting the 2 pins in the image for a split second (while connected to your pc). Then, you need to upload the keyboard.hex file through flip. Press ctrl+u and click on 'open'. Then, press the 'load hex' button and select the file. Disconnect your arduino and reconnect it. Now it will be detected as a keyboard. You may notice you are not able to upload files to your arduino anymore. For this, you need to follow the last steps again but now with the usb serial hex. Do this every time you want to edit your code.

keyboard.hex

USB_serial.hex

Description:

Initializing and declaring variables:

const int toggle = 2;<br>int toggle_val;
int toggle_old;

const int btn0 = 3;
int btn0_val;
int btn0_old;

const int btn1 = 4;
int btn1_val;
int btn1_old;

const int btn2 = 5;
int btn2_val;
int btn2_old;

const int btn3 = 6;
int btn3_val;
int btn3_old;

const int btn4 = 7;
int btn4_val;
int btn4_old;

const int pot0 = A0;
int pot0_val;
int pot0_old;

const int slider = A5;
int slider_val;
int slider_old;

const int flex = A4;
int flex_val;
int flex_old;

const int x = A2;
int xval;
const int y = A3;
int yval;

int selected_profile;

This piece of code is called a 'byte array, a 2 dimensional array that contains bytes. In here, all the keycodes are stored for easy access. There are 4 profiles with each 26 keycodes that can be used. In this example, not all keycodes and profiles are used, but it's nice to know they are there for easy access. Under the byte array the keyboard buffer is initialized. In this array, keypresses are temporarily stored before being sent to the computer.

byte profile[8][26] =  {{0x00,0x1B,0x00,0x19,0x00,0x50,0x00,0x4F,0x01,0x01,0x01,0x51,0x01,0x52,<br>		       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x1B},
                       {0x00,0x1D,0x00,0x50,0x00,0x4F,0x00,0x1B,0x00,0x29,0x00,0x00,0x00,0x00,
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06},
                       {0x00,0x2B,0x02,0x04,0x01,0x0D,0x01,0x16,0x42,0x00,0x04,0x2B,0x01,0x04,
                       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04},
                       {0x01,0x04,0x01,0x1D,0x01,0x1C,0x01,0x06,0x01,0x19,0x04,0x2B,0x01,0x04,
                       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04},
                       {0x01,0x04,0x01,0x1D,0x01,0x1C,0x01,0x06,0x01,0x19,0x04,0x2B,0x01,0x04,
                       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04},
                       {0x00,0x1D,0x00,0x50,0x00,0x4F,0x00,0x1B,0x00,0x29,0x00,0x00,0x00,0x00,
                       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
                       {0x00,0x2B,0x02,0x04,0x01,0x0D,0x01,0x16,0x42,0x00,0x04,0x2B,0x01,0x04,
                       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04},
                       {0x01,0x04,0x01,0x1D,0x01,0x1C,0x01,0x06,0x01,0x19,0x04,0x2B,0x01,0x04,
                       0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04}}; 
uint8_t buf[8] = {<br>0};

In the setup, the internal pullup sensor is activated for every sensor for more accurate readings. Also, the Serial is initialized with a standard baud rate of 9600.

void setup() {<br> 
  digitalWrite(toggle,1);
 
  digitalWrite(btn0,1);  
  digitalWrite(btn1,1);
  digitalWrite(btn2,1);
  digitalWrite(btn3,1);
  digitalWrite(btn4,1);
  digitalWrite(x,1);
  digitalWrite(y,1);
  digitalWrite(pot0,1);
  digitalWrite(slider,1);

  Serial.begin(9600);
}

The loop function.

void loop() {<br>//Here is the code for selecting the profile by sliding the thumbpad in each of four directions.
  xval = analogRead(x);
  yval = analogRead(y);

  if(yval>570){
   selected_profile = 0;       
  }<br>
  if(yval<300){
   selected_profile = 1;<br>  }

  if(xval>510){
   selected_profile = 2;
  }

  if(xval<250){
   selected_profile = 3;
 }

//Retrieving sensor data	
  toggle_val = digitalRead(toggle);
 
  btn0_val = digitalRead(btn0);
  btn1_val = digitalRead(btn1);
  btn2_val = digitalRead(btn2);
  btn3_val = digitalRead(btn3);
  btn4_val = digitalRead(btn4);

  flex_val = map(analogRead(flex),0,1023,0,100);

  pot0_val = analogRead(pot0);

  slider_val = map(analogRead(slider),0,1023,0,153);
 

//The rest of the code is only executed if the device is turned on
  if(toggle_val == 0){

//Setting the keyboard buffer when activating a sensor. buf[0] is reserved for modifier keys:
0x01: Left Control<br>0x02: Left Shift<br>0x04: Left Alt<br>buf[2] is for any other key. The keycode is easily selectable through the previously defined <br>byte array//

  else if(btn0_val == 1 and btn0_old == 0){
      
        buf[0] = (profile[selected_profile][0]);
        buf[2] = (profile[selected_profile][1]);
      }

  else if(btn1_val == 1 and btn1_old == 0){
      
        buf[0] = (profile[selected_profile][2]);
        buf[2] = (profile[selected_profile][3]);
      }
    else if(btn2_val == 1 ){
      
        buf[0] = (profile[selected_profile][4]);
        buf[2] = (profile[selected_profile][5]);
      }
    else if(btn3_val == 1){
      
        buf[0] = (profile[selected_profile][6]);
        buf[2] = (profile[selected_profile][7]);
      }
    else if(btn4_val == 1 and btn4_old == 0){
      
        buf[0] = (profile[selected_profile][8]);
        buf[2] = (profile[selected_profile][9]);
      }

    if(pot0_val < pot0_old){
        buf[0] = 0x01;
        buf[2] = 0x51;
      }else if(pot0_val > pot0_old){
        buf[0] = 0x01;
        buf[2] = 0x52;
      }

   if(slider_val < slider_old){
       
      }else if(slider_val > slider_old){
     
      }

   if(flex_val>=60 && flex_old<60){
        buf[2] = (profile[selected_profile][1]);
      }
//Values for detecting change in value for the sensors
    btn0_old = btn0_val;
    btn1_old = btn1_val;
    btn2_old = btn2_val;
    btn3_old = btn3_val;
    btn4_old = btn4_val;
    toggle_old = toggle_val;
    pot0_old = pot0_val;

   slider_old = slider_val;

   flex_old = flex_val;
    
  }
//Writing the buffer data through Serial communication
    Serial.write(buf,8);
    buf[0] = 0;
    buf[2] = 0;
    Serial.write(buf,8)<br><br>//A small delay for less interference
    delay(10);
}

Description:

If you followed along this far you have a fully functional arduino USB keyboard, although it is not really ready for use yet. A box has to be made. First you need to design your box. I chose for a sideways rectangle with a palmrest. What is important here, is to have enough vertical space for the big arcade buttons to fit, so first measure the desired height (about 7 centimeters). It is advised to not glue the top, but instead make it click or fit right in, so you can easily repair or adjust the parts. When you have all the parts together, you need to drill some holes for the components. The holes for the buttons should be 28mm, for the potentiometer 6mm, and for the toggle switch 18mm. The rest depends on how you want to mount the components and the sizes that you are using.

Now you have a fully functional Arduino Uno keyboard. No need to install any drivers, this keyboard is plug and play and works on any pc!


YOU MIGHT ALSO LIKE