/*
* Implementación de Grafcet
* para encender dos led 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_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 ENTRADAS_FISICAS {
PULSADOR_1,
PULSADOR_2,
};
enum SALIDAS_FISICAS {
LED_VERDE,
LED_ROJO,
};
enum NOMBRE_GRAFCETS {
GRAFCET_LED_VERDE,
GRAFCET_LED_ROJO,
};
enum TEMPORIZADOR_ESTADOS {
TEMPORIZADOR_REPOSO,
TEMPORIZADOR_CONTANDO,
TEMPORIZADOR_TERMINADO,
};
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;
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_1;
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) {
temporizador_1.estado = TEMPORIZADOR_REPOSO;
cien_milisegundos = millis() + 100;
decisegundos = 0;
}
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 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_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) {
// Temporizador 1
if (grafcet[GRAFCET_LED_ROJO].etapa1 == 0) {
temporizador_1.estado = TEMPORIZADOR_REPOSO;
}
if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
temporizador_1.estado == TEMPORIZADOR_REPOSO) {
temporizador_1.tiempo = decisegundos + 100;
temporizador_1.estado = TEMPORIZADOR_CONTANDO;
}
if (temporizador_1.estado == TEMPORIZADOR_CONTANDO &&
decisegundos - temporizador_1.tiempo < 500 ) {
temporizador_1.estado = TEMPORIZADOR_TERMINADO;
}
// Actualizar decisegundos
if (millis() - cien_milisegundos < 10000 ) {
cien_milisegundos += 100;
decisegundos += 1;
}
}
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_1.estado);
Serial.print(" ");
Serial.print(temporizador_1.tiempo);
Serial.println();
}