Close
0%
0%

Pro Trinket USB Keyboard

A USB keyboard for custom shortcuts based on the Pro Trinket and Pro Micro

Similar projects worth following
The aim of this project is to create a device similar in functionality to the Palette by palettegear.com at a lower price. As the Palette offers flexibility through reconfiguration, the low cost nature of this project will allow customization by redesign.

Motivation

A friend of mine asked me around the time of the Palette kickstarter if I could build something similar for him since it was relatively expensive. The Palette is a USB device with several different kinds of inputs (buttons, sliders, knobs) that can be configured as various keyboard shortcuts and the like. So over last couple of months I've been thinking about possible implementations and only recently got around to prototyping them. And now that Hackaday is hosting this contest I simply had to document it, such that others might profit from the solutions to problems I had during development.

Research and preparation

For this first prototype we decided that the device should have 8 buttons and 4 rotary encoders which have 4 additional buttons arranged in a 4 wide and 3 tall array with the encoders on top.

Rough sketch of the devices layout.

Since my microcontrollers of choice are AVRs and I also wanted to get into USB capable AVRs and VUSB, the decision to use a Pro Trinket as platform for this project was a quick one. Also the fact that it can be reprogrammed (i.e. with different keyboard shortcuts) without additional hardware (dedicated ISP or USB-to-serial converter) is a great advantage.

Read more »

  • 1 × Pro Trinket or Pro Micro
  • 8 × tact switch 12mm x 12mm or 6mm x 6mm
  • 4 × rotary encoder
  • 1 × case
  • 2 × angled tact switch rese & modet button, mounted in the back/side

View all 8 components

  • v4.2 hardware update

    Stefan Lochbrunner12/11/2015 at 00:21 9 comments

    It's v4 with I²C ports. Lots of I²C ports. GitHub.

    While the original premise of this project was that it could be easily redesigned to fit ones individual needs, @Craig Hissett convinced me to make it modular after all, just like its 'role model' Palette. Therefore, the I²C ports are for slave modules that can attach to this (master) module and extend it's functionality.

    Read more »

  • Pro Trinket/Micro Keyboard Jr

    Stefan Lochbrunner11/30/2015 at 23:09 5 comments

    As the name implies this is a device with almost the same functionality as the main Pro Trinket Keyboard but in a smaller formfactor. I have to give credit to @Craig Hissett for the inspiration for this device and since I could reuse a lot of the schematics it wasn't much work at all.

    The hardware files are already on GitHub and the firmware will come once the hardware is available to develop and test on.

    Read more »

  • v4 hardware update

    Stefan Lochbrunner11/30/2015 at 21:20 8 comments

    Due to a critical mistake in v3.4a [that @Craig Hissett had to find out about the hard way ;) ] I, of course, deemed it necessary to do a correction but it was also kind of clear that a redesign might be in order. Here are some changes:

    • Since everybody who built this keyboard wanted to use an external MCU (be it a Pro Trinket or Pro Micro) I decided to drop the footprints for the components that would otherwise make up the Pro Trinket circuit.
    • Dropped optional diode footprints (introduced in v3.4a) to make assembly less confusing
    • Rerouted whole board with Pro Trinket and Pro Micro compatible socket. More on this in the previous log. This way the USB ports of both boards also face away from the mode button.

  • Pro Trinket and Pro Micro Compatibility

    Stefan Lochbrunner11/30/2015 at 20:14 1 comment

    In preparation for the next logs I wanted to talk a bit about the pin compatibility between the Pro Trinket and the Pro Micro. The reason why I also want to integrate the Pro Micro is that it's more commonly available and cheaper.

    Read more »

  • v3.4 hardware update

    Stefan Lochbrunner10/20/2015 at 19:44 17 comments

    A minor update, implementing some more of @davedarko's suggestions.

    Changes:

    • Added footprints for smaller (6x6mm) tact switches
    • Added footprints for WS2812B's and diodes to the bottom layer and top layer, respectively. This allows the the board to be used with either side up.
    • Some rerouting, especially the of WS2812B supply traces
    Read more »

  • v4 sketch makes use of multimedia keys

    Stefan Lochbrunner09/26/2015 at 17:35 1 comment

    This has been long overdue... I finally updated the sketch to make use of the multimedia keys. Implementing this was a little annoying because the the multimedia keys (and mouse movement, which is not yet implemented) require a different function to be called than 'normal' keys and the keycodes that can be used for those functions overlap. For now the colliding 'normal' keycodes (ctrl, shift, alt & gui) are ignored in favor of the mmkeys. This goes only for the bare keys, they still work as modifiers. It's not ideal but at least volume control finally works. I thought about using another variable to distinguish between normal, mmkeys and mouse movement but that array is already way too confusing as it is.


    edit 2015-09-27:

    Initially I added some exceptions for ctrl, shift, alt & gui to be usable with the pressKey functions instead of invoking pressMultimediaKey. However, that didn't seem to work and while playing around with it I discovered (while writing the 1st version of this update ;) ) that you can also use the corresponding modifier without a keycode (well, more specifically kyecode 0). So it seems ignoring those codes will work without limiting functionality but now the problem is that my code doesn't allow for keys to be held down. One solution to this would be to make another exception for keycode 0 to toggle the modifier(s) on press and release. I'll look into this...

  • v3.3 schematics & PCB update

    Stefan Lochbrunner09/26/2015 at 13:32 4 comments

    As per @davedarko's suggestion I added diodes to the keypad and encoders to prevent ghosting. While I was at it I also switched the LEDs to WS2812B's to allow better color mixing and 'doubled' the amount of LEDs to better illuminate to top piece of acrylic. Files on Github.

    Read more »

  • Move to Adafruits ProTrinketHidCombo lib

    Stefan Lochbrunner06/02/2015 at 22:47 0 comments

    TLDNR: what it says in the caption, v3 sketch on GitHub.

    A few days ago I started moving the sketch to the (relatively) new ProTrinketHidCombo library directly from Adafruit thinking it would be an easy task...

    Besides the VUSB for Arduino linrary not compiling in the 1.6.4 IDE the ProTrinketHidCombo lib has the advantage (as the name implies) of 'complete'(?) HID functionality meaning not only keyboard but also mouse and multimedia key functionality.

    I ran into similar problems as before with the device not properly re-enumerating and the like. Going back and forth between this one and the working VUSB for Arduino library I found out that the thing that was missing to make it work was to disable the timer 0 overflow interrupt in the beginning of the usbBegin() function in ProTrinketHidComboC.c (starting in line 32). The changed function now looks like this:

    void usbBegin()
    {
      // disable timer 0 overflow interrupt (used for millis)
      TIMSK0&=!(1<<TOIE0);
      
      // Clear interrupts while performing time-critical operations
      cli();
      
      // run at full speed, because Trinket defaults to 8MHz for low voltage compatibility reasons
      clock_prescale_set(clock_div_1);
      
      // fake a disconnect to force the computer to re-enumerate
      //PORTD &= ~(_BV(USB_CFG_DMINUS_BIT) | _BV(USB_CFG_DPLUS_BIT));
      usbDeviceDisconnect();
      _delay_ms(250);
      usbDeviceConnect();
      
      // start the USB driver
      usbInit();
      sei();
    }

    Another minor thing with this function is that the write to PORTD (or PORTB as it says on their GitHub) is redundant. As the comment states this is intended to force re-enumeration which can be done by forcing D- (and D+) low. D- and D+ are on port D not B, pins 7 and 2 respectively. With the 'Optional Hardware Config' section in usbconfig.h commented out, D- is already being forced low by usbDeviceDisconnect() found in usbdrv.h (starting in line 298).

    As you might know I'm not using a genuine Pro Trinket but I don't think that should make much of a difference. I'd be interested if the library and the included example work without modification on a proper Pro Trinket.

    edit:

    Obviously if you disable the timer overflow interrupt right before initializing the library, there is no need to modify the library.

    TIMSK0&=!(1<<TOIE0);
    TrinketHidCombo.begin();

    edit 2015-09-26:

    added link to the post about the library above

  • Re: switch bouncing

    Stefan Lochbrunner05/20/2015 at 23:35 9 comments

    I played around with some capacitor values to get rid of the bouncing of the tact switches. I tried some caps in the pF an nF range but they either had no noticeable effect or lead to the neighboring button in the next column being read as pressed as well. Implementing a proper RC filter (with no footprints for the resistors) didn't improve it much either. However, adding some software debouncing in the form of 250us delay after a column is polled pretty much got rid of the bouncing, I haven't been able to replicate the issue since. This goes for for all of the above mentioned configurations (including no caps) so I'm glad I won't have to change the PCB... at least until a major redesign.

  • Final (?) assembly

    Stefan Lochbrunner05/09/2015 at 16:42 1 comment

    This week I finally received my order from DirtyPCBs (after anxiously waiting for about a month):

    To make better use of the area I added some breakout boards and some other things I wanted to try out. Besides some silkscreen issues on a few boards they turned out great and for that price I can't complain.

    Read more »

View all 22 project logs

Enjoy this project?

Share

Discussions

Sam A Y wrote 08/22/2017 at 08:48 point

Hi Stefan, great write up!  Do you have any more of the PCBs available?

Thanks!

  Are you sure? yes | no

davedarko wrote 03/18/2016 at 21:27 point


I finally came around to design a case :) I might add a 433MHz transmitter for using it to switch my sockets on and off. I need to use this more!

  Are you sure? yes | no

Stefan Lochbrunner wrote 03/19/2016 at 00:31 point

Awesome! Interesting design, looking forward to seeing how it turns out!

Interesting use case, too. Do you really have that many sockets? I looked into using those sockets for home automation but now I'm thinking I'll go with WiFi (which obviously means ESP); at least for controlling lighting.

Admittedly, I barely use mine. I do a bit more 3D modeling these days so I should probably make a profile for that so it gets some use.

  Are you sure? yes | no

davedarko wrote 05/09/2016 at 12:56 point

currently using this on a tablet pc with an OTG adapter :) I had to change my previous mac working keys for navigating through songs from:

#define MMKEY_FAST_FORWARD 0xB3 
#define MMKEY_REWIND 0xB4

back to the 

MMKEY_SCAN_PREV_TRACK and MMKEY_SCAN_NEXT_TRACK codes - but otherwise I'm happy.

  Are you sure? yes | no

andrei.harasemiuc wrote 11/05/2015 at 15:55 point

hey guys. i want to build something like this for myself with next to none knowledge of electronics and how they technically work (although I'm a programmer). Can you guys just point me in several directions where I could research stuff and then build a board like this?

  Are you sure? yes | no

Craig Hissett wrote 11/05/2015 at 17:12 point

Hey Andrei - thanks to @Stefan Lochbrunner's hard work barely any knowledge is required :)

Have a read through his project logs; he has made all of his board designs available on his Github. I am the same as you; comfortable programming but terrible at the hardware side - I have just sent one of Stefan's boards off to www.dirtypcbs.com to be created. Once they arrive it's a case of simply soldering on the buttons and microcontroller as detailed by Stefan (and also @davedarko who is making one too) and you are good to go!

If you are aiming to make your own from scratch I strongly recommend building one of Stefan's first; you will learn the necessary steps to go on and make your own!

  Are you sure? yes | no

Stefan Lochbrunner wrote 11/05/2015 at 17:30 point

Hi, for the basics of the circuit you can check out the Adafruit tutorials linked in the sidebar on the left. Then you can either build it on perfboard, like I did with the prototype here: https://hackaday.io/project/3502/log/12252, or design a PCB. For the design I use Eagle and know of this SparkFun tutorial here: https://learn.sparkfun.com/tutorials/using-eagle-schematic but maybe you'll be more comfortable with KiCad, then #The KiCAD Central might be a good starting point. Among others, there's also Fritzing (http://fritzing.org/) which might be more beginner-friendly but I haven't used it so I can't really tell.

If you would like to skip the design phase, I'd be happy to send you one of the (v3.1) PCBs and if you use a (store bought) Pro Trinket soldering the whole thing is pretty easy.

  Are you sure? yes | no

andrei.harasemiuc wrote 11/05/2015 at 17:35 point

thanks for replying! so if i could get my hand on one of your pcbs. All i would need to do is solder the pcb to the Pro Trinket, buy the necessary potentiometers and solder them (which ones? which would fit I mean), find a box to put it all safely in. What about programming the pro trinket. I imagine that's posted on your git as well.. If i'm getting all of this right, I'd love a pcb from you :D

  Are you sure? yes | no

Stefan Lochbrunner wrote 11/05/2015 at 18:19 point

You're pretty much right, the rotating knobs are rotary encoders (with buttons), not potentiometers though. Most of these encoders I've seen are almost identical so these http://www.adafruit.com/product/377 or these http://www.ebay.com/itm/New-10pcs-12mm-Rotary-Encoder-Push-Button-Switch-Keyswitch-Electronic-Components-/261537203134?hash=item3ce4d503be:g:5EEAAOSwEK9Tyl9g (or similar) should work. Mounting of the encoders is a bit tricky though but I hope this log (https://hackaday.io/project/3502/log/17616) and especially the last image is helpful; and if you have any questions I'm happy to help as well.

Basically you need the components listed above.

If you can't find a suitable case you can use the templates (also on GitHub) for an acrylic case like in the main project image. See this log for more information: https://hackaday.io/project/3502/log/16135

Yes, the software is on GitHub, but you also need the Adafruit Pro Trinket HID/rotary encoder library which is linked in the sidebar. That link also has information on how to install it.

So If you write me a message I'll send one your way :)

  Are you sure? yes | no

davedarko wrote 09/26/2015 at 19:32 point

nice updates :)

  Are you sure? yes | no

Stefan Lochbrunner wrote 09/27/2015 at 00:26 point

Thanks! I can't seem to get this finished ;)

  Are you sure? yes | no

mobichem wrote 05/20/2015 at 21:57 point

Nice PCBs and nice work.

  Are you sure? yes | no

Stefan Lochbrunner wrote 05/20/2015 at 23:17 point

Thanks, that means a lot to me :)

  Are you sure? yes | no

mobichem wrote 01/22/2015 at 13:54 point

Hi i am trying to send (LEFT GUI + X).

"{{(MOD_GUI_LEFT,KEY_X),0}....."

I checked the definitions but I can not send it.

have you tried it?

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/22/2015 at 14:29 point

Hi, in my code the 0s in the usb_codes array are the modifiers. Therefore the (first) array entry should look like this: {{{{KEX_X,MOD_GUI_LEFT},... (all the brackets are just to indicate that it is the first entry).

Accordingly the call to send a keystroke has to look like this: UsbKeyboard.sendKeyStroke(usb_codes[mode][j][i][0], usb_codes[mode][j][i][1]); where the "0" references the key and the "1" references the modifier. I don't think it's possible to call UsbKeyboard.sendKeyStroke(usb_codes[mode][j][i]) since this function expects either one or two bytes but not a 2 wide array. However, you could wrap the call in another function that does take a 2 wider array as input.

Sorry for this, I seem to have forgotten to put it in but I'll change it right now. Thanks for pointing this out :)

  Are you sure? yes | no

mobichem wrote 01/22/2015 at 18:12 point

Ok, I'm not sure about what you mean ( sorry again i'm beginner :? and not very expert programer ) i see here " http://www.xenoworld.org/?page_id=125 " this can be send " UsbKeyboard.sendKeyStroke(KEY_Z, MOD_CONTROL_LEFT); " (in the middle of the page)


In your code the send string is.


- UsbKeyboard.sendKeyStroke(usb_codes[mode][j][i][0], usb_codes[mode][j][i][1])
Can you,please, tell me more about the "modifier" do.


Let me know, if i'm to much irritating. ;D


Honestly thanks so much, for your help and patience.

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/22/2015 at 19:03 point

In the UsbKeyboard.h you find a list of definitions for various keys (and also the sendKeyStroke function if you haven't already). There the macro "KEY_X" is defined as 27. So what the sendKeyStroke function accepts as inputs are these integers. Instead of (30,0) (for the very first entry in my code) it could also say (KEY_1,0) for example.

What I do in my code (which is admittedly quite confusing... again ;) ) is to reference these numbers by the entries in the usb_codes array or more specifically by their coordinates (i and j). By using the coordinates of the entries (instead of the value of the entries) I can easily map the arrangement of the physical buttons to the layout of the array. So if I want to change the keys or their layout I can do this by changing the array (at the beginning of the file) and don't have to modify one or multiple functions that are further into the code.

Regarding the modifiers: It's like a normal keyboard. If you want capital letters you have to hold shift while pressing a letter. Therefore what you do with this library is to give the key (e.g. KEY_X) a modifier (e.g. MOD_SHIFT_LEFT, which would type a capital x = X). I was saying that in my code all modifiers are 0 which is why in the video all letters are lower case. I think it might be good to mention that the modifiers are optional as can be seen in the example of the Adafruit tutorial. In the UsbKeyboard.h you'll see that if you do not specify a modifier it will be set to 0. But in case any of the buttons use a modifier, there has to be an entry for all buttons or else the array dimensions/referencing doesn't work out.

I hope this is somewhat understandable and helps you out ;)

  Are you sure? yes | no

mobichem wrote 01/22/2015 at 19:50 point

If i understood, i can do like this.....¿NO?

code {{KEY_X,MOD_SHIFT_LEFT},{31,0},{32,0},{KEY_C,MOD_GUI_LEFT}},

output {{capital X}, {2}, {3}, {copy}}

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/22/2015 at 20:01 point

I think the modifier for copy should be MOD_CONTROL_LEFT but besides that it should give you that output. I haven't tested it though.

  Are you sure? yes | no

mobichem wrote 01/21/2015 at 18:30 point

Finally, i got.
The problem was the library, now i want to test functionality.

Thanks for your help.

  Are you sure? yes | no

mobichem wrote 01/19/2015 at 14:03 point

I have problems compiling usvdrv in arduino IDE, can you upload yours to github.

if you can upload all files..... ;)

Thanks in advanced.

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/19/2015 at 17:43 point

Hi, I haven't made any changes to the usbdrv.c / .h files from the UsbKeyboard library of VUSB for Arduino only to usbconfig.h. Those changes are:

- change "#define USB_CFG_DMINUS_BIT" from 4 to 7

- comment out the two definitions in the "Optional Hardware Config" section and

- make modifications to the "Device Description" section but that shouldn't be necessary to get it to work.

Those are the same changes that can also be seen in the Adafruit Pro Trinket USB tutorial (https://learn.adafruit.com/wireless-game-show-poppers/learn, roughly in the middle of the page). The problem with uploading my usbconfig.h file is that I'm not 100% sure about the proper legal usage of the vendor and device IDs and I'd rather not spread any false or infringing information.

Also make sure that the UsbKeyboard library is installed correctly ("Copy 'UsbKeyboard' directory in the 'libraries' directory to your Arduino 'hardware/libraries' directory." according to the USB for Arduino readme). In the IDE it should be listed under "Sketch/Import library...".

I hope this helps. It sounds like you're building one so let me know how it turns out :)

  Are you sure? yes | no

mobichem wrote 01/19/2015 at 19:12 point

Thanks a lot, finally i compiled, but no usb HID detected at computer. i don't know what happend.

i think the problem can be the schottky lose 1 volt, 4,90v before and 3,88v after. I'm not sure but i think is not enough for the microcontroler and the rest of the components.


if finally can do, don't worry, i tell you.


i'm sorry disturb you, Thanks again.

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/19/2015 at 19:29 point

Don't worry about the questions, I appreciate your feedback :)

The Schottky diode shouldn't drop a whole volt. I assume you're building the Pro Trinket yourself too, therefore I'd just leave it out. The ATmega328 should still work at 3.3V even if running it at 16MHz is considered overclocking but running it directlly with the 5V from USB should also be fine.

  Are you sure? yes | no

mobichem wrote 01/19/2015 at 22:08 point

I have two arduino clone (SMD ATmega328p 16Mhz with ft232rl ) and this is my start point.


take off diode and no luck.
i make the test, indicated USB tutorial (https://learn.adafruit.com/wireless-game-show-poppers/learn, roughly in the end of the page). and Pulling pin 4 low will cause the LED off, reverse like the description. and computer no detect HID.


I think i lose something, the computer no detect HID.


Copy ProTrinketUsbKeyboard.ino, usbconfig.h, UsbKeyboard.h, usbdrvasm.s and oddebug.c in the same folder for arduino, compiled program, ok. upload to 328, ok, but no results.


i need upload "pro trinket" bootloader first?


again i think i lose something.

Thx :)

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/19/2015 at 22:43 point

I'd try copying the whole UsbKeyboard keyboard folder to the libraries folder as it says in VUSB for Arduino. The Pro Trinket bootloader only facilitates the sketch upload over USB just like the "standard" Arduino bootloader facilitates it over UART so you won't need another bootloader. But you will need the the "VUSB circuitry" (zener diodes, series resistances and pull-up on D-) since the MCU can't show up as USB device through the FT232RL.

  Are you sure? yes | no

mobichem wrote 01/20/2015 at 00:20 point

of course, i made the "USB circuitry" and connected to arduino .....upload through FT232RL and test through "VUSB circuitry" no luck. :(


to be continued. ;).

  Are you sure? yes | no

mobichem wrote 01/15/2015 at 22:49 point

First thank for the reply,again doubt, pin18 -->+5v, pin4--> +5v are correct, and D8 used already.
can you explain a little bit more the pull-up resistance why you connect directly vcc.

thanks again and sorry for the inconvenience.

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/16/2015 at 01:36 point

I'm not sure I quite understand what you mean. Please have a look at the updated schematics that should now show the proper connections according to the labels.

Are you referring to the internal pull-up resistors of the microcontroller? Since you mentioned being a beginner I'm also not sure of how much you know about the usage of pull resistors but I'd be happy to (try to ;) ) explain it or point you towards some tutorials that might do a better job explaining it than I could.

  Are you sure? yes | no

mobichem wrote 01/16/2015 at 09:01 point

Thank for the new schematics ;).... i google more about pull-up.

  Are you sure? yes | no

mobichem wrote 01/15/2015 at 17:50 point

Hi, i like your project..... but i dont understand, at the IDE pin 13 is PD7, this used for usb conector and for the rotary? sorry for my ignorance, i am beginner.

can be possible a schematic more detailed... THX.

sorry for my english.

  Are you sure? yes | no

Stefan Lochbrunner wrote 01/15/2015 at 18:19 point

Hi, sorry for the confusion. You are right that pin 13 of the DIP package is PD7 which is used for USB. However, the numbers for the digital (and analog) pins used by the Arduino IDE are different. If you reference the schematic of the Pro Trinket under https://learn.adafruit.com/introducing-pro-trinket/downloads it says that digital pin 13 or D13 is PB5. This means that the numbers shown in my schematic would correspond to the silkscreen numbers on a Pro Trinket.

I hope this helps, if not please let me know.

  Are you sure? yes | no

johnowhitaker wrote 12/04/2014 at 17:22 point
This is an awesome project! Not only could this be a very useful every-day-cary for a designer or someone who has to work on different machines, it'll also help others of us do similar things when we next need to scratch this particular itch :) Oh, and I can easily see a final version that'll fit in a pocket without trouble.

  Are you sure? yes | no

Stefan Lochbrunner wrote 12/04/2014 at 21:08 point
Thanks! The aspect of using it working on different machines is interesting, it hadn't occurred to me. That would add a certain portability aspect to it where pocketability would come in handy. I'll definitely try to make it happen and post a picture.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates