Peter's electronic projects

USB digital I/O extender


description

Add general purpose input/output lines to your computer based projects. This project is a 12-bit digital I/O extender using the Microchip PIC18f14k50 microcontroller which connects to an USB host port. The microcontroller is available in through-hole DIP20 and SMD packages, too.
NOTE for beginners: PIC18F14k50 is a general purpose microcontroller which has to be programmed before you can use it in the actual circuit! Please check out this link to learn more.

USB interfaceUSB interfaceUSB interface

Circuit diagram

The device is powered by the USB bus. The ports RB4-7, RC0-7 can be set on a bit-by-bit basis to input or output direction. All LEDs on the schematic are optional, and are only shown for testing the device. You can find the USB connector pinouts at http://pinouts.ws/usb-pinout.html
I can send you pre-programmed microcontrollers or fully assembled, tested boards. If you are interested, contact me


USB digital I/O extender schematic

Controlling the I/O extender

A computer or an embedded RISC board with an USB host port can be used to control the I/O extender. The controlio example code uses libusb. This means that you don't need a kernel driver to interface with it.
The controlio example code can be invoked with these parameters:
command line
description
controlio getport
read the digital I/O port states
controlio setdir <n>
set the digital I/O port directions. Use bit 1 to set direction to input, bit 0 to set direction to output
<n> is a 16-bit decimal number between 0-65535
controlio setport <n>
set the digital I/O port output states. Sets all output I/O pins. Use bit 1 to set output to HIGH, 0 to set output to LOW
<n> is a 16-bit decimal number between 0-65535
controlio setbit <n>
set the selected digital I/O port output pins to HIGH. Use bit 1 to select I/O pins to set
<n> is a 16-bit decimal number between 0-65535
controlio clearbit <n>
set the selected digital I/O port output pins to LOW. Use bit 1 to select I/O pins to clear

Mapping of I/O port pins, directions to parameter <n> and buffer output:
controlio getport output
buffer[0]
buffer[1]
I/O pin
RC7
RC6
RC5
RC4
RC3
RC2
RC1
RC0
RB7
RB6
RB5
RB4
-
-
-
-
controlio setport <n>
controlio setdir <n>
controlio setbit <n>
controlio clearbit <n>
bit#7
bit#6
bit#5
bit#4
bit#3
bit#2
bit#1
bit#0
bit#15
bit#14
bit#13
bit#12
bit#11
bit#10
bit#9
bit#8

Examples:
command line example
explanation
controlio setdir 65535
set all I/O pins as input
controlio getport
Read the digital I/O port states. The buffer is 16 bit long, and is shown in hexadecimal. Output ports usually read back the state they are set to. Input ports read their externally set state.
Command output is:
OK: buffer length = 2
Buffer: ff f0
controlio setdir 0
set all I/O pins as output
controlio setport 0
set all output I/O pins LOW
controlio setport 12
set the RC2 and RC3 I/O pins HIGH,  other output pins LOW (works only on output pins)
controlio setbit 32768
set the RB7 output pin HIGH, don't change other output pins (works only if RB7 is an output pin)
controlio clearbit 4097
set the RB4 and the RC0 output pins LOW, don't change other output pins (works only if RB4 and RC0 are output pins)

USB requests

The circuit is a full speed (12Mbit) vendor-specific USB device. It uses only the control endpoint 0, and is controlled by vendor-specific control requests. If you want to make your own host interface, the implemented control requests are:
name
setup bmRequestType
setup bRequest
setup wValue
setup wLength
response
GETPORT
USB_TYPE_VENDOR, USB_ENDPOINT_IN, USB_RECIP_DEVICE
0x53
unused
8
2 bytes, I/O port states
SETPORT
USB_TYPE_VENDOR, USB_ENDPOINT_OUT, USB_RECIP_DEVICE
0x54
I/O port states <n>
0
0 bytes ACK
SETDIR
USB_TYPE_VENDOR, USB_ENDPOINT_OUT, USB_RECIP_DEVICE 0x55
I/O port directions <n>
0
0 bytes ACK
SETBIT
USB_TYPE_VENDOR, USB_ENDPOINT_OUT, USB_RECIP_DEVICE 0x56
I/O port pin selection <n>
0
0 bytes ACK
CLEARBIT
USB_TYPE_VENDOR, USB_ENDPOINT_OUT, USB_RECIP_DEVICE 0x57
I/O port pint selection <n>
0
0 bytes ACK

You can find the explanation of these requests under "controlling the I/O extender"

Compiling the host side code under Linux

- install a C compiler and the libusb development headers
yum install gcc libusb-devel # for redhat/fedora
apt-get install gcc libusb-dev # for debian/ubuntu
- compile the code
cd c; cc -o controlio controlio.c -lusb
- check operation with the command
./controlio getport

Compiling the host side code for openwrt

- install the Openwrt SDK on a computer
- a package/usbio/Makefile is being made (not yet ready, please ask for it if you need). Copy files from usbio.zip c/ directory to the SDK package/usbio/src/
- download the libusb library
svn co svn://svn.openwrt.org/openwrt/packages/libs/libusb
- select the libusb library and the usbio package to be built
make menuconfig
- build the libusb and usbio packages
make package/libusb/compile V=99
make package/usbio/compile V=99

Compiling the host side code under windows

- download and install mingw and msys from mingw.org
- extract files from usbio.zip c/ directory to c:\mingw\msys\1.0\home\<user> where user is your user name
- if your OS is Vista, Win 7 or later, modify the controlio.c source code, and delete these 5 lines from it:
    if (usb_claim_interface(udev, 0) < 0)
    {
        printf("Unable to claim interface\n");
        exit(-1);
    }
                            
- download and install libusb-win32 from sourceforge
- copy include/lusb0_usb.h from the libusb package to c:\mingw\msys\1.0\include\usb.h
(if your libusb-win32 version is 1.2.4 or older, then copy include/usb.h to c:\mingw\msys\1.0\include\usb.h)
- copy lib/gcc/libusb.a from the libusb package to c:\mingw\msys\1.0\lib
- start the mingw shell from programs->mingw->mingw shell
- compile the code with
gcc -o controlio controlio.c /lib/libusb.a -I/include
- connect the USB device to the computer
- start bin/inf-wizard from the libusb package
- select the connected device from the list, then create and install a driver for it
- find the executable controlio.exe under c:\mingw\msys\1.0\home\<user> where user is your user name
- check operation with the command
 controlio getport

Download

Download usbio.zip, contents:
directory
description
c/
source code for the USB host, please check section "controlling the I/O extender"
pic18f14k50/
source code and compiled HEX file (firmware) for the Microchip pic18f14k50 microcontroller

Planned improvements

Please contact me if you need a feature, or have an idea.

related projects

References

feedback

Please contact the author if you found an error, incomplete or missing documentation, or you have trouble making this circuit work.

Your e-mail address (optional):

Message: