In the Atmega 32u4 Based USB Controlled LED Series Project, it was demonstrated how to use control transfer to receive data from computer to the peripheral. In this project, it will be demonstrated to transfer data from microcontroller to the host computer. For this, the device will be configured as HID Class Device again. An HID Class device has USB communication over two types of transfers – Control transfer and Interrupt transfer. When data has to be exchanged from default endpoints i.e. endpoint 0 IN and endpoint 0 OUT only, the control transfer is sufficient to perform the data communication. Usually, HID devices only use control transfer for enumerating with the host. After enumeration, they send real-time data to the host computer using Interrupt Transfer for which additional endpoints are configured during enumeration process. In this project, an LED board will be designed and status of the LEDs will be transmitted to the host computer using Interrupt transfer.
The project will need a controller chip to handle USB data from the device to the host computer and to keep track of LED’s status in real-time. The 8-bit USB AVR – Atmega 32u4 is used as the device controller chip in the project. The project uses AVR based Lightweight USB Framework (LUFA) as the firmware which will be modified to implement the project’s functioning. The device is tested on a Linux system using Pyusb and Libusb frameworks for receiving data from peripheral device to the host computer.
The Generic HID device driver class of the LUFA firmware is used and modified to program the project. With the use of LUFA firmware, the device driver code to implement USB protocol is not needed to be written explicitly. Modifying the firmware code will be sufficient to implement the USB protocol. The device has two LEDs connected to it which will be operated ON or OFF by a tactile switch.
This project is based on Arduino Pro Micro which has the USB AVR – Atmega 32u4 as the sitting MCU. In order to understand this project, one must have basic knowledge of the AVR microcontrollers and the embedded C programming for AVRs. WinAVR Studio is used to write, edit and compile the project code, so closely following the project shall require familiarizing with the above stated IDE as well. Though LUFA framework takes care of implementing the USB protocol and has APIs to abstract the lower level codes, understanding USB protocol is recommended to understand how actually the project is working. In fact, if anyone has already worked on some other microcontroller, it will not be much pain to understand and follow this project as the project code is more or less about modifying the LUFA device driver to work as generic HID device. One must have additional knowledge of Linux operating system (Ubuntu) and should be knowing basic Linux commands. One having knowledge of Python programming language is recommended but not mandatory for implementing the project.
1. Arduino Pro Micro
3. Connecting wires
5. Tactile switch – 1
6. Micro USB cable
7. 10K resistors
SOFTWARE TOOLS REQUIRED
The project uses Arduino Pro Micro as the USB controller. A series of two LEDs is connected at the port B of the Arduino. The LEDs are connected at pins 4 and 5 of the port B. The 220 Ω pull up resistors are used to interface the LEDs. The LEDs are connected between the pins and the ground with anode connected to the pin and cathode connected to the ground. Therefore, when a HIGH logic is output from the pin, the LED starts glowing and when a LOW logic is output from the pin, the LED stops glowing. A tactile switch is connected at pin 2 of Port B between ground and the pin. The PB2 by default is connected to VCC through a 10 K Ω resistor. On pressing the switch, the pin is short circuited to the ground.
The Program code for the project is burnt to the Arduino Pro Micro using AVR Dude. The Arduino board is connected to the USB port of a PC by a USB cable.
HOW THE PROJECT WORKS
In this project the USB protocol is implemented by the LUFA framework. For configuring the controller chip to work as Generic HID device, the HID Class Driver of the LUFA framework will be used. The Human Interface Device (HID) class takes care of the transfers between the host device and the human controlled USB peripherals like USB Keyboard, Mouse or Joystick. However, the Generic HID device designed in this project uses Interrupt transfers to communicate LED status data to the host computer.
When a USB device is attached to the host (PC), the host sends request for configuration details in the form of control transfer. The connected device has to respond with appropriate descriptors to get configured and ready for further operations. Only after configuration, the device can communicate with the host in the form of interrupt, isochronous or bulk transfers for executing the operations for which the device has been made. This process of identification and configuration of the device with the host is called enumeration.
In case of this project, after configuring with the host device, it has to communicate with the host in the form of Interrupt transfers for sending data to the host computer. The Interrupt Transfer is always used for exchanging real-time data to the computer. The project uses interrupt transfer to communicate user-defined data packets to the computer. The data can be exchanged using Class-Specific Requests. These Requests are sent by Host to Device via Control Transfer. The Get_Report is the request by which Host can receive data from the device.
The project is based HID class driver of USB and LUFA framework has HID class related module in the LUFA-Source-Folder /LUFA/Drivers/USB/Class/Device folder. Other device class related module are also in the same folder. The LUFA framework has demo projects for different USB device classes in the LUFA-Source-Folder\Demos\Device\ClassDriver folder. For implementing the project, demo project for Generic HID devices provided in the LUFA framework will be modified and complied. The demo project for Generic HID devices is in the LUFA-Source-Folder\Demos\Device\ClassDriver\GenericHID folder. The folder contains GenericHID.c file which will be modified to implement the LED project.
How GenericHID.c identifies HID device being Generic HID device
The GenericHID.c uses Generic_HID_Interface interface in HID_Device_USBTask() function which is being imported from the HIDDeviceClass.c (from LUFA-Source-Folder \LUFA\Drivers\USB\Class\Device) to configure the device as generic HID device. The interface abstracts the low-level descriptor codes and identifies the device as generic HID device through an InterfaceNumber variable.
Generic HID Device Specific Report Descriptors
Any HID device has to exchange data with the host which should be structured in the form of reports. The report descriptor defines the report structure. A report descriptor contains the information needed by host to determine the data format and how the data should be processed by the host. Therefore, a report descriptor basically structure the data that needs to be exchanged with the host according to the USB protocol.
For working like a generic USB HID device, the device needs to send usage report descriptor specific to Generic HID Class to the host. The Usage Report informs the Host about the features or functionality of the USB device. An HID device sends data output report to the host computer for sending any data to it while it reads data input report to fetch data from computer to itself. The usage report and data reports are application layer features of USB protocol. In this project, data will be sent from device to the host so data input report will be utilized.
From Where GenericHID.C gets the USAGE and Data Reports Descriptors
In the LUFA framework’s demo project for GenericHID, GenericHID.h is imported. The GenericHID.h imports descriptor.c file which defines the relevant usage and data reports descriptors for the host device. The descriptor.c defines a GenericReport structure to generate generic HID usage and data reports descriptors. Inside descriptor.c the GenericReport  structure has the values returned by HID_DESCRIPTOR_VENDOR () function. The HID_DESCRIPTOR_VENDOR () is defined in HIDClassCommon.h (located in LUFA-Source-Folder\LUFA\Drivers\USB\Class\Common folder).
The GenericHID.c imports GenericHID.h which imports usb.h. USB.h imports HIDCLass.h. In HIDClass.h is imported HIDClassDevice.h if the USB_CAN_BE_DEVICE is true for the controller chip to being a USB device not the host. The HIDClassDevice.h imports HIDClassCommon.h where the HID device specific descriptor fields have been defined.
HID_DESCRIPTOR_VENDOR () returns the field values of the usage report descriptor, specific to generic HID device functioning. The fields are set to following values in HID_DESCRIPTOR_VENDOR ().
Read More: Atmega 32u4 Based LED Status