MAQUINA DE ESTADOS CON INTERRUPCIÓN INTERNA PARA ARDUINO DUE

Buenas noches a todos
Quiero compartir con ustedes algo que hice para aprender a realizar maquina de estados con interrupción interna.
Está funcionando en Arduino Due con un display Robot.
Utilice estas librerías
#include <LiquidCrystal.h>
#include <DueTimer.h>
Se trata de una idea simple, un led que parpadea a un ritmo y este se modifica según el botón que se mantenga presionado, incluso se puede modificar en forma independiente el tiempo de encendido y apagado.
Al hacerlo con interrupciones internas no hay demoras en el funcionamiento, ya que no se utiliza la función Delay.
Por otro lado la máquina de estados permite separar las funciones que debe realizar el programa.
En estado de reposo el display indica "opciones listas " y "normal"
Al presionar el botón de arriba el display indica " rápido" y el led acelera su ritmo.
El botón de abajo lo hace mas lento.
El de la izquierda lo mantiene permanentemente prendido.
El de la derecha lo apaga.
Por último el segundo de la izquierda lo hace asimétrico, el tiempo prendido es menor al apagado.
Modificando esta estructura se puede utilizar en varios proyectos.
Espero que sea útil.

MAQUINA DE ESTADOS.zip (13.1 KB)

Este es el código. Cuando no es muy grande es mejor postearlo a ponerlo en un archivo zipeado que pocos veremos.

 #include <LiquidCrystal.h>
 #include <DueTimer.h>
 
  LiquidCrystal lcd(8, 9, 4, 5, 6, 7);           // DEFINE LOS PINES PARA EL DISPLAY

  int timer_1=0;
  int timer_2=0;
  int timer_recarga_1=0;
  int timer_recarga_2=0;
  unsigned char estado=0;
  unsigned char estado_1=0;
  unsigned char estado_2=0;
  unsigned char flag_1=0;
  unsigned char flag_2=0;
  unsigned char prendido=1;
  unsigned char apagado=0;
  int lcd_key =0;
  int adc_key_in  = 0;

  #define btnRIGHT  0
  #define btnUP     1
  #define btnDOWN   2
  #define btnLEFT   3
  #define btnSELECT 4
  #define btnNONE   5

//RUTINA DE INTERRUPCION DE TIMER

void irq_timer() {			//ENTRA CADA VEZ QUE SE PRODUCE UNA INTERRUPCION DE TIMER
	timer_1--;   			//DEFINE EL TIEMPO DE TIMER 1
	if (timer_1<=0) 
		flag_1=1;

	timer_2--;    			//DEFINE EL TIEMPO DE TIMER 2
	if (timer_2<=0)
	flag_2=1;
}

//FUNCION PARA LEER LOS BOTOS TIENEN RESISTENCIAS, VARIAN EL VALOR DE TENSION EN LA ENTRADA ANALOGICA CERO

int read_LCD_buttons()   {                                     
    adc_key_in = analogRead(0);       // LEE LOS VALORES DE LA ENTRADA ANALOGICA Y LOS GUARDA EN LA VARIABLE adc_key_in

    if (adc_key_in > 1000) return btnNONE; // VALOR SIN APRETAR NADA
    
    if (adc_key_in < 50)   return btnRIGHT;  // VALORES PARA LOS DIFERENTES BOTONES Y LO QUE DEVUELVE LA FUNCION SI SE CUMPLE LA CONDICION 
    if (adc_key_in < 250)  return btnUP; 
    if (adc_key_in < 450)  return btnDOWN; 
    if (adc_key_in < 650)  return btnLEFT; 
    if (adc_key_in < 1000)  return btnSELECT;  
    return btnNONE;                // CUANDO TODOS FALLAN DEVUELVA ESTE
}

//MAQUINA DE ESTADO UNO LA FUNCION ES PRENDER Y APAGAR EL LED
void maquinaEstado_1(void) {
	
	switch(estado_1) {
	    case 0: //CUANDO EL ESTADO VALE 0
	        digitalWrite(53, prendido);   // PRENDE LED SE UTILIZA LA VARIABLE prendido PARA PODER MODIFICARLA MAS ADELANTE
	        timer_1 = timer_recarga_1;
	        flag_1 = 0; 
	        estado_1 = 1;
	        break;
	    case 1:
	        if(flag_1 == 1)
	        	estado_1 = 2;  
	        break;
	    case 2:
	        digitalWrite(53, apagado);   // APAGA LED SE UTILIZA LA VARIABLE apagado PARA PODER MODIFICARLA MAS ADELANTE
	        timer_2 = timer_recarga_2;
	        flag_2 = 0; 
	        estado_1=3;
	        break;
	    case 3:
	        if(flag_2==1)
	        	estado_1 = 4;  
	        break;
	    case 4:
	        estado_1 = 0;
	        break;
    }
}

// MAQUINA DE ESTADO DOS MODIFICA LOS TIMER PARA CAMBIAR EL RITMO DEL LED PRENDIDO Y APAGADO EN FORMA INDEPENDIENTE Y EL TEXTO SEGUN EL BOTON
void maquinaEstado_2(void) {
   switch (lcd_key)   {             // DEPENDE DEL BOTON APRETADO ENTRA EN EL CASE

       case btnRIGHT:             	//  PARA BOTON DERECHO EL LED QUEDA APAGADO PERMANENTE 
	       lcd.setCursor(0,1); 		//UBICA EL CURSOR EN LA POSICION UNO DE LA SEGUNDA FILA
	       lcd.print("     APAGADO    "); 
	       digitalWrite(53, LOW); 
	       prendido=0;
	       apagado=0;        
	       break;
       case btnLEFT:			    //  PARA BOTON IZQUIERDO LED ENCENDIDO PERMANENTE
	       	lcd.setCursor(0,1); 
	       	lcd.print("     FIJO       ");
	       	digitalWrite(53, HIGH); 
	       	prendido=1;
	       	apagado=1;  
	       	break;
       case btnUP:                 //  PARA BOTON DE ARRIBA TITILA RAPIDO
	       	lcd.setCursor(0,1); 
	       	lcd.print("     RAPIDO     "); 

	       	timer_recarga_1=150;
	       	timer_recarga_2=150;
	       	break;
        case btnDOWN:              //  PARA BOTON DE ABAJO TITILA LENTO
       		lcd.setCursor(0,1); 
       		lcd.print("     LENTO      ");  
       		timer_recarga_1=1000;
       		timer_recarga_2=1000;
       		break;
       case btnSELECT:                   //  BOTON SELECCION NO UTILIZADO
	       	lcd.setCursor(0,1); 
	       	lcd.print("   ASIMETRICO  "); 
	       	timer_recarga_1=200;
	       	timer_recarga_2=1200;
	       	break;
       case btnNONE:                  //  CUANDO NO HAY BOTON APRETADO TITILA INTERMEDIO
	       	lcd.setCursor(0,1); 
	       	lcd.print("     NORMAL     "); 
	       	timer_recarga_1=500;
	       	timer_recarga_2=500;
	       	prendido=1;
	       	apagado=0; 
	       	break;
   }
}

void setup() {

        pinMode(53, OUTPUT);             //DEFINE EL PIN DONDE ESTA EL LED Y LO PONE COMO SALIDA
        lcd.begin(16, 2);               // DEFINE DISPLAY DE 16 * 2
        
        Timer3.start(1000);               // INTERRUMPE CADA 1mS
        Timer3.attachInterrupt(irq_timer); // LLAMA A LA RUTINA DE INTERRUPCION
}

void loop()  {

  	lcd_key = read_LCD_buttons();   // GUARDA EN LA VARIABLE (LCD_KEY) LO QUE RETORNA LA FUNCION QUE LEE LOS BOTONES
 	lcd.setCursor(0,0);            // EL CURSOR A LA PRIMERA POSICION DEL PRIMER RENGLON 
 	lcd.print("OPCIONES LISTAS");  // ESCRIBE EN EL DISPLAY 
  	maquinaEstado_1();            // VA A EJECUTAR LA MAQUINA DE ESTADOS UNO
  
  	maquinaEstado_2();            // VA A EJECUTAR LA MAQUINA DE ESTADOS DOS
}

Muchas gracias por tu aporte, es mi falta de experiencia.
Gracias