Back

How to build a cheap USB on off relay

Summary

This is a step by step guide on how to build a cheap USB relay (around $3) that can turn the USB port power on and off from software.

Basic idea

The idea came from the famous lava lamp alert system where you can switch a power socket on and off. I thought it sounded like a fun project but $40 was a bit too much considering I was just playing around. So I decided that I would try to build the USB relay as cheap as possible where I could turn the power of an USB port on and off by software.

That way you can be alerted by your favorite USB toy when your server is running out of diskspace, if your build server says the build is broken or whatever you decide.

Limitations

Since the USB data signal is used to communicate with the serial port this project will only run on dumb USB toys that does not require any data signals but will just run when they get some power.

First try failed

First attempt was to dig deep into windows registry and see if it was possible to disable a USB port. But, alas, that is not possible. Apparently the USB ports are always on in order to power the devices that will be connected. So I decided to go for hardware instead.

Tools

Required parts

I bought the parts on ebay for less than $3 including free shipping.

Description on how to build it

So I had to do it by hardware and I chose to use a USB to serial port since they are very cheap. You can buy one for $2 on ebay including an extension cable and free delivery. The MOSFET I used cost around $1. It is fairly easy to build since there is only three parts to connect. The basic idea is to send a signal to the serial port which will trigger the MOSFET.

The diagram below shows how to connect the three parts:

So let's get started!

Step by step guide

Step 1

Cut the serial cable around 15 cm from the serial adapter and find the ground and +5V wires. The +5V wire is usually red while the ground will be black. Solder some extra wires on ground and +5V and connect the four wires again.

Step 2

Solder a wire to pin 3 of the serial cable

Step 3

Connect the wire from pin3 to the left leg of the MSOSFET called Gate

Step 4

Connect the +5V wire from step 1 to the middle leg of the MOSFET called Drain

Step 5

Connect a wire from the right leg of the MOSFET called Source.

Step 6

Cut the USB extension cable and throw away the male part. Now connect the +5V of the female part to the wire from step 5. Connect the ground leg of the USB to the ground wire from step 1.

Testing the USB relay

You should now have a working USB relay. To test it first connect the male USB to your computer. You should get a "found new hardware" and the driver should be downloaded automatically:

Now connect your favorite USB toy.

Then download Realterm or some similar software that can change the pins of a serial port. Select the correct port in the port tab:

Finally go to the pins tab and click on the "set break" and "clear break":

You should now see your USB toy turn on and off.

Source code for java

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
//http://yengal-marumugam.blogspot.dk/2012/04/serial-port-manipulation-in-java.html
//http://www.cloudhopper.com/opensource/rxtx/
//http://rxtx.qbang.org/wiki/index.php/Download#x64_Binaries

/**
 * Connects to a serial port and turns the USB power on or off
 * 
 * @author theis.borg
 * 
 */
public class USBOnOffSwitch {

  public static boolean keepRunning = true;
  public static boolean off = true;
  SerialPort serialPort;
  static String detectedPort = "";

  /**
   * the main program that receives user input and a thread that communicates with the COM port
   * 
   * @param args
   */
  public static void main(String[] args) {
      new USBOnOffSwitch();
  }

  /**
   * detects all ports and uses the last detected serial port
   */
  static void detectPorts() {
    java.util.Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
    while (portEnum.hasMoreElements()) {
      CommPortIdentifier portIdentifier = portEnum.nextElement();
      if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) {
        detectedPort = portIdentifier.getName();
      }
      System.out.println("Found port: " + portIdentifier.getName() + " - " + getPortTypeName(portIdentifier.getPortType()));
    }
    if (detectedPort.equals("")) {
      System.out.println("No serial ports found");
      System.exit(0);
    }
  }

  /**
   * writes the type of a COM port
   * 
   * @param portType
   * @return
   */
  static String getPortTypeName(int portType) {
    switch (portType) {
    case CommPortIdentifier.PORT_I2C:
      return "I2C";
    case CommPortIdentifier.PORT_PARALLEL:
      return "Parallel";
    case CommPortIdentifier.PORT_RAW:
      return "Raw";
    case CommPortIdentifier.PORT_RS485:
      return "RS485";
    case CommPortIdentifier.PORT_SERIAL:
      return "Serial";
    default:
      return "unknown type";
    }
  }


  /**
   * Starts a thread that handles communication to the COM port and receives 
   * user input in order to turn the USB power on or off
   */
  public USBOnOffSwitch() {
    detectPorts();
    // if you have multiple COM ports on your computer you may wish to connect to a specific one, i.e. connect("COM5");
    connect(detectedPort);   
    Thread portThread = new Thread(new Runnable() {
      public void run() {
        while (keepRunning) {
          if (off) {
            serialPort.sendBreak(500); // off
          }else{
            try {
              Thread.sleep(500);
            } catch (InterruptedException e) {
            }
          }
        }
        serialPort.close();
        System.out.println("Thread stopped");
      }
    });
    portThread.start();
    while (keepRunning) {
      try {
        System.out.println("Enter something (ON, OFF, STOP): ");
        BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
        String s = bufferRead.readLine();
        if (s.equalsIgnoreCase("ON")) {
          off = false;
        }
        if (s.equalsIgnoreCase("OFF")) {
          off = true;
        }
        if (s.equalsIgnoreCase("STOP")) {
          keepRunning = false;
        }
        System.out.println(s);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    System.out.println("USB on off stopped");
  }

  /**
   * Connects to the specified serial COM port
   * 
   * @param portName
   */
  void connect(String portName) {
    try {
      CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
      if (portIdentifier.isCurrentlyOwned()) {
        System.out.println("Error: Port is currently in use");
      } else {
        CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
        if (commPort instanceof SerialPort) {
          serialPort = (SerialPort) commPort;
          serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        } else {
          System.out.println("Error: Only serial ports are handled by this example.");
        }
      }
    } catch (Exception e) {
      System.out.println("Error: could not connect to port.");
      System.exit(0);
    }
  }
}

Next steps

Next step will be to implement a small web server so that the USB relay can be switched on and off from a build server.

Pictures