Code and Life

Programming, electronics and other cool tech stuff

Supported by

Supported by Picotech

USB Mouse with ATmega32U4 Pro Micro Clone and LUFA

I have spent a fair amount of time with 8-bit AVR microcontrollers and one of the cooler things has been the V-USB library which implements low-speed USB with clever (and very time-critical) bit-banging. The popularity of my USB tutorials is a testament to its usefulness, and I’ve gotten lots of mileage out of that.

There are, however, some limitations to software USB with such a low spec microcontroller. USB communication hogs up the MCU completely during USB communication, which means you lose dozens of microseconds in random (or in many cases 8 ms) intervals. This rules out things like software UART at reasonable speeds (which I discovered when trying to implement MIDI on Adafruit Trinket). And more powerful ATmega328-based dev boards like Pro Trinket start to get quite large.

ProMicro on a breadboard

Not so with this tiny beauty shown in the image. It’s a ATmega32U4 based board, where the U4 means it has hardware USB support. The form factor is extremely compact 12 pin header length, which leaves 5 rows free on the smallest prototyping breadboards. That means you can have a DIP8 component with a few resistors on the same breadboard (such as a 6N137 optocoupler which is nice for MIDI… ;).

And the best part is, that because the chip is flashed with same firmware used in Arduino Leonardo (and a largely matching pinout), you can use Arduino for programming, and avrdude supports it out of the box.

Actually, scratch the above statement. The best part is the price. The board is based on Sparkfun Pro Micro 16 MHz, but it’s actually a Chinese clone, which you can get for $4 via DealExtreme and from quite many places in AliExpress: Just search for ATmega32U4 and they will come up. This means you can just order five and solder them into whatever project you’ll make permanently. And unlike Arduino Micro (for which clones exist as well), this has the micro-USB port already in place.

Using Pro Micro without Arduino IDE

Now you can just follow SparkFun’s instructions on how to use that thing on Arduino (short version: select Leonardo as board type, and look up the schematic if you are unsure which pins are connected to LEDs, etc.). But if you’re like me and want to get to raw metal, avr-gcc and avrdude is the way to go. Here’s a simple blinky demo:


#include <avr/io.h>

#define F_CPU 16000000UL 
#include <util/delay.h>

int main() {
  DDRB = _BV(PB0); // Pro Micro TX LED

  while(1) {
    PINB |= _BV(PB0); // toggle TX LED
    _delay_ms(500); // wait 0.5s
  }	

  return 1;
}

And here’s how you you compile it. Just short RST and GND before avrdude command to reset the device, so bootloader is ready:


avr-gcc -O2 -mmcu=atmega32u4 blink.c -o blink.elf
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex
avrdude -p atmega32u4 -c avr109 -P COM9 -U flash:w:blink.hex

That’s really it! If you don’t know which COM port your device is on, just fire up Arduino, reset the device and look up the port it shows under in Tools > Port.

More Advanced Example: USB Mouse with LUFA

The great things about the ATmega32U4 don’t stop to Leonardo compatibility. I got this board because it’s one of the MCUs supported by the awesome Lightweight USB Framework for AVRs, or LUFA in short. LUFA has great example code for making many kinds of USB devices, including USB MIDI which I’m going to do next. But to get started, I wanted to make something really simple. So let’s make an USB mouse which goes right when you press a button.

First, I downloaded LUFA, unpacked the source and made a copy of the Demos\Device\ClassDriver\Mouse directory. Then I followed Dean’s instructions to edit Makefile to match Arduino Leonardo. You only need to change the MCU, BOARD and F_CPU settings, and add the two AVRDUDE rows to make the makefile look like this:


MCU          = atmega32u4
ARCH         = AVR8
BOARD        = LEONARDO
F_CPU        = 16000000
F_USB        = $(F_CPU)
OPTIMIZATION = s
TARGET       = Mouse
SRC          = $(TARGET).c Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH    = ../../../../LUFA
CC_FLAGS     = -DUSE_LUFA_CONFIG_HEADER -IConfig/
LD_FLAGS     =

# Arduino Leanardo compatible flashing
AVRDUDE_PROGRAMMER = avr109
AVRDUDE_PORT = COM9

# Default target
all:

# Include LUFA build script makefiles
include $(LUFA_PATH)/Build/lufa_core.mk
include $(LUFA_PATH)/Build/lufa_sources.mk
include $(LUFA_PATH)/Build/lufa_build.mk
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
include $(LUFA_PATH)/Build/lufa_doxygen.mk
include $(LUFA_PATH)/Build/lufa_dfu.mk
include $(LUFA_PATH)/Build/lufa_hid.mk
include $(LUFA_PATH)/Build/lufa_avrdude.mk
include $(LUFA_PATH)/Build/lufa_atprogram.mk

Next, I looked at the source code in Mouse.c and realized Dean had made the example code for a development board that has some kind of joystick, buttons and all kinds of LEDs in it. After a bit of head-scratching, I found the LEONARDO board definitions in LUFA\Drivers\Board\AVR8\LEONARDO. There is LEDs.h but no Joystick.h or Buttons.h, so I commented out latter two from Mouse.h:


//#include <LUFA/Drivers/Board/Joystick.h>
#include <LUFA/Drivers/Board/LEDs.h>
//#include <LUFA/Drivers/Board/Buttons.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>

I then proceeded to cut out everything seemingly unnecessary from Mouse.c, and added initialization code to enable pullup resistor on PC6 pin (labelled “5” on the device, corresponding to
Leonardo digital pin 5, I think), and modified the HID report callback to set MouseReport->X to 1 whenever that pin is digital low (i.e. shorted to ground, which means button press).

I retained some LED functionality, but if you don’t need that, you could just comment out the #include for LEDs.h as well in Mouse.h, and remove all lines with “LED” in them in my final Mouse.c. I had a couple of IC hooks available which I used to short pin 5 (and RST when programming) to ground, so I avoided soldering the pin headers on this one. :)

ATmega32U4 Pro Micro clone

I was quite surprised that running make in my copied directory (note: it has to be in same folder as original Mouse directory is for the relative paths in Makefile to work!) actually ran without any errors. And flashing the device can be achieved with make avrdude. To see if everything worked, you just short #5 and GND and the green LED should light and your mouse cursor should start moving left. Easy!

Conclusions

This ATmega32U4 board (and three others I sourced from various Chinese suppliers) looks a strong candidate for my new favorite development board:

  1. Out-of-the-box Arduino compatibility
  2. Easy flashing with avrdude
  3. Very compact form factor
  4. Easy and extensive USB support with LUFA
  5. Enough pins and functionality (ATmega328 plus USB) for almost any project
  6. USB port, fast 16 MHz crystal, a couple of LEDs on board
  7. Extremely inexpensive and widely available (SparkFun, DX.com, AliExpress, Ebay)

My next task is to make this thing a native USB MIDI device, and see if it can do high-speed USB to overcome the 8 ms polling limitation on low-speed V-USB MIDI implementation I’m currently using (more on that in the future as well).

Hope you enjoyed the article, and stay tuned for follow-ups!

6 comments

Rick:

how can you find makefile ?
I’m using atmel studio
thanks

Roger Williams:

Hey Joonas!

Nice work.

Question for you, did you use Sparkfun’s Windows Driver or something else?

Thanks!

Joonas Pihlajamaa:

Not quite sure. The USB mouse thing of course works without drivers, but for flashing, it either works due to Arduino Leonardo drivers, or then I had previously tried the Sparkfun device, so I had those installed. I used AVRdude instead of Arduino, so no Arduino support per se was needed, just the driver…

Artem:

I’ve tried implementing this solution just today and running it under OSX, yet it did not work. The device was not even displayed in the System Information window. Do you have any ideas on OSX issues?

Artem:

Just to put a little bit of context around this, I’m building the simplest V-USB circuit possible – with 7805 to stabilize the voltage and two 68-ohm resistors between D+/D- and ATTiny44A MCU. According to the instructions, I’ve connected D+ to the INT0 of an MCU and D- to the INT1 (just in case). I assumed the 5V voltage on data lines of the USB should be okay.

I’ve also changed the configuration in `usbconfig.h` accordingly to my setup and even flashed the `mouse` sample code to the MCU (to be more secure about the code).

The voltage from USB is there, but the device is not recognized by my host OS (OSX).

Here’s the project in EasyEDA for a reference (together with sources and a schematic): https://easyeda.com/shybovycha/V-USB-test1

Cheers!

Joonas Pihlajamaa:

I recall I had trouble getting a USB HID keyboard to work in OS X, but haven’t tried this project on a Mac. So unfortunately I cannot much help with this one, other than keeping thumbs up. :(