Saturday, January 17, 2015

USB interfacing for AVR microcontrollers

Since the release of V-USB, dozens of projects have been made that allow an AVR to communicate over USB.  USB data signals are supposed to be in the range of 2.8 to 3.6V, so there are two recommended ways to have an AVR output the correct voltage.  One is to supply the AVR with 3.3V power, and the other is to use 5V power but clip the USB data signal using zener diodes.  Most implementations of V-USB, like USBasp, use the zener diodes.  I'll explain why using a 3.3V supply should be the preferred method.

Pictured above is a capture of D- line on a chinese USBasp, showing one of the 1kHz SE0 idle pulses.  The idle voltage is close to the 2.8V limit because this particular USBasp uses a 2.2K pullup resistor to +5V.  Using a 1.5K pullup as is recommended on the V-USB site puts it closer to 3.2V, which is the high voltage level from the host.

To determine how the signal is read by the AVR, we can look at the ATmega8A input threshold graphs at section 28.8 of the datasheet.
The graph indicates with a 5V supply, any voltage over 2.65V will be read as a logic "1".  The next graph in the datasheet shows any voltage below 2.4V will be read as a logic "0".  Since signals from the host transition between 0 and 3.2V and not 5V, the AVR will interpret low signals as being longer than high signals.  With a fall time of about 115ns, the signal will drop to 2.4V (logic low) in about 29ns.  With a rise time of about 100ns, the signal will rise above 2.65V from 0V in about 83ns.  At 1.5mbps, both high and low bits should last 667ns, but instead a low bit will last 721ns and a high bit will last only 612ns.  This 18% difference in bit times reduces the margin of error V-USB has to work with.

With a 3.3V supply voltage to the AVR, the low signal will last almost 670ns, and the high will last a little more than 663ns, for a timing difference of just under 1%.  Besides significantly improving signal timing, using a 3.3V supply simplifies the USB interface circuit.  Obviously the zener diodes are no longer needed.  Additionally, the 68Ohm resistors which limit the current from the AVR through the zener diodes, are no longer necessary either.

An alternative to using a 3.3V regulator, which is described on the V-USB site, is to use 2 diodes in series to provide a drop of about 1.6V.  My preference is to use a medium-power red LED like the BR5379K, which doubles as a power LED.  At 5mA, the current draw of an ATmega8A running at 12Mhz and 3.6V, the BR5379K has a voltage drop of about 1.65V.  It has a maximum current of 50mA; more than enough to drive something like a nRF24l01+ module in addition to the AVR.