Ir al contenido principal

Semáforos y más semáforos

Que levante la mano quién no haya hecho el típico circuito de semáforo para probar una plataforma o un microcontrolador nuevo. El semáforo se podría considerar como el HolaMundo de la electrónica. Cualquier alumno de tecnología o de ingeniería podrá corroborar lo que digo.

Semaforos

Sobre este particular, José Antonio Vacas dio una interesante charla en Malakabot 2017 que os dejo aquí debajo.

Está claro que como ejemplo inicial, el semáforo puede ser un diseño útil, pero después hay que ir más allá. Si andáis faltos de imaginación, José Antonio os deja en su GitHub algunas ideas que os pueden servir de inspiración

Pero si pensabais que tras todo este movimiento se habían acabado los semáforos, estáis muy equivocados. Tras esto de los semáforos se encuentra un interesante reto propuesto por Cesar García del podcast La Hora Maker y David Cuartielles. Se trata de un proyecto colectivo para realizar semáforos en la mayor cantidad de modos posible. Dejo que ellos mismos os presenten el proyecto.

Si queréis participar sólo tenéis que acudir al GitHub de David y seguir las instrucciones. Yo por mi parte me he animado a enviar dos diseños: Uno con el TI MSP430 y otro con FreeRTOS.

El diseño del semáforo es muy simple y se muestra en el siguiente esquema, donde se indica a qué pines han de conectarse los LED. En este caso he usado una placa de desarrollo LaunchPad basada en el microcontrolador MSP430. También os dejo el código C del semáforo.

#include <msp430.h>
enum estados { ROJO, AMARILLO, VERDE };
int color;

int main(void)
{
	WDTCTL = WDTPW + WDTHOLD; 	// Detiene el watchdog
	P3DIR |= BIT0;            	// P3.0 (LED rojo) como salida digital
	P3DIR |= BIT1;            	// P3.1 (LED amarillo) como salida digital
	P2DIR |= BIT6;            	// P2.6 (LED verde) como salida digital
	P1REN |= BIT1;		  	// Resistencia en P1.1 (pulsador derecho)
	P3OUT |= BIT1;		  	// Modo pull-up
	P2OUT |= BIT1;
	P1IE  |= BIT1;			// habilita la interrupción de P1.1
	P1IES |= BIT1;			// Interrupción por flanco de bajada
	P1IFG &= ~(BIT1);		// baja flag de interrupción de P1.1 (por si acaso)
    color = ROJO;
	P3OUT |= BIT0; 			// Empezamos encendiendo el rojo
	P3OUT &= ~BIT1;			// apagamos el amarillo
	P2OUT &= ~BIT6;			// apagamos el verde
    // Activar interrupciones
	__bis_SR_register(GIE); 	// también puede usarse: __enable_interrupt()
    // Modo bajo consumo pero atendemos interrupciones
	__low_power_mode_0();		// Entrada LPM0, habilita interrupciones
	__no_operation();         	// Para depuración
    }
    
// Rutina de gestión de interrupciones de P1
#pragma vector=PORT1_VECTOR
__interrupt
void P1_ISR(void) {
	extern int color;
	if (P1IFG & BIT1) {		// ¿fuente de la interrupción es P1.1 (pulsador)?
		switch (color) {
			case ROJO:
				color = AMARILLO;
				P3OUT &= ~BIT0;	// apagamos el rojo
				P3OUT |= BIT1;	// encendemos el amarillo
				break;
			case AMARILLO:
				color = VERDE;
				P3OUT &= ~BIT1;	// apagamos el amarillo
				P2OUT |= BIT6;	// encendemos el verde
				break;
			case VERDE:
				color = ROJO;
				P2OUT &= ~BIT6;	// apagamos el verde
				P3OUT |= BIT0;	// encendemos el rojo
				break;
		}
		P1IFG &= ~BIT1;		// puesta a cero del flag de interrupción P1.1
	}
}

Para el ejemplo de semáforo con FreeRTOS he usado la placa de desarrollo LaunchPad CC3200 que utiliza una MCU ARM Cortex A4. El esquema de conexionado con la placa y el código son los siguientes.

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "hw_types.h"
#include "hw_ints.h"
#include "hw_memmap.h"
#include "interrupt.h"
#include "rom_map.h"
#include "prcm.h"
#include "gpio.h"
#include "pinmux.h"
#include "FreeRTOS.h"
#include "task.h"

// prototipos de función
void BoardInit(void);

// variables globales
extern void (* const g_pfnVectors[])(void);

//*****************************************************************************
// FreeRTOS User Hook Functions enabled in FreeRTOSConfig.h
//*****************************************************************************
void
vAssertCalled( const char *pcFile, unsigned long ulLine )
{
    //Handle Assert here
    while(1)
    {
    }
}

void vApplicationMallocFailedHook()
{
    //Handle Memory Allocation Errors
    while(1)
    {
    }
}

void vApplicationStackOverflowHook( void *pxTask,
                                   signed char *pcTaskName)
{
    //Handle FreeRTOS Stack Overflow
    while(1)
    {
    }
}

// Board Initialization & Configuration
void BoardInit(void)
{
// Set vector table base
    IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
    // Enable Processor
    MAP_IntMasterEnable();
    MAP_IntEnable(FAULT_SYSTICK);
    PRCMCC3200MCUInit();
}
  
/*-----------------------------------------------------------*/
//Esta tarea enceinde las luces del semáforo
static void SemaforoBlink( void *pvParameters )
{
//La tarea debe tener un bucle infinito...
	for( ;; )
	{
		// Encender LED rojo
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_3,GPIO_PIN_3);
		vTaskDelay(0.5*configTICK_RATE_HZ);
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_3,0);
        // Encender LED amarillo
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_2,GPIO_PIN_2);
		vTaskDelay(0.5*configTICK_RATE_HZ);
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_2,0);
        // Encender LED verde
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,GPIO_PIN_1);
		vTaskDelay(0.5*configTICK_RATE_HZ);
		GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_1,0);
	}
}
/*-----------------------------------------------------------*/

// Función main
void main()
{ 
	BoardInit();	// Configuración de la placa
    PinMuxConfig();	// Pinmux donde se configuras los puertos para los LED como salida digital
    // Apagamos los LED
    GPIOPinWrite(GPIOA1_BASE,GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1,0);
    
	/* creamos la tarea para el semaforo */
	if (xTaskCreate( SemaforoBlink, "Semaforo", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, NULL )!=pdPASS)
		while (1);
        vTaskStartScheduler(); // Inicia el planificador de tareas
}

Os animo a que participéis, ya que es un proyecto, además de interesante, bastante divertido.

Comentarios

Entradas populares de este blog

Creando firmas de virus para ClamAV

ClamAv es un antivirus opensource y multiplataforma creado por Tomasz Kojm muy utilizado en los servidores de correo Linux. Este antivirus es desarrollado por la comunidad, y su utilidad práctica depende de que su base de datos de firmas sea lo suficientemente grande y actualizado. Para ello es necesario que voluntarios contribuyan activamente aportando firmas. El presente artículo pretende describir de manera sencilla cómo crear firmas de virus para ClamAV y contribuir con ellas a la comunidad.

Ingeniería inversa de un parche de Microsoft Windows

A estas alturas ya hemos asumido que la seguridad total en Internet es, cuanto menos, un mito. Ningún software está libre de vulnerabilidades, y por mucha auditoría, test de intrusión o pruebas de fuzzing que nos empeñemos en hacer, ninguna metodología puede demostrar sin lugar a dudas que un software es 100% seguro. Ante este panorama, hay dos tendencias mayoritarias a la hora de hacer públicas las vulnerabilidades. Por un lado, están los que piensan que cuando se descubre un fallo ha de hacerse público de forma inmediata. En este escenario, la publicación de una vulnerabilidad es el pistoletazo de salida para una carrera entre el desarrollador para sacar el parche y los "malos" para lograr explotarla. Esta política es conocida como full disclosure . Por otro lado, tenemos a los siguen una política responsible disclosure , que abogan por mantener la vulnerabilidad en secreto hasta la salida del parche por parte del desarrollador. Sin entrar en cuestiones filosóficas que no...

Manejo de grafos con NetworkX en Python

El aprendizaje computacional es un área de investigación que en los últimos años ha tenido un auge importante, sobre todo gracias al aprendizaje profundo (Deep Learning). Pero no todo son redes neuronales. Paralelamente a estas técnicas, más bien basadas en el aprendizaje de patrones, también hay un auge de otras técnicas, digamos, más basadas en el aprendizaje simbólico. Si echamos la vista algunos años atrás, podemos considerar que quizá, la promesa de la web semántica como gran base de conocimiento ha fracasado, pero no es tan así. Ha ido transmutándose y evolucionando hacia bases de conocimiento basadas en ontologías a partir de las cuales es posible obtener nuevo conocimiento. Es lo que llamamos razonamiento automático y empresas como Google ya lo utilizan para ofrecerte información adicional sobre tus búsquedas. Ellos lo llaman Grafos de Conocimiento o Knowledge Graphs . Gracias a estos grafos de conocimiento, Google puede ofrecerte información adicional sobre tu búsqueda, ad...