# Control de reles por puerto paralelo usando Pascal



## enigmaelectronica (Jul 5, 2011)

*Control de reles por puerto paralelo usando Pascal*

este es uno de mis viejos aportes y no quiero que quede olvidado en algun servidor...

Este es un proyecto en el cual a menudo mezclamos la electronica con la programacion, uniendolas con interfases, que en este caso, son por medio de un optoacoplador.

La idea se basa en poder controlar una serie de 8 dispositivos [por lo general luces] en una casa o algun lugar donde se requiera el control de la electricidad por medio remoto.

En internet puedes buscar mi compilacion de Turbo pascal 7, que viene parcheada y lista para ser usada sin correr el riesgo del temible error BSOD de DOS: 
ERROR 20 DIVISION BY CERO 

Porque funciona para procesadores de mas de 1 GHz en modo DOS normal, asi que puedes buscar en Google si quieres 

Porque elegir Pascal?

1)Primeramente porque es un lenguaje facil y rapido.
2)Al momento de compilar no se necesita de librerias.
3)Para este proyecto no usaremos una potente computadora
4)Puede usarse el ejecutable sin necesidad de instalarse primero, sin siquiera tener que usar algun sistema operativo, al menos con que tenga MS-DOS es suficiente.


*Diagrama de la Interfase*

Aqui tenemos la interfase que usaremos para conectarla al puerto paralelo de la computadora:

Cabe aclarar que debemos hacer 8 de estos circuitos para poder controlarlos con el programa que mas adelante les dejo. 


Es mas sencillo este circuito aunque digan lo contrario, en mi opinion, este circuito es mas facil de probar que confundirse con la puesta de los transistores...

Para la conexion:

Realicen 8 de estos circuitos, luego coloquen la entrada (R1) a cada pin de salida del puerto paralelo, del pin 2 al pin 9. 

El puerto debe trabajar con la direccion 378h Base 1 en la direccion $0040 y segmento 0008
osea el puerto LPT1.

Si desean saber como trabaja, tanto este puerto, como otros, busquen mi post sobre libros de electronica o de programacion y acceso a puertos.

Primero descargate el compilador de Pascal, mas adelante les dare el enlace 

Ahora empecemos por el asunto, Conozcamos la interfase:

Usando Circuitos integrados se la empresa motorola, que por su sencillez no deja de darnos cosas utiles como el "PASAJE POR CERO" y una tension de aislamiento cercano mayor a los 1 KiloVoltios.

el MOC usado es el 3040 (o su equivalente MOC3041) o un alternativo tambien como el siguiente diagrama:

El valor de R1 depende de la tension de entrada, R1 = 1000 

(Uin - 1,3) / ILED (mA)


donde: 
Uin se expresa en Voltios
R1 esta en Ohmios
ILED es la corriente que circula por el diodo LED en el optoacoplador expresada en mili Amperios.

ejemplo:
Uin = 12
ILED = 30 mA como en el MOC3040
R1 es en total = 356 Ohmios, estandar buscado cercano es de 330 Ohmios

12 - 1.3 = 10.7 
10.7 / 30 = 0.356 = 356 Ohmios 

Ahora sabemos que el puerto paralelo nos da un valor TTL de 5 voltios aplicamos la formula matematica para el calculo de la resistencia que el MOC3040 usara:

5 - 1.3 = 123 Ohmios = aproximandolo a un valor comercial nos da 125 Ohmios en R1

Ahora que tenemos los calculos procederemos a la programacion:

aqui esta el codigo fuente: si desean modificarlo. Si lo desean, tambien pueden descargarlo, si se desean ahorrar todo el trabajo de compilacion mas abajo del codigo fuente.


*Codigo Fuente (algunas librerias no se usan, pueden eliminarlas)*


```
uses DOS,graph,Crt,SVGA256,Txt;

label 100;
var
graphdriver,graphmode:integer;
nombre: string[17];
Font: array[0..767] of byte;
clave,Ch:char;
p: word absolute $0040:0008;
a,b,c,d,e,f,g,h: integer;
{----------------------------------------------------------------------------}

procedure inicio;
begin;
textbackground(blue);
clrscr;
gotoxy(17,10);
textcolor(white);
writeln('iniciando ambiente grafico, espere unos segundos');
gotoxy(10,30);
writeln('Por favor ingresa tu nombre para mostrarlo mas adelante');
gotoxy(10,33);
writeln('como usuario durante el programa');
writeln;
gotoxy(44,33);
textcolor(white);
textbackground(blue);
gotoxy(45,33);
read(nombre);
gotoxy(44,33);
delay(300);
clrscr;
end;

procedure Titulo;
begin
SetMode(1);
Bar(0,0,320{ancho horizontal},200{ancho vertical},blue{color fondo});
Print2(10,5,62,'Laboratorios Enigma software');{9 es violeta 16 es negro}
Print2(10,10,62,'');
Print2(30,50,62,' CONTROL PORT ');

Print2(10,160,62,' Presiona la Tecla [Enter]');
Print2(10,185,62,'(c)Gerson Enigma Guatemala 2005');
Ch:=ReadKey; Ch:=#0;
{este es el fondo principal del programa}
Bar(0,0,320,200,blue{color fondo});
Bar(2,2,316,20,9 {bluelight color fondo});
bar(2,186,316,18,9); {fondo de mensajes esc y F11}
bar(2,2,3,199,9);
bar(316,2,3,199,9);

Print2(115,10,62,'Control Port');
Print2(90,190,65,nombre);
print2(5,190,62,'Operador: ');
bar(7,35,220,88,black); {fondo de interruptores}
end;
{----------------------------------------------------------------------------}
procedure iniciodatos; {todos los bits a cero}
begin
delay(100);
port[p]:=0;
a:=0;
b:=0;
c:=0;
d:=0;
e:=0;
f:=0;
g:=0;
h:=0;
delay(100);
end;

procedure status;
begin
print2(85,25,65,'Estado');
Print2(5,126,65,' ');

print2(5,125,65,'[F1] terminal 1 [F7] Terminal 7');
print2(5,135,65,'[F2] Terminal 2 [F8] Terminal 8');
print2(5,145,65,'[F3] Terminal 3 [F9] Selec. Todos');
print2(5,155,65,'[F4] Terminal 4 [F10] Menu Ayuda ');
print2(5,165,65,'[F5] Terminal 5 ');
print2(5,175,65,'[F6] Terminal 6 [ESC] Salir');
end;

procedure instrucciones;
begin
end;

{----------------------------------------------------------------------------}
procedure estado;
begin

if port[p] = port[p]-1 then bar(10,40,200,10,black); print2(10,40,62,'interruptor [1] apagado');
if port[p] = port[p]+1 then bar(10,40,200,10,black); print2(10,40,62,'interruptor [1] Encendido');
if port[p] <> -1 or +1 then bar(10,40,200,10,black); print2(10,40,62,'interruptor [1] Data Error');

if port[p] = port[p]-2 then bar(10,50,200,10,black); print2(10,50,62,'interruptor [2] apagado');
if port[p] = port[p]+2 then bar(10,50,200,10,black); print2(10,50,62,'interruptor [2] Encendido');
if port[p] <> -2 or +2 then bar(10,50,200,10,black); print2(10,50,62,'interruptor [2] Data Error');

if port[p] = port[p]-4 then bar(10,60,200,10,black); print2(10,60,62,'interruptor [3] apagado');
if port[p] = port[p]+4 then bar(10,60,200,10,black); print2(10,60,62,'interruptor [3] Encendido');
if port[p] <> -4 or +4 then bar(10,60,200,10,black); print2(10,60,62,'interruptor [3] Data Error');

if port[p] = port[p]-8 then bar(10,70,200,10,black); print2(10,70,62,'interruptor [4] apagado');
if port[p] = port[p]+8 then bar(10,70,200,10,black); print2(10,70,62,'interruptor [4] Encendido');
if port[p] <> -8 or +8 then bar(10,70,200,10,black); print2(10,70,62,'interruptor [4] Data Error');

if port[p] = port[p]-16 then bar(10,80,200,10,black); print2(10,80,62,'interruptor [5] apagado');
if port[p] = port[p]+16 then bar(10,80,200,10,black); print2(10,80,62,'interruptor [5] Encendido');
if port[p] <> -16 or +16 then bar(10,80,200,10,black); print2(10,80,62,'interruptor [5] Data Error');

if port[p] = port[p]-32 then bar(10,90,200,10,black); print2(10,90,62,'interruptor [6] apagado');
if port[p] = port[p]+32 then bar(10,90,200,10,black); print2(10,90,62,'interruptor [6] Encendido');
if port[p] <> -32 or +32 then bar(10,90,200,10,black); print2(10,90,62,'interruptor [6] Data Error');

if port[p] = port[p]-64 then bar(10,100,200,10,black); print2(10,100,62,'interruptor [7] apagado');
if port[p] = port[p]+64 then bar(10,100,200,10,black); print2(10,100,62,'interruptor [7] Encendido');
if port[p] <> -64 or +64 then bar(10,100,200,10,black); print2(10,100,62,'interruptor [7] Data Error');

if port[p] = port[p]-128 then bar(10,110,200,10,black); print2(10,110,62,'interruptor [8] apagado');
if port[p] = port[p]+128 then bar(10,110,200,10,black); print2(10,110,62,'interruptor [8] Encendido');
if port[p] <> -128 or +128 then bar(10,110,200,10,black); print2(10,110,62,'interruptor [8] Data Error');

end;

procedure keys;

begin
estado;
repeat
begin
ch:=readkey;
if (ch = #0) then Begin
ch:= readkey;
case ch of

#59: begin {F1}
a := a+1;
if frac(a/2) = 0 then
begin
bar(10,40,210,10,black);
print2(10,40,62,'interruptor [1] apagado');
port[p]:=port[p]-1
end
else
begin
bar(10,40,210,10,black);
print2(10,40,62,'interruptor [1] Encendido');
port[p]:= port[p]+1
end;
end;

#60: begin {F2}
b := b+1;
if frac(b/2) = 0 then
begin
bar(10,50,210,10,black);
print2(10,50,62,'interruptor [2] apagado');
port[p]:=port[p]-2
end
else
begin
bar(10,50,210,10,black);
print2(10,50,62,'interruptor [2] Encendido');
port[p]:= port[p]+2
end;
end;

#61: begin {F3}
c := c+1;
if frac(c/2) = 0 then
begin
bar(10,60,210,10,black);
print2(10,60,62,'interruptor [3] apagado');
port[p]:=port[p]-4
end
else
begin
bar(10,60,210,10,black);
print2(10,60,62,'interruptor [3] Encendido');
port[p]:= port[p]+4
end;
end;

#62: begin {F4}
d := d+1;
if frac(d/2) = 0 then
begin
bar(10,70,210,10,black);
print2(10,70,62,'interruptor [4] apagado');
port[p]:=port[p]-8
end
else
begin
bar(10,70,210,10,black);
print2(10,70,62,'interruptor [4] Encendido');
port[p]:= port[p]+8
end;
end;

#63: begin {F5}
e := e+1;
if frac(e/2) = 0 then
begin
bar(10,80,210,10,black);
print2(10,80,62,'interruptor [5] apagado');
port[p]:=port[p]-16
end
else
begin
bar(10,80,210,10,black);
print2(10,80,62,'interruptor [5] Encendido');
port[p]:= port[p]+16
end;
end;

#64: begin {F6}
f := f+1;
if frac(f/2) = 0 then
begin
bar(10,90,210,10,black);
print2(10,90,62,'interruptor [6] apagado');
port[p]:=port[p]-32
end
else
begin
bar(10,90,210,10,black);
print2(10,90,62,'interruptor [6] Encendido');
port[p]:= port[p]+32
end;
end;

#65: begin {F7}
g := g+1;
if frac(g/2) = 0 then
begin
bar(10,100,210,10,black);
print2(10,100,62,'interruptor [7] apagado');
port[p]:=port[p]-64
end
else
begin
bar(10,100,210,10,black);
print2(10,100,62,'interruptor [7] Encendido');
port[p]:= port[p]+64
end;
end;

#66: begin {F8}
h := h+1;
if frac(h/2) = 0 then
begin
bar(10,110,210,10,black);
print2(10,110,62,'interruptor [8] apagado');
port[p]:=port[p]-128
end
else
begin
bar(10,110,210,10,black);
print2(10,110,62,'interruptor [8] Encendido');
port[p]:= port[p]+128
end;
end;

#70: {[F11]}
begin
bar(7,35,210,88,black); {fondo de interruptores}
print2(10,40,62,'Creado por ');
print2(10,60,62,'Gerson Hernandez');
print2(10,90,62,'(c) 2005 enigma');
end;

#68 : {[F10]}
begin
instrucciones;
titulo;
keys;
end;

#67: {[F9]}
begin
bar(7,35,210,88,black); {fondo de interruptores}
print2(10,40,62,'Encenderlos Todos [F2]');
print2(10,50,62,'Apagarlos Todos [F3]');
print2(10,60,62,'Regresar [Esc]');
print2(10,80,62,'Estado Actual:');
repeat
begin
ch:= readkey;
case ch of
#60:
begin {F2}
bar(10,100,210,10,black);
print2(10,100,62,'Todos Encendidos');
port[p]:=255;
end;
else
begin
bar(10,100,210,10,black);
print2(10,100,62,'Todos Apagados');
port[p]:= 0 ;
end;
end;
end;
until ch = #27;
bar(7,35,210,88,black); {fondo de interruptores}
keys;



end;
end;
end;
end;
until ch in [#27];
end;





procedure salir;
begin
Bar(0,0,320{ancho horizontal},200{ancho vertical},Blue{color fondo});
print2(19,50,62,'Saliendo del programa');
print2(90,120,62,' Cerrando Sesion');
print2(10,186,62,'Creado por Gerson Hernandez (c)2005');
sound(2700);
delay(100);
nosound;
Delay(700);

end;
{------------Main Program------------}

begin
FileRead('0808art.fnt',0,96,8,Font);
InstallFont(1,8,8,32,96,8,Font);
iniciodatos;
inicio;
Titulo;
status;
keys;

salir;
{ Ch:=ReadKey; Ch:=#0;}

end.
```

Notas Finales 

La interfase del optoacoplador se debe poner a los pines siguientes del puerto paralelo:
El programa usa librerias en modo Grafico si no las tienen o no las quieren usar quiten lo que no es interese
Pines de datos:

[2][3][4][5][6][7][8][9]

Los pines del 18 al 25 se conectan todos juntos a Masa (0 Voltios = GND) y los restantes pines no se usan.

Quieren las cosas faciles?
Entonces les dejo el programa ya compilado:
Filename: PORT.rar
Filesize: 8 kB (se espera que tengas la direccion 378h de tu Bios en el puerto paralelo con la funcion bidireccional como minimo)

No funciona en Windows vista / Win7

ejecutarlo con DOS


----------

