Tuesday, February 23, 2010


note: this video is showing an early prototype, behavior of the final version is slightly modified


A good while back, I made the 1-key-keyboard project. Ever since it has always been in the back of my mind that the ATTiny microcontroller, which I used in this project, had still 3 IO ports which were unused. Only recently I’ve found the time to expand my old project in the most obvious way possible; by adding 3 more buttons to these IO ports and thereby creating a 4-key-keyboard, without having to add any other hardware than these 3 extra buttons.

Although this project can still easily be built on a stripboard, I chose this time to etch my own (single sided) PCB and to use an old USB cable to interface with the computer, instead of the makeshift USB-plug as used in my previous project.

see here the result:


The hardware:


• 1x Atmel ATTiny45-20PU or ATTiny85-20PU microcontroller
• 1x 8-pin DIL socket (optional but highly recommended)
• 2x Diodes (0.5W) (ordinary 1N4148 will do the job)
• 2x 68 ohm resistors
• 1x 1.5K resistor
• 1x 0.1 uF capacitor (note: can be higher capacity, I also used 1uF and in the example circuit from obdev they use 4u7)
• 4x push-button
• 1x usb cable with the standard usb-A plug
• 1x etched circuit board (or use stripboard as alternative)

And a programmer for the ATTiny45/ATTiny85 microcontroller. For this project a programmer supporting High Voltage Serial Programming (HVSP) is highly recommended, since we enable the ‘reset disable’ fuse. I’ll explain this in more detail later on.

The schematics:


The circuit-board:

In the .zip file of this project, there’s a .pdf which can be used for photo-chemical etching of the circuit-board. EAGLE files are also included.

The component layout on the circuit board:


The firmware:

I tried to add useful comments to the sourcecode of this project, so I suggest to have a look at it to see the precise details.

At a high-level, this project implements V-USB (previously called AVR-USB) from Objective Development, which I use to emulate a USB keyboard.

Contrary to my 1-key-keyboard project, I now used the standard report descriptor for a USB keyboard, which has a 8-byte report buffer. This may be a bit of a overkill, since I only use 4 of these bytes in this project (1 for each button) but it does allow for easy expansion of functionality in the future.

Another difference with my old project is the fact the way key-presses are emulated. in the old version, two different keys were emulated on press and release of the button. Now every button simulates just 1 key, but with its individual key-down and key-up event, which is exactly the same as a normal keyboard operates.

In the standard firmware, key presses are emulated for the keyboard-keys 1 to 4. Though this can easily be changed.

Programming the firmware:

OK, I’ll start here with a warning: If you don’t have a programmer that supports High Voltage Serial Programming (HVSP) then you can’t reprogram the ATTiny anymore after enabling the reset-disable fuse. (An Atmel STK500 programmer does support HVSP!)

If you have a programmer that only supports ISP, then you can still successfully program the 4-key-keyboard, as long as you upload the firmware before setting the reset-disable fuse.

If you want to experimenting/test this project without having a HVSP capable programmer, then I suggest to test it without the reset-disable fuse set. This will result in button 3 not working (since it’s connected to the IO pin that doubles as reset pin), but all other 3 will work. Only when you’re sure that you’re happy with the firmware, you can set the reset-disable fuse.

I have personally always used AVR Studio in combination with WinAVR to program my AVR’s (they are available at no cost) But you can use your own favorite AVR programming environment to program your ATTiny. You can find both the sourcecode and a pre-compiled .hex in the .zip file of this project.

Recommended fuse-settings:

HIGH: 0×5D (use 0xDD to test without reset-disable fuse set, as described above)
LOW: 0xC1


Testing the project

After you have built the circuit, programmed the firmware and set the fuses correctly, it’s time to test the project.

After plugging in the USB cable, the computer should recognize a new keyboard and automatically install the standard keyboard-drivers. Then it’s time to test! The easiest way is to open a text-editor, e.g. notepad, and push the buttons in the prototype. If everything is successful, keyboard-keys 1-4 are emulated by the 4 buttons on the prototype.

Interfacing with Adobe Flash

By emulating a standard keyboard, this project should be easy to integrate in any software with which you want to interface. But personally I’ve used it often in combination with Adobe Flash. Since I’ve modified the behavior of the buttons to resemble how a normal keyboard operates, there’s a slight change in the code to interface with flash, compared to the 1-key-keyboard project.

Now in flash you can create event-listeners for KeyboardEvent.KEY_DOWN and KeyboardEvent.KEY_UP for keys 1-4, just like one would interface with a normal keyboard to detect when a key is pressed and when it’s released. Flash example code is included in the project file.

Download the project files

Click here to download the complete sourcecode of this project

  1. Martín

    Wednesday, May 19, 2010 - 01:37:23

    Hello my name is Martin, I’m from Argentina.

    I have moved your application to a ATTINY2313 to this move some pins and used the Timer0 (8 bits) instead of the Timer1 (16 bits) of TINY2313. In addition to some space, I removed the calibration routine and went to use a crystal of 16 mega hertz.

    It’s working really well and I appreciate you sharing your work.

    Greetings, Martin

  2. zeynab

    Tuesday, July 20, 2010 - 04:42:45

    Hi Mr. Flip.
    first of all thank you for your grate project.
    it’s exactly what i was looking for.
    i need 3 push button to be connected to computer through usb.
    bat i have a problem, I only hane attiny13. and the memory is 8 times less than atttiny85. I’m new in these stuff. do you think that would work?
    could you help to find another micro instead of attiny45/85? I mean in different micros that are what factor should i check.
    I myself think in this case I should check the memory, bat i don’t know for example should I check your hex file with the flash memory of the micro a something else?
    thank you for spending your time reading my comment.
    looking forward for your reply.

  3. Flip

    Tuesday, July 20, 2010 - 08:36:22

    Hi Zeynab,

    The ATTiny13 has too little memory indeed, so it can’t be used for this project.

    the ATTiny45 and ATTiny85 microcontrollers are the smallest and cheapest microcontrollers that can run this project, so why don’t you consider buying them? I paid around 2 euro a piece for them, so that would be the best solution I think. Make sure you get the 20MHz version if you want to buy them! (I used the attiny45-20pu and attiny85-20pu for my project)

    or is there a specific reason for you not wanting to use the attiny45 or attiny85?

    Kind regards,

  4. zeynab

    Tuesday, July 20, 2010 - 09:55:45

    Hi Mr. Flip
    Thank you for your reply and your attention.
    actually my main problem is that in the place that I live the only attiny micros that I had found was attiny13 and attiny2313 that by simulating on protues I get the point that you said about low memory!
    actually there are loads of atmega different kinds in here. I guess I should look more for your suggested micros and if I didn’t find I think I should work with atmega! I will be so grateful to see if you have any suggestion about witch kind of atmega is better to use.
    Sorry for bothering and having your time!


  5. Jack

    Friday, September 3, 2010 - 11:57:28

    Hi Mr. Flip and thank you for the project!
    I m a newbie in C and Assembler programming, but i need only of a little help.
    I want to assign to a key the shift function, and have tried to assign to a key the shift code, wich is 225 (L Shift).
    I have build and programmed the attiny, but it not work.
    When i press the key, is sent a character in loop, and there is no way to stop the transmission.
    Probably is incorrect the value 225 for the shift, please can you help me?
    Thanks in advance!

  6. Flip

    Friday, September 3, 2010 - 17:52:06

    Hi Jack

    the problem you’re facing is that the shift key is a ‘modifier key’ and not a normal key.. I’ve put some comments about this in my sourcecode. - do a search in my code for “modifier keys” and you’ll see.

    so you should set reportBuffer[0] = 1<<1 to press the left shift and set reportBuffer[0] = 0 to release.

    Good luck, and let me know if this works for you!

  7. surpher

    Monday, October 11, 2010 - 13:58:51

    Hi Flip

    I made one of these keyboards on stripboard for my Tablet PC, I can confirm the code for the “modifier keys” in the above post works.


    Thanks for sharing your project, it was really easy to follow :)

  8. Flip

    Tuesday, October 19, 2010 - 09:23:31

    I just updated the PCB design for this project.

    Now all tracks are on the back side of the PCB (In the first edition a jumper-wire was needed) So it’s now ideal for single-sided etching!

  9. Oliver

    Saturday, November 13, 2010 - 22:14:15

    What a great project! I’m just a bare newbie on micros, but good documentet helped me to adapt it to my needs. Just had some trouble if I used an ATTiny45-20PU - some usb-chipsets won’t work with it (unknown usb-device). Think it’s a problem with the osc. If I use an ATTiny85-20PU it works on all tested chipsets. Thanks for sharing the project. Olli

  10. warezzzok

    Saturday, July 16, 2011 - 20:32:34

    Hello. Your keyboard is what I was looking for. I tried to collect your circuit using the same components as you, but when you connect the controller to usb, the system only reports “unknown device”.
    the device all the time disappears and appears in Device Manager.
    I used a chip Attiny85, flash it via codegersionAvr and stk200.
    what could be the reason?

  11. Flip

    Sunday, July 17, 2011 - 06:55:30

    The “unknown device” error is only a very generic error, which can be either failing hardware or failing firmware, so I suggest the following:

    - double check the hardware circuit you made
    - verify you programmed the project’s standard .hex file successfully (this firmware certainly works)
    - verify that you have the correct fuse setting. I am not familiar with the compiler you’re using. so sadly I can’t give details on how to do this.

    Good luck with the project!

  12. warezzzok

    Saturday, September 3, 2011 - 19:21:30

    Hello. Only now found time and completed the keyboard. The problem was not correct fuse bits.
    Flashed controller with AVRdude + Burn-O-Mat
    Thank you again for this project. This is exactly what I need - arrow keys to Tablet mode of my notebook))

  13. Keystone6

    Wednesday, June 6, 2012 - 21:16:10

    Great project. Almost exactly what I need. D/L’d and burned hex file to ATTiny85 and it runs as advertized. Now for what I want: two inputs, ‘2′ on close & ‘[’ on open; ‘3′ on close & ‘’ on open…kinda in between 1-Key and 4-Key projects. No prob: mod Main.c to send different keystrokes, recompile, reburn. WRONG. Not that easy grasshopper. 1. AVR Studio isn’t avail anymore. Replacement, Atmel Studio, takes forever to install, consumes gobs of resources, takes 3 minutes to load. 2. “Stuff” is in different places: usbdrv files not found. 3. After finding a suitable folder and moving the files, they won’t compile. Apparently PROGMEM specs have changed. First of many errors is usbDescriptorDevice in usbdrv.h 4. Won’t compile because a declared variable isn’t declared.

    I’ve been programming since 1971. Gave up Assembly back in the mid 70’s. Never picked up on C. Now I know why.

    Anybody have an updated, detailed set of instructions so I can stop pulling out what little hair I have left?

  14. ceemos

    Friday, June 8, 2012 - 20:23:48

    @Keystone6: I updated the project right now to compile with latest gcc. Modified some stuff, and added a Makefile, so compiling is a simple \”make hex\” (using gnu make) — no AVR/Atmel/whatever Studio required.
    I will probably add more info soon.

    @Filp: The RC Oscillator calibration is far from working for me. It tries values that make the oscillator stop (the AVR is actually overclocked at 3.3V/16.5MHz - calibratoin tries even higher values). I wonder whether this has ever worked at 3.3V… right now using a hand-tuned fixed value.

  15. Keystone6

    Saturday, June 16, 2012 - 01:19:26

    TNX for the quick response, ceemos. I think I’ve posted all your updates and changed by main prog as required. Improvement, but there yet. Was getting some funky error message about ‘(’ expected before token on a line using F_CPU, so I changed the define line in main to ‘# define F_CPU 1000000UL’. The compiler seems happy but for an ‘OSCAL’ undeclared (first use… (in main prog) error and a ‘calibrateOscillator’ defined but not used warning. Is this function required for the ATTiny?

    Note that I’m not familiar enough with all the parameters in the make file, so opted to try compiling w/ Atmel Studio 6.

    This is turning out to be w-a-y more difficult than I anticipated. About to throw in the towel on the project!

  16. Flip

    Wednesday, June 20, 2012 - 12:59:39

    I just successfully imported, compiled and programmed this project using Atmel AVR studio 6. I might post an update later when I have time to turn it in an actual post. Just want to let you all know now that I didn’t encounter any errors like described above.

  17. ceemos

    Thursday, June 21, 2012 - 18:41:58

    That “‘calibrateOscillator’ defined but not used” is normal, I disabled the claibration since it caused trouble for me, but I left the function in. I hava no idea wether my fixed value will work with another ATTiny, so probably you’d better put call to calibratOscillator back in, but it will probably not work work with a 3.3V supply voltage.

    That OSCAL unefined and F_CPU trouble however shouldnt happen: F_CPU is correctly defined in the makefile, I have only put it in main.c that my IDE finds something. Same for the include below, that should be handled by some magic. Better remove these 4 lines if there is trouble with #define’s.

  18. Brad V

    Monday, August 6, 2012 - 17:49:04

    Hi Flip, great project and yes it did easily import to avr studio 6. I’ve made a working prototype, and it works perfect. However I’m trying to use it to type in multiple keystrokes per button push. 1 button press equals say 3 keystrokes. After reading your blog I bought an avrdragon and started using avrstudio so I’m a total newbie learning more everyday. Anyway any pointers you could give on modding the code for multiple keystrokes would be greatly appreciated. Thanks