Serial USB For Any AVR Microcontroller

If you’re using an AVR microcontroller and you’d like to add USB to a project, there are a lot of options out there for you. Both LUFA and V-USB add some USB functionality to just about every AVR micro, but if you’d like a native serial port, your only options are to look towards the USB-compatible Atmel micros.

[Ray] looked at the options for adding a USB serial port and didn’t like what he saw; seemingly, this was an impossible task without a second, more capable microcontroller. Then he had an idea: if the goal is only to transfer data back and forth between a computer and a microcontroller, why not write an HID-class USB serial port?

[Ray] based his project on The V-USB library and created a new HID descriptor to transfer data between a micro and a computer. While it won’t work with a proper terminal such as Putty, [Ray] managed to whip up a serial monitor program in Processing that’s compatible with Windows, Linux and OS X.

In the video below, you can see [Ray] using an ATmega328p with a standard V-USB setup. He’s transferring analog values from a photoresistor as a proof of concept, but just about everything that would work with a normal serial port will work with [Ray]’s library.

30 thoughts on “Serial USB For Any AVR Microcontroller

  1. I’m confused. The goal was to implement serial port type behavior, but without actually appearing as a serial port to the attached computer? Can’t he just use the regular HID stuff?

    1. The USB serial profile is only available to full speed devices, while software USB on V-USB etc is only low speed. HID profile is available at low speed, so he implemented serial-over-HID.

      1. Hello,

        Actually you can cheat. The problem is that the serial port uses burst transfers, which require full speed or better. However, some operating systems happily let a low speed device use bulk transfer. I seem to remember BSD and Windows made no problems about it (was not me who did the testing), linux has a test somewhere that you can easily remove (look for error in dmesg, search for error in kernel source, comment out).

        Also, nothing would stop you to make a real driver for this ‘HID-USB’ device, then it would appear as an actual serial port ;)

    2. Now if only someone were to could write a user mode program that
      redirect the HID traffic to named pipes in windows that communicate with
      a virtual serial port program such as HDD’s “Free Virtual Serial Port”.

      This would let your custom HID (or vendor mode) USB device appears as a
      serial port to any program. The best part is that it does not require
      turning off Driver Signature Enforcement.

  2. This isn’t a serial port, it’s just your standard HID comms. No CDC class here. Was never intended to be seen as a serial port by the OS, the article never makes that claim.

    1. I was going to point readers to this; good to hear it from the OP.

      For those that haven’t gone to the link above, it’s on an ATtiny461 plus 4 passives, and the AVR receives commands but does not transmit.

    1. All of the solutions so far require some hacking as MS disabled low
      speed bulk transfer in newer versions of Windows. They also require one
      to compromise security by disabling “Driver Signature Enforcement” in
      win x64.

      trinket-fake-usb-serial is actually pretty close to my idea described
      above except the com0com program doesn’t have a signed driver for x64
      either. HDD’s “Free Virtual Serial Port” on the other hand has signed
      drivers for x86/x64. Probably a rewrite to the Python source code to use
      named pipe would work.

    1. What are you talking about, in single quantities, and is 33% more expensive!
      The ATmega8u2 with 8 KiB flash 22 IO pins costs 3.70.
      The ATmega382 with 32 KiB flash and 23 IO pins costs 2.77.
      The ATmega32u2 with 32 KiB flash and 22 IO pins costs 4.40.
      The ATmega32u4 with 32 KiB flash and 26 IO pins costs 6.05.
      and here’s the kicker,
      the ATtiny85 with 4/8 KiB flash and 6 IO pins costs 1.03/1.18.

      While doing a one off, it really doesn’t matter which chip you choose, but even here the ATmega8u2 is 3.6 times more expensive then an ATtiny84.

      It becomes really interesting if you take the pricebreak into account, getting 25 ATTiny’s isn’t a bad idea, they can be quite usefull for various fun projects, and then they cost 0.65/0.75 each when getting 25 (8u2 is 2.32, 382 is 1.25 and 32u2 is 2.76).

      So again, you get 1 micro for 1 USB project, paying 3.70 or 2.77 won’t matter much to you, but there is still quite a significant price difference here, so yeah, I’m quite happy with v-usb on my 0.75 cents ATtiny85’s :)

      1. Simply looking on Digikey, Atmega328P (for a 1 piece buying) starts at 2.88
        Freescale MKL26Z64VLH4-ND starts at 1.84 and is much more powerful and equipped for nearly half-the-price

        1. For a one off project the Freescale unit would be far more expensive. Not only do I need to buy / build a programming solution, but I would need to dedicate valuable time to learning a different platform, using a different set of tools in a likely different language.

          I’d take the extra $3-6 NOT to do that anyday.

        2. Thanks for the tip. I’ll keep that in mind for cheap USB OTG ARM chips.

          FYI That part is not in stock. Not to mention that the family come in a
          finer pitch (0.5 vs 0.8mm) than $1.2 ATmega8. 0.5mm pitch requires 10
          mil tracks with 10 mil spacing which is the limit on my toner transfer.

      2. ATmega328P @ Digikey – 2.35 euro
        LPC1343 @ futureelectronics – 2.40$

        LPC1343 is cool in this context because it does not require you to have any programmer to program it – it just shows up as a flash drive, you drop compiled firmware into it.

        When you go into tinys – yes, there is no way to get USB connectivity for the price point. But frankly, how much of the tiny is left for you after you put a USB stack on it? Not much probably.

        And again – what would you use serial for? Probably to read the debug output. There are bit banged serial solutions for tinys exactly for this.

        And BTW – cp2102 module on ebay – 2.30$

        Nevertheless, cool hack, go go go!

    2. In the past I’ve used Microchip’s PIC18F14k50. It’s very low-cost (less than a dollar for quantity more than 100) and has hardware USB. But for many open-source projects, it’s still valuable to base the work on avrs and Arduino — there are tons of existing libraries out there, saves a lot of time for development.

    1. Indeed.

      This should have been called something like “streaming over HID”. Calling it serial is either redundant (all comms over USB are serial), or inaccurate (since it’s not recognized as a CDC serial port by the host OS).

      And while this may be a good exercise in learning about V-USB, if you just need serial, get a $5 USB-to-serial adapter; rather than messing about with something so odd.

    2. What should you call it communication over USB for any AVR? Language is not some thing static, homonyms are very common. I believe tautology accusations are usually just a case of trying to be a smart arse. (like this comment).

      I had a similar problem as this project, with data not being delivered after running for a while. I solved it by checksumming all messages, ACK:ing, and storing it in flash on failure. Turned out I couldn’t send a specific 8 byte long message, if sent communications would be corrupted.

  3. I tries Vusb for serial port.. i gave up. It was sometimes loosing connection.
    I settled on two options: CP2102 modules from ebay for $2.x or FT230X or FT232R for things that need a nice PCB.

    I don’t think VUSB is that relevant now(it was a few years ago), there are plenty of micros with HW USB for about the same money.

  4. With vusb you can hook in a proper cdc-acm class. That will work for _most_ usb hosts, since it breaks the specs with bulk endpoints on a low-speed dev.
    Making it that way is simpler, I’ve done something like that, but I ended up writing a linux kernel module for the host part.

  5. Hi, please is there any particular reason D+ and D- are not hooked up to the TX and RX pins of the Atmega? I have seen a couple of circuits and in all of them, the D+ and D- are not connected to the RX, and TX pins. Thanks

Leave a Reply to ftoramaCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.