El segundo programa tiene el siguiente funcionamiento:
/*
* 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).