Bernd-Ludwig's Website

Valid HTML 4.01 Strict Valid CSS!

Hardware >> Relay circuit

Relay on a Serial Port

The implementation described in this section allows controlling a relay over a serial port. For switching, the control signal DTR is used, which is assigned to pin 4 of a 9-pin serial interface. The RTS signal on pin 7 could also be used the same way.

The electrical diagram:

relay circuit diagram

As you can see at the diagram, the relay is not directly connected to the serial port, but there is a Darlington-transistor in between. To better protect the PC hardware, the transistor may be replaced by a suitably dimensioned optic coupler (IC ≥ 100 mA). The resistor R2 needs to be adapted to the coupler, of course.
The reason for the use of a transistor or optic coupler is that the output power of the serial port is not high enough to drive the relay directly. So an additional power supply has to be used. A voltage of 5V is sufficient for this and can be taken e.g. from the gameport. Other power sources could be a power cable for a disk drive or an external power supply. I do not recommend to use the USB for power supply. Standard USB ports are specified for currents up to 500mA, but firstly, there are also low-power USB ports for up to 100 mA, and secondly, the USB power management is based on the devices telling how much they consume when they register themaselves to the bus. A circuit which only uses USB as a power supply obviously cannot do this. In the worst case, this can damage the USB port or the controller.

One remark for the use on Windows-PCs: During the bootup, the Windows hardware detection causes that the relay is switched on and off a couple of times. The exact amount of switchings depends on the Windows version. According to my experience, the relay switches on and off once under Windows 98, while it switches on and off seven times under Windows XP.

Having finished the construction of the hardware, the next question is: How do I control this from a software?

Using DOS (and 16-bit-Windows, i.e. Windows 3.x) you can directly access the interface registers. Detailed information on this (which bits have to be set in which registers) can be found for example on www.franksteinberg.de (in german).

Using 32-bit-Windows (Win95 or newer) the operating system denies direct access to the registers (in Win95 this sometimes still works, but you should not rely on this). So the access to the serial port has to be done another way. In C++, you can use the modem control functions of the Windows API for this. To show how this works, here are some lines of code:

// Declaration of required variables
HANDLE hcom;
DCB dcb; //  "DCB" is a structure containing status information about the port
char *portname;
portname="COM1";

// Opening a handle for the port
hcom=CreateFile(portname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

// Reading the port status
GetCommState(hcom, &dcb);

// Set DTR to "HIGH"
dcb.fDtrControl=DTR_CONTROL_ENABLE;

// Writing the new port status
SetCommState(hcom, &dcb);

// Closing the handle (This sets DTR back to "LOW"!)
CloseHandle(hcom);

You can also find this in the C++ source code of the programs in my download area.

In Linux, you can also use modem control functions, but it looks slightly different:

// Needed Includes
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>

// Open the port (in this case the first serial port ttyS0)
int fd = open("/dev/ttyS0", O_RDWR);

// Set DTR to "HIGH" (might already happen when opening the port)
int state = TIOCM_DTR; ioctl(fd, TIOCMSET, &state);

// Set DTR to "LOW"
state = ~TIOCM_DTR; ioctl(fd, TIOCMSET, &state);

// Close the port
close(fd);

I have a linux program available in my download area (including source code).