Monday, January 19, 2015

Controlling Microchips 18F4550 as HID Custom USB device using python pyUSB

The MLA( Microchip Libraries for Applications ) ships with a MPLABX project for 18F4550 that makes the chip behave like a HID Custom device. i built the project, burnt the hex file, and was also able to test it using the plug_and_play executable provided for Linux

As per this project, there is 1 interface with 2 endpoints.
One is IN, other is OUT. Both are of type INTERRUPT.
( See usb_descriptors.c )

For the commands, see app_device_custom_hid.c.
The commands are :
  • COMMAND_TOGGLE_LED = 0x80 -- LED on RD0
  • COMMAND_GET_BUTTON_STATUS = 0x81 -- Button on RB4, pressing should bring it to Ground
  • COMMAND_READ_POTENTIOMETER = 0x37 -- ADC_CHANNEL_0

Commands should be sent on the OUT endpoint, and data received on the IN.


i wanted to write my own code to control the device. came across the pyusb framework, which looked easy to use.

Here is working code for the first 2 commands :
import usb.core
import usb.util
import sys

# find our device
dev = usb.core.find(idVendor=0x04d8, idProduct=0x003f)

# was it found?
if dev is None:
    raise ValueError('Device not found')

interface = 0

if dev.is_kernel_driver_active(interface) is True:
            print "but we need to detach kernel driver"
            dev.detach_kernel_driver(interface)

# set the active configuration. With no arguments, the first
# configuration will be the active one
dev.set_configuration()

# get an endpoint instance
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]

for cfg in dev:
    sys.stdout.write("ConfigurationValue:" + str(cfg.bConfigurationValue) + '\n')
    for intf in cfg:
        #print vars(intf)
        sys.stdout.write('\t' + \
                         "InterfaceNumber:" + str(intf.bInterfaceNumber) + \
                         ',' + \
                         "AlternateSetting:" + str(intf.bAlternateSetting) + \
                         '\n')
        for ep in intf:
            #print vars(ep)
            sys.stdout.write('\t\t' + \
                             "EndpointAddress:" + str(ep.bEndpointAddress) + \
                             '\n')

assert ep is not None

# toggle the led. COMMAND_TOGGLE_LED
# args : ep, value, timeout
dev.write( 1, chr(128), 100)

# read the button state. COMMAND_GET_BUTTON_STATUS
# first send the command on EP_OUT
dev.write( 1, chr(129), 100)
# read on EP_IN
ret = dev.read( 129, 100)
print "Received: %d,%d", ret[0], ret[1]
print "Button Status : " + "Released" if ret[1] == 1 else "Pressed"


No comments:

Post a Comment