SISTEMAS MULTITAREA CON MÁQUINAS DE ESTADO
CONTROLADO EN ENCENDIDO/APAGADO DE UN LED CADA 100 ms CON MÁQUINAS DE ESTADO
Recordando el tutorial pasado, debemos definir cada tarea a realizar como una máquina de estados. En este ejemplo solo queremos realizar una única tarea (controlar el encendido/apagado de un led cada 100 ms) por lo tanto programaremos una única máquina de estados.
La programación de una máquina de estados consiste en usar la estructura de control switch case en la cual los casos posibles para este ejemplo serán solo dos: led encendio o led apagado.
const int ESTADO_LED_1_ENCENDIDO = 1;
const int ESTADO_LED_1_APAGADO = 2;
Debemos recordar también que la máquina irá conmutando entre sus posibles estados (los cuales deben ser definidos desde un inicio). Para realizar la conmutación se hará uso del timer 0 funcionando en modo ctc, el cual provocará una interrupción cada un 1ms.
Entonces, cada 1ms ocurre una interrupción y eso hará que automáticamente saltemos a la rutina de servicio de interrupcion. Dentro de esa rutina haremos que un contador de valor 100 se decremente cada vez que se ingrese a dicha rutina (lo cual quiere decir que este contador se decrementa cada 1ms y por ello su valor será cero cuando hayan pasado 100ms).
El valor del contador se irá verificando dentro del lazo void loop y servirá como condición para que la maquina de estados conmute de estado. Si el led estaba encendido entonces se apagará y si estaba apagado se encenderá
Aparentemente es mucho código para hacer parpadear un led;sin embargo, a futuro nos trae mas ventajas ya que podremos añadir mas tareas por realizar y estas se ejecutaran de manera independiente (definiendo cada tarea como una máquina de estados distinta). Entonces podriamos por ejemplo generar una melodia con tone mientras un led parpadea a 100ms, otro led parpadea a 200ms, sondeamos un pulsador con debouncing y monitoreamos un sensor con el adc. Ya en el siguiente tutorial veremos cómo incluir mas tareas a nuestro sistema.
el código:
#define t1 100
volatile unsigned int time1;
//variables para la tarea1
///////////////////////////////////////////////
const int PIN_LED_1 = 13;
const int ESTADO_LED_1_ENCENDIDO = 1;
const int ESTADO_LED_1_APAGADO = 2;
int estadoLed1 = ESTADO_LED_1_ENCENDIDO;
void controlarEstadoLed1();
void encenderled1();
void apagarLed1();
void inicializarLed1();
void controlarEstadoLed1Encendido();
void controlarEstadoLed1Apagado();
void configTimer0();
ISR(TIMER0_COMPA_vect)
{
if(time1>0) --time1;
}
void setup()
{
inicializarLed1();
configTimer0();
}
void loop()
{
controlarEstadoLed1();
}
void configTimer0()
{
cli();//paramos interrupciones
//configurando timer0 para 1ms
TCCR0A = 0;// set entire TCCR0A register to 0
TCCR0B = 0;// same for TCCR0B
TCNT0 = 0;//initialize counter value to 0
// seteamos el registro de comparacion para lograr 1ms
OCR0A = 248;// = (16*10^6) / (2000*64) - 1 (must be <256)
// activamos modo CTC
TCCR0A |= (1 << WGM01);
// Seteamos CS01 y CS00 para usar pre-escalador en 64
TCCR0B |= (1 << CS01) | (1 << CS00);
// activamos interrupcion por comparación exitosa
TIMSK0 |= (1 << OCIE0A);
sei();//activamos interrupcion
}
//funciones definidas para la tarea1
//////////////////////////////////////////////
void controlarEstadoLed1()
{
switch (estadoLed1)
{
case ESTADO_LED_1_ENCENDIDO:
controlarEstadoLed1Encendido();
break;
case ESTADO_LED_1_APAGADO:
controlarEstadoLed1Apagado();
break;
}
}
void controlarEstadoLed1Encendido()
{
if (time1==0)
{
apagarLed1();
time1=t1;
estadoLed1 = ESTADO_LED_1_APAGADO;
}
}
void controlarEstadoLed1Apagado()
{
if (time1==0)
{
encenderLed1();
time1=t1;
estadoLed1 = ESTADO_LED_1_ENCENDIDO;
}
}
void inicializarLed1()
{
pinMode(PIN_LED_1, OUTPUT);
encenderLed1();
}
void encenderLed1()
{
digitalWrite(PIN_LED_1, HIGH);
}
void apagarLed1()
{
digitalWrite(PIN_LED_1, LOW);
}
Podemos realizar la simulación en proteus para confirmar que el led cambia de estado cada 100ms
0 comentarios:
Publicar un comentario