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.
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
Publicar un comentario