Puente levadizo neumático gobernado mediante control programado

Víctor R. González
Angelberto Mieres

 

Propuesta

<< 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.

Volver al principio de página

 

Descripción

 

Dentro de la propuesta anterior caben muchos tipos de soluciones para los distintos aspectos constructivos. Así se harán las siguientes elecciones:

  1. Se dará al puente una estructura de doble hoja. 
  2. Para el sistema de elevación se diseñará y construirá un circuito neumático con cilindros de doble efecto cuyas carreras de entrada y salida accionen la subida y bajada, respectivamente, de las hojas del puente.
  3. El control programado se realizará directamente mediante el puerto paralelo de un PC, programado en lenguaje C.

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.

Volver al principio de página

 

Planos

 

 

 

Ç

 

Volver al principio de página

 

 

Programación

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 );
}

Volver al principio de página

 

Galería de películas con los detalles estructurales y funcionales del puente

Reproducir película que muestra la conexión al PC Reproducir película que muestra detalles constructivos
Conexión al PC Detalles constructivos
Reproducir película que muestra la detección óptica Reproducir película que muestra detalles de la apertura
Detección óptica de presencia de barco Detalles de la carrera de los cilindros
Reproducir secuencia de funcionamiento
Secuencia de funcionamiento -puente sin detector óptico-
(grabación con sonido pero con volumen muy bajo)

Volver al principio de página