Introduction: Mini USB Keyboard With a $7 Microcontroller
Make a keyboard that uses a microcontroller to send usb keypresses, which interfaces with AutoHotKey, a Windows application for creating applications and macros.
AutoHotKey can be used with your original keyboard with no need for an additional keyboard. This supplementary device isn't for everyone, but some of the uses include:
- simplifying annoying hotkeys to the push of a single button
- creating special controllers for games / interfaces
- creating program specific tasks, like using each button to save out a different filetype in an application
The AutoHotKey software can assign just about anything to the press of a button:
- launching applications
- multi step commands that can be done with the keyboard
- simplifying cumbersome shortcuts
- launching a specific web url
- inserting snippets of text
This was just an experiment for me, but I have found it to be useful for many things, so I thought I'd share. I am not experienced in circuit design or arduino programming, but this worked for me and maybe it can help with your projects. I did not see a lot of information about using the trinket, so I thought that making this available for people to see could be helpful. Feel free to comment on any improvements that could be made.
Step 1: Supplies
Materials / parts:
- Adafruit Trinket microcontroller
- Mx Cherry key sampler
- small perf board
- resistors: 1k(x4), 100k(x2)
- solder
- wire
Tools:
- soldering iron
- hack saw
- pliers
Step 2: Modifying the Enclosure
I used a mx cherry keyboard sample that I had, but anything with multiple switches could be used for this: game controllers, numeric keypads, or just switches on a pcb.
Grooves will need to be cut in the separating walls of the base. this is so we can run connecting wires through. I used pliers to snap out some of the dividing plastic between the top and bottom keys, to run a few more wires through.
Step 3: Making the Circuit
I started by soldering the full length wire going to one of the inputs that was isolated on the end. then I soldered in the resistors and connections between buttons, then finally snaked in the last full length wire around everything else.
It might take some maneuvering to keep the components out of the way so it sits flat. Then solder the trinket and resistors to the perf board, and lastly connect to the buttons.
Step 4: Trinket Arduino Code
Here is the code I used, you might have to tweak the input values to get the best results. I just replaced the F keys with letters and tested in notepad.
#include
const int sensorPin = 3; const int sensorPin2 = 2;
int sensorValue = 0; int sensorValue2 = 0;
void setup() { pinMode(sensorPin, INPUT); pinMode(sensorPin2, INPUT); // start USB stuff TrinketKeyboard.begin(); }
void loop() { sensorValue = analogRead(sensorPin); sensorValue2 = analogRead(sensorPin2); TrinketKeyboard.poll(); if( sensorValue >= 615 and sensorValue <= 625 ) { TrinketKeyboard.pressKey(0, 0); } if( sensorValue >= 700 and sensorValue <= 800 ) { TrinketKeyboard.pressKey(0,KEYCODE_F4); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0,0); delay(300); } if( sensorValue >= 670 and sensorValue <= 700 ) { TrinketKeyboard.pressKey(0,KEYCODE_F6); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue >= 655 and sensorValue <= 660 ) { TrinketKeyboard.pressKey(0,KEYCODE_F7); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue >= 650 and sensorValue <= 655 ) { TrinketKeyboard.pressKey(0,KEYCODE_F8); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue2 >= 650 and sensorValue2 <= 800 ) { TrinketKeyboard.pressKey(0,KEYCODE_F9); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue2 >= 600 and sensorValue2 <= 650 ) { TrinketKeyboard.pressKey(0,KEYCODE_F10); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue2 >= 580 and sensorValue2 <= 600 ) { TrinketKeyboard.pressKey(0,KEYCODE_F11); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } if( sensorValue2 >= 560 and sensorValue2 <= 579 ) { TrinketKeyboard.pressKey(0,KEYCODE_F12); // this releases the key (otherwise it is held down!) TrinketKeyboard.pressKey(0, 0); delay(300); } }
Attachments
Step 5: AutoHotKey Code
SetTitleMatchMode, 2 Hotstring to enter time stamp in document ; F6 and F7 keys always have the same function regardless of the active program F6:: Run, "C:\Windows\Sysnative\SnippingTool.exe" ; opens snipping tool return #IfWinActive, Snipping Tool ; if snipping tool is open, the same button will close it F6:: { WinClose Snipping Tool } return #IfWinActive F7:: FormatTime, CurrentDateTime,, yyyyMMdd ; inserts the current date in a specified format SendInput %CurrentDateTime% return ; F8 and F9 keys function varies by the active program #IfWinActive, Program Manager ; functions if desktop is active F8:: run taskmgr.exe ; open task manager return F9:: IfWinExist Google Chrome ; open Chrome or maximize window if open already WinActivate, Google Chrome else run "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" return #IfWinActive #IfWinActive, Chrome ; Chrome specific functions F8:: Send, ^+{Tab} ; go left a tab return F9:: Send, ^{Tab} ; go right a tab return #IfWinActive #IfWinActive ahk_class CabinetWClass ; windows explorer specific functions F8:: Send, !{Up} ; go up a folder level return F9:: Send, ^n ; opens a new window return #IfWinActive
Step 6: Customization
Using a separate usb device lets you customize the buttons for your needs. There are a whole bunch of custom key caps available online to use for a custom USB input device.

Participated in the
Epilog Contest VII
11 Comments
Question 5 years ago
Dear Jake,
I want to use the updated Trinket microcontroller, that is, the Adafruit Trinket M0 (same form factor, much newer design).
What are the main differences I should take care of? First of all, the M0 has a 3V arhitecture, so I guess I have to divide the 3V output with the resistors in order to protect the analog inputs. Will the 1k resistors still be fine? Another difference is that I want to use 12 keys instead of 8. As I understand I have one more analog input so I simply use 3×4 configuration instead of 2×4, as shown in your example. Or, if not, I can use more than 4 divisions, cannot I?
Can I use your existing code essentially unchanged (but updated the analog reading values)?
Thanks a lot!
5 years ago
Thanks for your code and wiring guide, but the pin 2 and 3 are used for USB, how can they be used as analog read at the same time? I tried on my digispark, connection pin 2 to GND will cause a device disconnection in PC end. Also, the analog read value really confused me, for example, pressing S1 should give an analog read around 1000 ( 100k/(100k+1k) ), but why the highest read in your code is 800? Please do reply, I'm so confused now :( Thank you.
7 years ago
Wow thanks you really helped me but, dose this work for raspberry pi? If so, this will work as a game pad for Retropie. Again Thanks!
8 years ago on Introduction
that's so lagit
8 years ago on Introduction
nice job :) thats a prety amazing build :)
8 years ago
cool
8 years ago on Introduction
here you go:
http://www.maxkeyboard.com/max-keyboard-keycap-che...
8 years ago
Where would one obtain a sampler for those switches you have?
8 years ago on Introduction
Thanks guys, I hope it is useful to you.
8 years ago on Introduction
I like this instructable a lot!
8 years ago on Introduction
Cool Project