I 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:
http://www.obdev.at/products/vusb/easylogger.html
http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/
http://www.instructables.com/id/Digispark-DIY-The-smallest-USB-Arduino/step4/Digispark-schematic/
Some products do it also:
https://www.sparkfun.com/products/9147
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 PORTB |= LED_PIN; // LED ON wdt_enable(WDTO_1S); // enable 1s watchdog timer usbInit(); usbDeviceDisconnect(); // enforce re-enumeration for(i = 0; i<250; i++) { // wait 500 ms wdt_reset(); // keep the watchdog happy _delay_ms(2); } usbDeviceConnect(); sei(); // Enable interrupts after re-enumeration PORTB &= ~LED_PIN; // LED OFF while(1) { wdt_reset(); // keep the watchdog happy usbPoll(); } 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.
Enjoy,
Roy.