Little Robot

This is part two of a series.  Part one covered the hardware build.  Part three will cover the python based host software.

Without any further ado:

Firmware

This entire project was based around Objective Development's V-USB product -- an open source software USB implementation. Among the AVR community, it seems to be reasonably well used, and has a nice selection of reference projects.

From the outset, I knew one robot -- the one for my desk -- would be talking to a linux or macintosh computer. However, my fiancé's robot would have be happy in windows. Unfortunately, windows devices require kernel device drivers, with a very few exceptions; the most abused being the Human Interface Device profile. So why buck a trend? HID it is.

With that in mind, two existing projects seem most useful.

  • 1-Key Keyboard -- the original hardware base for the little robots -- is naturally firmware compatible. In fact the belly switch of each robot does indeed work as a keyboard switch. This is a full bidirectional HID device.
  • The HID-Data example included in the V-USB distribution. This is a much simpler application -- it allows a host application to set and read the EEPROM storage in an AVR. It is unidirectional -- all interaction is initiated by the host controller.

I chose to build off the HID-Data example as it was somewhat simpler, and did come with example host software. From there, little modification was needed; I integrated the timer calibration code from the 1-key keyboard, and added some hardware PWM support.

Every interaction is controlled from the host. For example, the microcontroller counts individual button presses. The host then sends a request to read that value. The microcontroller returns the value, and then resets the counter.

Full firmware and software is available via GitHub.

Servo Control

Servos are controlled via pulse width modulation. Many microcontrollers do have hardware PWM support, and the ATtiny85 is no exception. However, all of its timers have an 8-bit resolution. For my purposes, this is acceptable, but provides only about 25 steps from one end of the servo's range to the other. This works out to be about seven degrees a step. Better resolution would require a software timer.

I find with the small servos I have handy, the low end of the servo's sweep comes in at around 11, and the high end anywhere from 35 to 40.

void pwm_set( int x ) {
    OCR0B = x;
}
 
void pwm_init( void ) {
    // Set non-inverting output mode on pin OC0B.
    TCCR0A = ( 1 << COM0B1 ) | ( 0 << COM0B0 );
 
    // Set fast pwm mode.
    TCCR0A |= ( 1 << WGM01 ) | ( 1 << WGM00 );
    TCCR0B = ( 0 << WGM02 );
 
    // Use /1024 Prescaler.
    // This sets a PWM frequency of ~48Hz,
    // which is just about perfect for a servo.
    TCCR0B |= ( 1 << CS02 ) | ( 0 << CS01 ) | ( 1 << CS00 );
}

Lessons Learned

  • Include a programming header on a development board. For every firmware revision I had to pop the AVR out, reprogram it, and reinstall it. As simple as the process is, it gets old real quick.
  • Chip self-protection features are your friend. For example, under-voltage detection and hardware watchdog timers are very useful. When a computer -- especially a laptop -- reboots, it may brown out devices on the USB bus. A microcontroller may come back up in an undefined state. One of the robots burnt out a servo when it flaked out on a reboot.
  • Embedded software is actually fun to write! It's simple, clean and very scope limited. Perfect for a satisfying hobby project.