![]() |
Víctor R. González
Angelberto Mieres
<< Diseñar y construir la maqueta de un puente que se eleve al paso de un vehículo acuático, atravesado por una calzada de un solo sentido cuyo tráfico esté regulado por dos semáforos sincronizados. El ciclo de los semáforos y la apertura del puente deberán realizarse mediante control programado >>.
La propuesta anterior da libertad a la hora de elegir el sistema actuador que procura la apertura y cierre del puente, así como la propia estructura del mismo. También, acerca de la forma concreta mediante la que debe realizarse el control de los dispositivos.
El proyecto está pensado para ser realizado de forma cooperativa entre los distintos grupos de taller de un curso de 4º de E.S.O., dado que abarca muy diversos aspectos constructivos y de control.
Dentro de la propuesta anterior caben muchos tipos de soluciones para los distintos aspectos constructivos. Así se harán las siguientes elecciones:
La maqueta consta de un puente de dos hojas atravesado por una calzada cuyo cruce se halla regulado por dos semáforos (ver plano general). Las hojas se elevan gracias a dos cilindros neumáticos de doble efecto cuyas carreras se activan mediante electroválvula 5/2 y se ajustan mediante válvulas unidireccionales reguladoras de caudal (ver circuito neumático). Cuenta con un zumbador que actúa como sirena cuando el puente se halla elevado. El control de la activación del ciclo de los semáforos, de la sirena, y de la elevación y recogida de las hojas del puente se programa utilizando las líneas del puerto paralelo.
La elevación del puente se puede llevar a cabo manualmente, mediante la pulsación de las teclas +/- en el teclado o mediante la pulsación de dos pulsadores rojo/negro situados en la propia maqueta. Asimismo, se puede realizar mediante la activación de una puerta óptica (elaborada con un diodo emisor/receptor de infrarrojos propio de los sistemas de mando a distancia de TV) situada en el vano del puente cuando ésta es atravesada por un barco.
El estado por defecto del puente consiste en un ciclo repetitivo verde-ámbar-rojo que es interrumpido cuando el sensor óptico o el control manual (pulsadores y/o teclado) se activan, para producir la elevación del puente. Ésta termina cuando el barco deja de detectarse en la puerta óptica o cuando lo decide el control manual.
Puesto que el control se realizará directamente mediante el puerto paralelo del PC hay que realizar una elección de las líneas de entrada y salida del mismo que se utilizarán. En las siguientes figuras se recoge la estructura física del conector DB25, así como la distribución de líneas.


En el circuito de control que se instalará en la maqueta se situará un conector macho como el de la figura de la izquierda, que irá conectado al hembra del PC (fig. izquierda) mediante un cable de extensión.

Las líneas de entrada/salida del conector se describen en la siguiente figura:

Estas líneas se reparten entre los registros de datos (D), Estado (S) y Control (C) del puerto como se muestra a continuación:

La conexión de actuadores y sensores a las líneas del puerto paralelo se resume en la tabla que figura a continuación. Los detalles concretos del control se pueden seguir a través de los comentarios insertados en el código fuente del programa utilizado.
|
Líneas del puerto |
|||
| Actuadores digitales |
Sirena | 2 | bit 1 de Datos (D0) |
| Semáforos LED rojo-verde | 3 | bit 2 de Datos (D2 | |
| Semáforos LED verde-rojo | 4 | bit 3 de Datos (D3) | |
| Semáforos LED ámbar-ámbar | 5 | bit 4 de Datos (D3) | |
| Electroválvula: subir (ELV1) | 6 | bit 5 de Datos (D4) | |
| Electroválvula: bajar (ELV2) | 7 | bit 6 de Datos (D5) | |
| Sensores digitales |
Detector de IR | 10 | bit 6 de Estado (S6) |
| Pulsador rojo (subir) | 11 | bit 7 de Estado (S7) | |
| Pulsador negro (bajar) | 12 | bit 5 de Estado (S5) | |
| Otros (*) | Alimentación de pulsadores | 9 | bit 7 de Datos (D0) |
(*) Se pone la línea 9 en nivel alto por programa para alimentar a +5V el circuito de los pulsadores rojo y negro.
Los sensores se conectan a las líneas de entrada del puerto paralelo en la forma que se esquematiza en la figura siguiente:

Los actuadores se conectan mediante una etapa de potencia proporcionada por transistores (para un relé, por ejemplo):

La forma exacta de conectar cada actuador y sensor figura en el plano del circuito de control y potencia.
Los detalles constructivos y de funcionamiento del sistema se recogen en una colección de películas, en lugar de en planos de despiece y detalles.

![]()
Ç
![]()

El código de control utilizado se esquematiza en el diagrama de
flujo de la siguiente figura. El proceso principal contiene una repetición de
ciclos de semáforo que sólo finaliza cuando la variable en_marcha
se establece a NO (FALSO). Durante el tiempo de espera en el que el semáforo
permanece de cada color, se comprueba continuamente el estado del teclado y de
los sensores para detectar la presencia de barco en el detector de infrarrojos o
una acción de control manual por parte del usuario. Todo ello se lleva a cabo
en el subprograma ESPERA que admite un argumento que es
precisamente el tiempo de espera en segundos.

El listado del código fuente es:
/* PUENTE.C Control de un puente levadizo accionado neumáticamente, mediante puerto paralelo 2002 Víctor R. González - Angelberto Mieres */ #include <stdio.h> #include <dos.h> #include "paralelo.h" #define APAGADO 0x00 /* D0-D7, pin 2-9, desactivados */ #define SIRENA 0x01 /* D0, pin 2, zumbador */ #define ROJO 0x02 /* D1, pin 3, LED */ #define VERDE 0x04 /* D2, pin 4, LED */ #define AMBAR 0x08 /* D3, pin 5, LED */ #define PUENTE_SUBE 0x10 /* D4, pin 6, electroválvula */ #define PUENTE_BAJA 0x20 /* D5, pin 7, electroválvula */ #define PULSA_ALIM 0x80 /* D7, pin 9, alimentación pulsadores */ #define BARCO_VIENE 0x0 /* S6, pin 10 alto, detector IR */ #define PULSA_SUBIR 0x0 /* S7#,pin 11 bajo, pulsador n/c de subida */ #define PULSA_BAJAR 0x0 /* S5, pin 12 bajo, pulsador n/a de bajada */ /* El estado normal de los sensores (desactivados) es: S7#=1, S6=1, S5=1 */ #define T_ROJO 5 /* duración (en segundos) de la luz roja */ #define T_VERDE 5 /* duración (en segundos) de la luz verde */ #define T_AMBAR 2 /* duración (en segundos) de la luz ambar */ #define T_PARPADEO 400 /* duración (en milisegundos) del parpadeo de la luz ambar */ #define T_SUBIDA 3 /* duración (en segundos) de la elevación del puente */ #define T_BAJADA 3 /* duración (en segundos) de la bajada del puente */ #define T_ESPERA 10 /* período (en milisegundos) de atención al teclado */ /* Activa las señales adecuadas del puerto */
#define Activa(valor) if (en_marcha) {outportb (DATOS, valor | PULSA_ALIM); printf("Enviado: 0x%X\n", valor);}
#define SensorSubir() (inportb (ESTADO) & 0x80) /* Toma sólo bit 7 de ESTADO */
#define SensorBarco() (inportb (ESTADO) & 0x40) /* Toma sólo bit 6 de ESTADO */
#define SensorBajar() (inportb (ESTADO) & 0x20) /* Toma sólo bit 5 de ESTADO */
#define Apaga() outportb (DATOS, APAGADO) /* Desactiva las salidas */
int ParaleloIni (void);/* Detecta el puerto paralelo */ void Espera (float); /* Espera con atención al teclado y a las entradas digitales */ char en_marcha; /* Indica el funcionamiento o el fin del proceso */ void main (void)
{
/* Realiza el control si se detecta el puerto paralelo */
if ( ParaleloIni() != LPT_NINGUNO ) {
Activa (PULSA_ALIM); /* Activa alimentación circuito pulsadores */ en_marcha = TRUE; /* Secuencia periódica de los semáforos
esperando suceso de teclado o entrada digital */
do {
Activa (VERDE); Espera (T_VERDE); Activa (AMBAR); Espera (T_AMBAR); Activa (ROJO); Espera (T_ROJO); } while( en_marcha ); Apaga(); /* Apaga las señales del puerto */ }
else {
printf ("No se encuentra ningún puerto paralelo\n");
exit(1);
}
}
/*
Realiza una espera activa de <t> segundos.
Atiende al teclado y a las entradas digitales cada 10 ms
*/
void Espera (float t)
{
int t_max = 1000*t; /* tiempo a esperar (en ms) */
int crono = 0; /* tiempo transcurrido (en ms) */
int periodo= T_ESPERA;
int tecla, sens_barco, barco = FALSE;
char puente_arriba = FALSE;
/* Espera hasta que se agota el crono */
while (en_marcha && crono < t_max) {
if ( kbhit() ) tecla = getch(); /* Comprueba teclado */ sens_barco = SensorBarco(); /* Comprueba presencia del barco */ if (tecla == '+' || SensorSubir() == PULSA_SUBIR || (!barco && sens_barco == BARCO_VIENE)) {
if (sens_barco == BARCO_VIENE) barco = TRUE;
/* Eleva las hojas del puente */
for (crono=0; crono< 1000*T_SUBIDA; crono += 2*T_PARPADEO) {
Activa (SIRENA + PUENTE_SUBE + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA + PUENTE_SUBE);
delay (T_PARPADEO);
}
Activa (SIRENA);
puente_arriba = TRUE;
tecla = 0;
crono = 0;
} else
if( tecla == '-' || (!barco && SensorBajar() == PULSA_BAJAR) || (barco && sens_barco != BARCO_VIENE)) {
barco = FALSE;
/* Baja las hojas del puente */
for (crono=0; crono< 1000*T_BAJADA; crono += 2*T_PARPADEO) {
Activa (SIRENA + PUENTE_BAJA + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA + PUENTE_BAJA);
delay (T_PARPADEO);
}
Apaga();
puente_arriba = FALSE;
tecla = 0;
crono = t_max; /* Sale del modo espera */
} else
if( tecla == 'f' ) {
/* Finaliza; si el puente está elevado, lo baja */
if (puente_arriba) {
Activa (PUENTE_BAJA);
delay (1000*T_BAJADA);
}
en_marcha = FALSE;
} else if (puente_arriba) {
/* Si el puente sigue elevado, la sirena suena y las luces ambar parpadean */
Activa (SIRENA + AMBAR);
delay (T_PARPADEO);
Activa (SIRENA);
delay (T_PARPADEO);
} else {
/* Espera hasta nueva comprobación de teclado y pulsadores */ delay (periodo); crono += periodo; } } } /* Identifica los puertos paralelos instalados en el PC Devuelve (ver paralelo.h): LPT_NINGUNO: si no hay puertos instalados LPT_OTROS : si el primer puerto es de tipo desconocido LPT_SPP : si el primer puerto es SPP LPT_BIDIR : si el primer puerto es bidireccional LPT_EPP : si el primer puerto es EPP LPT_ECP : si el primer puerto es ECP */ int ParaleloIni (void) { unsigned int PuertoNum, Puerto, NumPuertos; unsigned int Byte, tmp; char PuertoEPP; int PuertoTipo; char *PuertoNombre[]={"", "Estandar (SPP)", "Bidireccional", "EPP", "ECP"}; /* Busca la dirección de E/S de los puertos instalados */
NumPuertos = 0;
PuertoTipo = LPT_NINGUNO;
for (PuertoNum=1; PuertoNum<=3; PuertoNum++) {
_lpt_dir[PuertoNum] = peek(0x0040,0x0008 + (PuertoNum-1)*2);
if (_lpt_dir[PuertoNum] == 0)
printf ("No se encuentra puerto asignado a LPT%d \n", PuertoNum);
else {
printf ("La dirección asignada a LPT%d es 0x%X\n", PuertoNum, _lpt_dir[PuertoNum]);
NumPuertos++;
}
}
if (NumPuertos > 0 ) {
/* Detecta el tipo de puerto del primero hallado */
printf ("\nPuerto seleccionado: LPT%d en 0x%X. ", LPT_NUM, LPT_BASE);
/* Prueba puerto ECP */
Byte = inportb (CONTROL_EXT) & 0x03; /* toma bits 0 y 1 de CONTROL_EXT */
if (Byte == 1) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte ^ 0x03); /* pone a 0 los bits 0 y 1 de CONTROL */
Byte = inportb(CONTROL_EXT) & 0x03;
if (Byte == 1) PuertoTipo = LPT_ECP;
outportb (CONTROL, tmp); /* restaura CONTROL */
}
/* Prueba puerto EPP */
if (!PuertoTipo) {
PuertoEPP = FALSE;
if (LPT_BASE != 0x03BC) {
Byte = inportb (ESTADO);
tmp = Byte;
outportb (ESTADO, Byte & (~0x01) ); /* Pone a 0 el bit 0 de ESTADO */
for (Puerto=REG_EPP_PRI; Puerto<=REG_EPP_ULT; Puerto++) {
outportb (Puerto, 0x55);
Byte = inportb (Puerto);
if (Byte == 0x55) {
outportb (Puerto, 0xAA);
Byte = inportb (Puerto);
PuertoEPP = (Byte == 0xAA);
if (!PuertoEPP) break;
}
}
outportb (ESTADO, tmp); /* restaura bit 1 de ESTADO */
}
if (PuertoEPP) PuertoTipo = LPT_EPP;
}
/* Prueba puerto SPP */
if (!PuertoTipo) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0x55);
Byte = inportb (DATOS);
if (Byte == 0x55) {
outportb (CONTROL, Byte | 0x20 ); /* Pone a 1 el bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0xAA);
Byte = inportb (DATOS);
if (Byte == 0xAA) PuertoTipo = LPT_SPP;
}
outportb (CONTROL, tmp); /* Restaura el bit 5 de CONTROL */
}
/* Prueba puerto bidireccional */
if (!PuertoTipo) {
Byte = inportb (CONTROL);
tmp = Byte;
outportb (CONTROL, Byte | 0x20 ); /* Pone a el 1 bit 5 de CONTROL (entrada de DATOS)*/
outportb (DATOS, 0x55);
Byte = inportb (DATOS);
if (Byte != 0x55) {
outportb (CONTROL, Byte | 0x20 ); /* Pone a el 1 bit 5 de CONTROL (entrada de DATOS) */
outportb (DATOS, 0xAA);
Byte = inportb (DATOS);
if (Byte != 0xAA) PuertoTipo = LPT_BIDIR;
}
outportb (CONTROL, tmp); /* Restaura el bit 5 de CONTROL */
}
if (PuertoTipo) {
printf("Puerto tipo: %s (%i)\n", PuertoNombre[PuertoTipo], PuertoTipo);
/* Pone DATOS en modo salida */ DATOS_out(); /* Pone las salidas en bajo */ outportb (DATOS, 0x00); /* reg. de DATOS */ outportb (CONTROL, inportb (CONTROL) & 0xFB); /* nibble bajo del reg. de CONTROL */ } else {
PuertoTipo= LPT_OTROS; /* Puerto de tipo desconocido */
printf("Puerto de tipo desconocido\n");
}
} /* NumPuertos > 0 */ return( LPT_TIPO = PuertoTipo ); } |