Jun 24

Simple ATTiny85 USB board

IMG_20140623_121908_fixI needed to create a small, cheap USB-enabled circuit to serve as a key logger, and I've found some nice projects online that explain how to do this.
I found out you could use an ATTiny85 to run the V-USB software USB stack, and I only needed the one input pin to gather data (it's going to be a USB "That was easy" button).
Since this was done so many times before, I will be brief, and try to point out problems I had instead of a regular tutorial.

For a tutorial please take a look at one of these:

Some products do it also:

So I went ahead and drew out a circuit in Eagle (well, first I tried it on a breadboard):

And created a routing for it (all through-hole components - yay!):

I had to make sure the clearing is good for the Roland Modela machine we have in our shop at the Media Lab. The clearing should be 16mil, since the smaller bit we use is 1/64".

Milled it out on the Modela and stuffed it:

NOTE: there is one air wire going from the ISP connector to the Tiny, with only top-layer routing it was hard to route it around stuff. I've jumped it with a wire, but it could also go on the bottom with a wire to keep things nice and clean on the top.

Programed the code from here on it, with an AVR programmer:

First I needed to fuse it though, to get the clock to run 16MHz:

avrdude -P usb -c stk500v2 -p attiny85 -U lfuse:w:0xe1:m -U hfuse:w:0xdd:m

I've also made a little change to the code, to make the LED light up during the time it's looking for the right OSCCAL value:

int main() {
    uchar i;

    DDRB = LED_PIN; // LED pin as output
    wdt_enable(WDTO_1S); // enable 1s watchdog timer

    usbDeviceDisconnect(); // enforce re-enumeration
    for(i = 0; i<250; i++) { // wait 500 ms
        wdt_reset(); // keep the watchdog happy
    sei(); // Enable interrupts after re-enumeration
    while(1) {
        wdt_reset(); // keep the watchdog happy
    return 0;

Actually I first tried just the Blink sketch on Arduino, based on the tutorial by Dave Mellis: http://highlowtech.org/?p=1695

When everything is connected, USB Prober is happy and recognizes the device as "USBExample" (which is what the demo code makes it say).

To make this actually work as a keyboard for the PC (and not use the LibUSB interface to send low-level commands), I had to make some changes to the code based on some very good remarks here: http://codeandlife.com/2012/02/11/v-usb-tutorial-continued-hid-mouse/
The usbconfig.h file must be very accurate about defining:

#define USB_CFG_INTERFACE_CLASS     3  // this is needed in order to tell the PC this is an HID device
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH    35 // this must correspond to the # of bytes of the descriptor in main.c

There are more things to do, depending on the needs, but the tutorial from before covers them pretty nicely.

I had fun doing this project! But it was frustrating too...
My lessons learned are:
- Check and then double-check your wires. Make sure everything is properly connected to the right place and there are no shorts.
- USB is fussy. It needs short, low impedance wires on the data lines, that is why I got a recommendation to make a PCB when my breadboard wasn't working.