V-USB tutorial (software-only usb for mega & tiny)

Arduino use the FTDI chip for usb communication (not anymore). This chip is expensive and only surface mount. To save money and be able to make a PCB at home, i found a software-only implementation of USB for AVR (attiny, atmega): http://www.obdev.at/products/vusb/index.html.


You don’t need the 2 LEDs (visual feedback for debugging / bootloader).
Not using a bootloader? Then you can connect R4 to VCC (thus freeing PD4).


I am using an ATMEGA164p. The example code need to be modify to suit your device (bootloader address, registers, EEPROM functions).

This tutorial is for people who have some experience or are patient. Please pardon my english.

1) breadboard your avr for programmation (SPI / JTAG)

2) download vusb (last version)

A SIMPLE TEST (hid mouse)

cd vusb-x/examples/hid-mouse/firmware
open usbconfig.h – set the pin for usb (USB_CFG_DMINUS_BIT – USB_CFG_DPLUS_BIT)
open Makefile – edit DEVICE / F_CPU / FUSES / AVRDUDE
make hex
make program

Replug the device and automagically the mouse will move on your screen.

3) download bootloadhid (last version)
This bootloader doesn’t require a driver (it’s HID). With it, you will be able to program your firmware without your programmer.

4) delete usbdrv, cp the usbdrv from vusb
5) open usbconfig.h – change the VENDOR and DEVICE name if you want
6) open bootloaderconfig.h – set the pin for usb (USB_CFG_DMINUS_BIT – USB_CFG_DPLUS_BIT) and if you want to be able to reset via usb (USB_CFG_PULLUP_IOPORTNAME). Change the bootloadcondition to suit your needs, i am using the EEPROM to write (from the firmware) & read (from the bootloader) + a button on PD5 (need to be hold) for the condition and finally 2 leds (so i know that i am in the bootloader).

show code ▼

7) main.c: Edit your condition, mine looks like this:
show code ▼

8) edit the Makefile

You need to know the BOOTLOADER_ADDRESS of your device (learn more about bootloader). Basically your datasheet will tell you the Start Bootloader section (look for Boot Size Configuration) in word address. You need to multiply it by 2 (the toolchain works on BYTE ADDRESS). For example, the atmega164p for 1024 words, the address is: 1C00 * 2 = 3800.

I am using a 20mhz clock, V-USB can be clocked with 12 Mhz, 15 MHz, 16 MHz or 20 MHz crystal or from a 12.8 MHz or 16.5 MHz internal RC oscillator.

Finally, you need to set the fuse correctly:

  • Boot Flash section size = 1024 words
  • Uncheck Divide clock by 8 internally
DEVICE = atmega164p
F_CPU = 20000000
FUSEH = 0xd8
FUSEL = 0xff
PORT = usb

make fuse
make flash

Now that you have the bootloaderhid, let's write a simple firmware to test it.


#define F_CPU 20000000

int main(void) {

	// Set Port B pins as all outputs
	DDRB = 0xff;

  while(1) {

    PORTB = 0xFF;

    PORTB = 0x00;


  return 1;

avr-gcc -mmcu=atmega164p -Os test.c
avr-objcopy -j .text -j .data -O ihex a.out a.hex

cd bootloader/commandline
edit main.c if you changed the VENDOR and PRODUCT string

You need to connect the usb cable while holding the reset button. 2 LEDs should light up and you should see in dmesg something like:

[ 1727.956432] usb 3-2: new low speed USB device using uhci_hcd
[ 1728.119279] usb 3-2: configuration #1 chosen from 1 choice
[ 1728.142142] generic-usb 0003:16C0:05DF.000A: hiddev97,hidraw4: USB HID v1.01 Device [YOURVENDOR YOURPRODUCT] on usb-0000:00:1a.0-2/input0

./bootloadHID -r a.hex


Now what you want in your custom firmware is a way to tell your device to go in the bootloader (so you don't have to hold the reset button anymore). With this method in place, adding the reset button is optional, but recommanded (in case you break something in the firmware, you need a way to go back in the bootloader).

Remember, in the bootloader we are reading the EEPROM to see if we need to stay in the bootloader section, if not we load the firmware. So in the firmware we will write the EEPROM if we want to go in the bootloader.
show code ▼

You are ready to write the firmware for your application. Since you are using V-USB not only it let you upgrade your firmware very easily, but you can of course send and receive message between your computer and the device. Here's an example of sending the value of a potentiometer to your computer and telling your device to blink a led at a certain speed. This example is for my device, Atmega164p.


You can trick Windows so it doesn't popup the driver installation when you plug your device. Your need to use a HID descriptor (Vendor type requests sent to custom HID class device).

show code ▼

show code ▼

Here's an example for installing the software & driver:


Here's the most basic host software written in python.
show code ▼


V-USB runs on any AVR microcontroller with at least 2 kB of Flash memory, 128 bytes RAM and a clock rate of at least 12 MHz. For example the ATTINY25 can do the job. The price of this chip is 1.66 2.00 USD!


Here's my template for the Atmega164p. This firmware is ready for ADC free-running mode, SPI master (you need to +5V PB4), external interrupts (PORTC), EEPROM read / write, jump to bootloader.
show code ▼



PUREDATA (custom-class) TEMPLATE

Communication from and to Pure Data


You can find more information about the API / USB Device Class / Host Software on the wiki of V-USB. Tutorial by Joonas Pihlajamaa: AVR ATtiny USB Tutorial.


08 2009

0 Comments Add Yours ↓

  1. psc #

    hi Serjio,

    Maybe installing this USB Python Module would help:

    Good luck!

  2. Serjio #

    hey, patrick!
    nice tutorial!
    looking forward to get the wires and soldering iron to try it out!
    the thing is I downloaded the python code to my mac and run python python.python in a terminal, and it says,

    Traceback (most recent call last):
    File “python.python”, line 1, in
    import usb
    ImportError: No module named usb

    what could be the problem?

    I’d like to develop a servo PWM controller, which would be accessible via USB (e.g. you open, for instance, a telnet session and type a digit to turn servo at some angle – I want it to be controllable from my dir-320 router with openwrt firmware)

  3. psc #

    hi dorijan,

    i am sorry, but i don’t have access to vista or 7 / 64 bits. what is not working exactly? from the innosetup install script: Filename: “rundll32”; Parameters: “libusb0.dll,usb_install_driver_np_rundll {app}\driver\edubeat.inf”; StatusMsg: “Installing driver (this may take a few seconds) …” from edubea.inf: CatalogFile.NTAMD64 = edubeat_x64.cat & [Devices.NTAMD64]
    “USB Human Interface Device”=LIBUSB_DEV, USB\VID_16c0&PID_05dc. in theory it should work, of course your device needs the same VID & PID.


  4. dorijan #

    I was wondering how to make driver for windows vista or 7 64 bit? The one that is in edubeat.zip does not work. Thank you! this is great tutorial how to use USB with atmega :)

  5. me #

    Hi Yuse,

    My english isn’t better than yours…

    May i suggest to have a look at a similar project:

    Also, it might be a good idea to start with a simple HID project like this one: http://www.obdev.at/products/vusb/hidkeys.html It should be trivial to modify this project for an atmage168 (modify the Makefile).


  6. 6

    Heii Patrick…
    Thanks for Your great tutorial…
    Im interesting in developing USB apps using this VUSB…

    I want to make an HID accelerometer mouse using VUSB…

    I used ATMEGA168 in this app.. but i got stuck on its configurations…
    Can U help me on migrating this one to ATMEGA168..

    Whats configuration should I changed from its default setting..
    I used vusb-20090822…

    Sorry for my bad english.. im Indonesian..



  1. work in progress » Blog Archive » kicad – video tutorial – 1 31 01 10

Your Comment