Autor Tema: Grafcets en Arduino. Encendido de dos ledes  (Leído 25386 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Carlos

  • Moderador Global
  • ****
  • Mensajes: 294
Grafcets en Arduino. Encendido de dos ledes
« en: 02/Ene/2020, 12:55:39 pm »
TAGS:
Implementar Grafcets en c.
Implementar Grafcets en Arduino.
Programación concurrente en Arduino.

Introducción:
Adjunto un programa para Arduino, en C, que implementa dos grafcets para encender y apagar dos ledes con dos pulsadores. Cada grafcet es independiente uno del otro y se ejecutan en paralelo.

Código: (c) [Seleccionar]
/*
 * Implementación de Grafcet
 * para encender dos ledes con dos pulsadores
 */

// Definiciones
#define NUMERO_DE_GRAFCETS  2
#define NUMERO_DE_ENTRADAS  2
#define NUMERO_DE_SALIDAS   2

#define PIN_LED_VERDE   2
#define PIN_LED_ROJO    3
#define PIN_PULSADOR_1  8
#define PIN_PULSADOR_2  9

#define PULSADOR_PRESIONADO  0
#define PULSADOR_REPOSO      1
#define LED_ENCENDIDO        1
#define LED_APAGADO          0


enum NOMBRE_GRAFCETS {
   GRAFCET_LED_VERDE,
   GRAFCET_LED_ROJO,
};
 
enum ENTRADAS_FISICAS {
   PULSADOR_1,
   PULSADOR_2,
};
 
enum SALIDAS_FISICAS {
   LED_VERDE,
   LED_ROJO,
};

typedef union  {
  struct {
    unsigned char etapa0: 1;
    unsigned char etapa1: 1;
    unsigned char etapa2: 1;
    unsigned char etapa3: 1;
    unsigned char etapa4: 1;
    unsigned char etapa5: 1;
    unsigned char etapa6: 1;
    unsigned char etapa7: 1;
  };
  unsigned char etapas;
} tipo_grafcet;


// Declaración de variables
tipo_grafcet grafcet[NUMERO_DE_GRAFCETS];
tipo_grafcet grafcet_siguiente[NUMERO_DE_GRAFCETS];
unsigned char entradas[NUMERO_DE_ENTRADAS];
unsigned char salidas[NUMERO_DE_SALIDAS];


// Programa principal
void setup(void) {
   setup_pines();
   grafcet_inicializar();
   while(1) {
      print_estado();
      leer_entradas();
      grafcets_evoluciona();
      escribir_salidas();
      temporizadores();
   }
}

void loop(void) {
}


//
// Funciones del programa principal
//

void setup_pines(void) {
   pinMode(PIN_LED_VERDE, OUTPUT);
   pinMode(PIN_LED_ROJO, OUTPUT);
   pinMode(PIN_PULSADOR_1, INPUT_PULLUP);
   pinMode(PIN_PULSADOR_2, INPUT_PULLUP);

   Serial.begin(9600);
}

void grafcet_inicializar(void) {
   grafcet_siguiente[GRAFCET_LED_VERDE].etapas = 0;
   grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;

   grafcet_siguiente[GRAFCET_LED_ROJO].etapas = 0;
   grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
}


void leer_entradas(void) {
   entradas[PULSADOR_1] = digitalRead(PIN_PULSADOR_1);
   entradas[PULSADOR_2] = digitalRead(PIN_PULSADOR_2);
}


void escribir_salidas(void) {
   digitalWrite(PIN_LED_VERDE, salidas[LED_VERDE]);
   digitalWrite(PIN_LED_ROJO, salidas[LED_ROJO]);
}


void grafcets_evoluciona(void) {
   grafcets_copiar_transiciones();
   grafcets_calcular_transiciones();
   grafcets_calcular_acciones();
}
 
 
void grafcets_copiar_transiciones(void) {
   grafcet[GRAFCET_LED_VERDE].etapas = grafcet_siguiente[GRAFCET_LED_VERDE].etapas;
   grafcet[GRAFCET_LED_ROJO].etapas = grafcet_siguiente[GRAFCET_LED_ROJO].etapas;
}


void grafcets_calcular_transiciones(void) {

   // GRAFCET_LED_VERDE
   if (grafcet[GRAFCET_LED_VERDE].etapa0 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa2 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa3 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
   }

   // GRAFCET_LED_ROJO
   if (grafcet[GRAFCET_LED_ROJO].etapa0 == 1 &&
       entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 1;
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
       entradas[PULSADOR_2] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa2 = 1;
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa2 == 1 &&
       entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa2 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa3 = 1;
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa3 == 1 &&
       entradas[PULSADOR_2] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa3 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
   }
}


void grafcets_calcular_acciones(void) {
   if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 ||
       grafcet[GRAFCET_LED_VERDE].etapa2 == 1 ) {
      salidas[LED_VERDE] = LED_ENCENDIDO;
   }
   else {
      salidas[LED_VERDE] = LED_APAGADO; 
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 ||
       grafcet[GRAFCET_LED_ROJO].etapa2 == 1 ) {
      salidas[LED_ROJO] = LED_ENCENDIDO;
   }
   else {
      salidas[LED_ROJO] = LED_APAGADO; 
   }
}


void temporizadores(void) {

}
 
void print_estado(void) {
   Serial.print("Etapas:");
   Serial.print("  Grafcet led verde=");
   Serial.print(grafcet[GRAFCET_LED_VERDE].etapas);
   Serial.print("  Grafcet led rojo =");
   Serial.print(grafcet[GRAFCET_LED_ROJO].etapas);
   Serial.println();
}

Adjunto grafcet de un solo pulsador y un led, esquema eléctrico y esquema de cableado en protoboard.
« Última modificación: 16/Ene/2020, 16:42:18 pm por Carlos »

Carlos

  • Moderador Global
  • ****
  • Mensajes: 294
Re:Grafcets en Arduino. Encendido de dos ledes
« Respuesta #1 en: 02/Ene/2020, 20:51:57 pm »
El segundo programa tiene el siguiente funcionamiento:

Código: (c) [Seleccionar]
/*
 * Implementación de Grafcet
 * para encender dos ledes con dos pulsadores
 *
 * El primer led verde se enciende y se apaga
 * al presionar el pulsador 1.
 *
 * El segundo led rojo se enciende durante
 * 10 segundos al presionar el pulsador 2.
 *
 */

// Definiciones
#define NUMERO_DE_ENTRADAS  2
#define NUMERO_DE_SALIDAS   2
#define NUMERO_DE_GRAFCETS  2
#define NUMERO_DE_TEMPORIZADORES  1

#define PIN_LED_VERDE   2
#define PIN_LED_ROJO    3
#define PIN_PULSADOR_1  8
#define PIN_PULSADOR_2  9

#define PULSADOR_PRESIONADO  0
#define PULSADOR_REPOSO      1
#define LED_ENCENDIDO        1
#define LED_APAGADO          0

#define SEGUNDOS_EN_DECIMAS 10

enum ENTRADAS_FISICAS {
   PULSADOR_1,
   PULSADOR_2,
};
 
enum SALIDAS_FISICAS {
   LED_VERDE,
   LED_ROJO,
};

enum NOMBRE_GRAFCETS {
   GRAFCET_LED_VERDE,
   GRAFCET_LED_ROJO,
};

enum NOMBRE_TEMPORIZADORES {
   TEMPORIZADOR_1,
};

enum TEMPORIZADOR_ESTADOS {
   TEMPORIZADOR_REPOSO,
   TEMPORIZADOR_CONTANDO,
   TEMPORIZADOR_TERMINADO,
};

typedef union  {
  struct {
    unsigned int etapa0: 1;
    unsigned int etapa1: 1;
    unsigned int etapa2: 1;
    unsigned int etapa3: 1;
    unsigned int etapa4: 1;
    unsigned int etapa5: 1;
    unsigned int etapa6: 1;
    unsigned int etapa7: 1;
    unsigned int etapa8: 1;
    unsigned int etapa9: 1;
    unsigned int etapa10: 1;
    unsigned int etapa11: 1;
    unsigned int etapa12: 1;
    unsigned int etapa13: 1;
    unsigned int etapa14: 1;
    unsigned int etapa15: 1;
  };
  unsigned int etapas;
} tipo_grafcet;

typedef struct {
   unsigned char estado;
   unsigned int tiempo;
} tipo_temporizador;


// Declaración de variables
unsigned char entradas[NUMERO_DE_ENTRADAS];
unsigned char salidas[NUMERO_DE_SALIDAS];
tipo_grafcet grafcet[NUMERO_DE_GRAFCETS];
tipo_grafcet grafcet_siguiente[NUMERO_DE_GRAFCETS];
tipo_temporizador temporizador[NUMERO_DE_TEMPORIZADORES];
unsigned int decisegundos;
unsigned long cien_milisegundos;

// Programa principal
void setup(void) {
   setup_pines();
   inicializar_grafcets();
   inicializar_temporizadores();
   
   while(1) {
      print_estado();
      leer_entradas();
      grafcets_evoluciona();
      escribir_salidas();
      temporizadores();
   }
}

void loop(void) {
}


//
// Funciones del programa principal
//

void setup_pines(void) {
   pinMode(PIN_LED_VERDE, OUTPUT);
   pinMode(PIN_LED_ROJO, OUTPUT);
   pinMode(PIN_PULSADOR_1, INPUT_PULLUP);
   pinMode(PIN_PULSADOR_2, INPUT_PULLUP);

   Serial.begin(9600);
}


void inicializar_grafcets(void) {
   grafcet_siguiente[GRAFCET_LED_VERDE].etapas = 0;
   grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;

   grafcet_siguiente[GRAFCET_LED_ROJO].etapas = 0;
   grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
}


void inicializar_temporizadores(void) {
   unsigned char i;
   for(i=0; i < NUMERO_DE_TEMPORIZADORES; i++) {
      temporizador[i].estado = TEMPORIZADOR_REPOSO;
   }

   decisegundos = 0;
   cien_milisegundos = millis() + 100;
}


void leer_entradas(void) {
   entradas[PULSADOR_1] = digitalRead(PIN_PULSADOR_1);
   entradas[PULSADOR_2] = digitalRead(PIN_PULSADOR_2);
}


void escribir_salidas(void) {
   digitalWrite(PIN_LED_VERDE, salidas[LED_VERDE]);
   digitalWrite(PIN_LED_ROJO, salidas[LED_ROJO]);
}


void grafcets_evoluciona(void) {
   grafcets_copiar_transiciones();
   grafcets_calcular_transiciones();
   grafcets_calcular_acciones();
}
 
 
void grafcets_copiar_transiciones(void) {
   unsigned char i;
   for(i=0; i < NUMERO_DE_GRAFCETS; i++) {
      grafcet[i].etapas = grafcet_siguiente[i].etapas;
   }
}


void grafcets_calcular_transiciones(void) {

   // GRAFCET_LED_VERDE
   if (grafcet[GRAFCET_LED_VERDE].etapa0 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa2 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 1;
   }

   if (grafcet[GRAFCET_LED_VERDE].etapa3 == 1 &&
       entradas[PULSADOR_1] == PULSADOR_REPOSO) {
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 0;
      grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
   }

   // GRAFCET_LED_ROJO TEMPORIZADO
   if (grafcet[GRAFCET_LED_ROJO].etapa0 == 1 &&
       entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 1;
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
       temporizador[TEMPORIZADOR_1].estado == TEMPORIZADOR_TERMINADO) {
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 0;
      grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
   }
}


void grafcets_calcular_acciones(void) {
   if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 ||
       grafcet[GRAFCET_LED_VERDE].etapa2 == 1 ) {
      salidas[LED_VERDE] = LED_ENCENDIDO;
   }
   else {
      salidas[LED_VERDE] = LED_APAGADO; 
   }

   if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 ) {
      salidas[LED_ROJO] = LED_ENCENDIDO;
   }
   else {
      salidas[LED_ROJO] = LED_APAGADO; 
   }
}


void temporizadores(void) {
   // Actualizar estado de los temporizadores
   temporizador_actualizar(TEMPORIZADOR_1,
                           grafcet[GRAFCET_LED_ROJO].etapa1,
                           10*SEGUNDOS_EN_DECIMAS);


   // Actualizar variable decisegundos
   if (millis() - cien_milisegundos < 10000 ) {
      cien_milisegundos += 100;
      decisegundos += 1;
   }
}


void temporizador_actualizar(unsigned char temporizador_id,
                             unsigned int grafcet_etapas,
                             unsigned int tiempo) {
   if (grafcet_etapas == 0) {
      temporizador[temporizador_id].estado = TEMPORIZADOR_REPOSO;
   }

   if (grafcet_etapas != 0 &&
       temporizador[temporizador_id].estado == TEMPORIZADOR_REPOSO) {
      temporizador[temporizador_id].tiempo = decisegundos + tiempo;
      temporizador[temporizador_id].estado = TEMPORIZADOR_CONTANDO;
   }

   if (temporizador[temporizador_id].estado == TEMPORIZADOR_CONTANDO &&
       decisegundos - temporizador[temporizador_id].tiempo < 10 * SEGUNDOS_EN_DECIMAS ) {
      temporizador[temporizador_id].estado = TEMPORIZADOR_TERMINADO; 
   }
}


void print_estado(void) {
   Serial.print("Grafcet led verde=");
   Serial.print(grafcet[GRAFCET_LED_VERDE].etapas);
   Serial.print(" Grafcet led rojo=");
   Serial.print(grafcet[GRAFCET_LED_ROJO].etapas);
   Serial.print(" Temporizador=");
   Serial.print(temporizador[TEMPORIZADOR_1].estado);
   Serial.print(" ");
   Serial.print(temporizador[TEMPORIZADOR_1].tiempo);
   Serial.println();
}

Adjunto grafcet del segundo led (Led rojo).
« Última modificación: 03/Ene/2020, 18:48:27 pm por Carlos »