Controlar dispositivos por el puerto serie

Si alguna vez has pensado en controlar algún dispositivo desde tu PC puede que este truco pueda servirte. En este caso se activa o desactiva un rele, que a su vez actúa como un interruptor que permite encender o apagar "cualquier cosa" (una luz, una puerta automática, etc.).

Para realizar esto vamos a usar el puerto serie del PC, mas concretamente el pin RTS que en un conector de 9 pines es el numero 7. El circuito se ha reducido para que resulte sencillo y no utilice demasiados componentes, su funcionamiento es muy básico cuando activamos RTS tendremos una tensión positiva que activara el rele, si desactivamos RTS tendremos una tensión negativa y el rele volverá a su estado de reposo. (Siento no entrar en más detalles, intento no utilizar palabras técnicas para que todos puedan entenderlo, pero resulta difícil)

El circuito sería el siguiente (no es fácil dibujar con letras):

                                  V+
                                  |
                           +------+
                           |      |
                           _   -------
                        D2 ^  |   /   |  RELE
                           |   -------
                           |      |
                           +------+
                                  |
                                  | c
                                | /
        D1        R1            |/
RTS >--->|-+--/\/\/\/\----------|   T1
                 R2     |       |\
           +--/\/\/\/\--+       | \ e
           |                      |
GND >------+----------------------+-----< GND
 
R1,R2 10K
D1,D2 1N4007
T1 BC517
V+ 6V..12V

En cuanto al software, tenemos esta función que, pasándole como parámetros el puerto y el tiempo de espera en milisegundos, activa RTS y la mantiene activa durante el tiempo de espera para después volver a desactivarla.

function Activar_RTS(Puerto: String; Espera: Cardinal): String;
var
  hPort: THandle;
  DCB: TDCB;
begin
  Result:= '';
  Puerto:= Uppercase(Puerto);
  // Cambiar esto si es necesario un puerto diferente
  if (Puerto<>'COM1') and (Puerto<>'COM2') then
    exit;
  hPort:= CreateFile(PChar('\\.\'+Puerto), GENERIC_READ or GENERIC_WRITE,0, nil,
    OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if hPort<>INVALID_HANDLE_VALUE then
  begin
    DCB.DCBlength:= sizeof(DCB);
    if GetCommState(hPort,DCB) then
    begin
      with DCB do
      begin
        BaudRate := CBR_9600;
        ByteSize := 8;
        Parity   := NOPARITY;
        StopBits := ONESTOPBIT;
        Flags    := $01;
      end;
      if SetCommState(hPort, DCB) then
      begin
        EscapeCommFunction(hPort,SETRTS);
        Sleep(Espera);
        EscapeCommFunction(hPort,CLRRTS);
      end;
    end;
    CloseHandle(hPort);
  end;
end;

Ejemplo de uso:

  Activar_RTS('COM1',5000);

Ahora bien, seria interesante poder activar y desactivar el rele a discrepcion. Para eso, vamos a tener una funcion que lo encienda y otro que lo apague. Pues bien lo primero que tenemos que hacer es declarar la variable hPort como global, y separar la función de arriba en 4:

var
  hPort: Thandle;
 
procedure AbrirPuerto(Puerto: String);
var
  DCB: TDCB;
begin
  Puerto:= Uppercase(Puerto);
  // Cambiar esto si es necesario un puerto diferente
  if (Puerto<>'COM1') and (Puerto<>'COM2') then
    exit;
  hPort:= CreateFile(PChar('\\.\'+Puerto), GENERIC_READ or GENERIC_WRITE,0, nil,
    OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if hPort<>INVALID_HANDLE_VALUE then
  begin
    DCB.DCBlength:= sizeof(DCB);
    if GetCommState(hPort,DCB) then
    begin
      with DCB do
      begin
        BaudRate := CBR_9600;
        ByteSize := 8;
        Parity   := NOPARITY;
        StopBits := ONESTOPBIT;
        Flags    := $01;
      end;
      if SetCommState(hPort, DCB) then
        Exit;
    end;
    CloseHandle(hPort);
    hPort:= INVALID_HANDLE_VALUE;
  end;
end;
 
procedure CerrarPuerto;
begin
  if hPort <> INVALID_HANDLE_VALUE then
  begin
    CloseHandle(hPort);
    hPort:= INVALID_HANDLE_VALUE;
  end;
end;
 
procedure ActivarRTS;
begin
  if hPort <> INVALID_HANDLE_VALUE then
    EscapeCommFunction(hPort,SETRTS);
end;
 
procedure DesactivarRTS;
begin
  if hPort <> INVALID_HANDLE_VALUE then
    EscapeCommFunction(hPort,CLRRTS);
end;

Antes de usar el puerto tienes que llamar la función AbrirPuerto y cuando dejes de usarlo CerrarPuerto. Las funciones ActivarRTS y DesactivarRTS hacen lo que parece activar y desactivar RTS, para que funcionen el puerto tiene que estar abierto.

Comentarios

Listo amigo, funciona de maravilla, un millon de gracias

Buenas, amigo con este circuito puede encender una bomba de agua de 1/2 HP, el rele es de 5v/120v

No veo porque no, pero todo depende de las características del relé y de la bomba.

De todas formas para una aplicación profesional, te recomiendo que compres un dispositivo ya montado.

Por ejemplo este que, aunque no lo he probado, tiene buena pinta:
http://www.sigma-shop.com/product/7/usb-relay-controller-one-channel-box...

Desde una interfaz serial RS-232 (Tx, Rx y GND) puedo mandar strings de caracteres ya sean ASCII o Hexadecimal. Quiero que ese string me active un relé y otro string otro rele. ¿Como se puede hacer esto ?

Saludos y hasta pronto

Precisamente en el comentario anterior puse un enlace a un relé que funciona de esa manera:
http://www.sigma-shop.com/product/7/usb-relay-controller-one-channel-box...

Hola, de ante manos gracias por el proyecto, comento que realice el proyecto y trabaja muy bien aclaro que al principio no funcionaba por que tuve que usar 2 pin que es el 7 TRS y 5 GND, el GND que es lo mismo que el pin 5 la uni al GND de la fuente de voltaje osea los 2 GND unido.

Solo queria hacer esa aclaracion por que al principio pense que era solo un pin el numero 7 para lo que se confundieron al igual que YO una el pin 5 (GND) al negativo de la fuente externa que alimenta el circuito asi me trabaja,