#include <LiquidCrystal_I2C.h>
// Pantalla LCD
#define I2C_addr 0x27
#define columnsLCD 20
#define rowsLCD 4
LiquidCrystal_I2C lcd(I2C_addr, columnsLCD, rowsLCD);
// Timers
hw_timer_t *timerButton = NULL; // Se define el timer
hw_timer_t *timerParpadeo = NULL; // Se define el timer
#define tiempoParpadeo (0.25)*1e6
#define tiempoPulsacionLarga (2)*1e3 // milisegundos
unsigned long tiempoPulsado;
// Botones
#define pinBArmar 34
#define pinBFuncionar 35
#define pinBParar 32
#define pinBDesarmar 33
#define pinBAlerta 25
#define pinBAlertaConocida 26
#define pinBQuitarAlerta 27
// LEDs
#define pinLedDesarmada 2
#define pinLedArmada 4
#define pinLedFuncionamiento 16
#define pinLedAlerta 17
// Buzzer
#define pinBuzzer 19
#define noteC5 523
// Variables empleadas
volatile int state;
volatile bool conmutaLed;
volatile bool bArmarSuelto;
volatile bool bFuncionarSuelto;
volatile bool bPararSuelto;
volatile bool bDesarmarSuelto;
volatile bool bAlertaSuelto;
volatile bool bAlertaConocidaSuelto;
volatile bool bQuitarAlertaSuelto;
volatile bool bQuitarAlertaPulsado;
/**************************************** ISRs ******************************************/
void IRAM_ATTR ISR_bArmar(void) {
if (state == 1) {
bArmarSuelto = true;
}
}
void IRAM_ATTR ISR_bFuncionar(void) {
if (state == 2) {
bFuncionarSuelto = true;
}
}
void IRAM_ATTR ISR_bParar(void) {
if (state == 3) {
bPararSuelto = true;
}
}
void IRAM_ATTR ISR_bDesarmar(void) {
if (state == 2) {
bDesarmarSuelto = true;
}
}
void IRAM_ATTR ISR_bAlerta(void) {
if ((state == 1) || (state == 2) || (state == 3)) {
bAlertaSuelto = true;
}
}
void IRAM_ATTR ISR_bAlertaConocida(void) {
if (state == 4) {
bAlertaConocidaSuelto = true;
}
}
void IRAM_ATTR ISR_bQuitarAlerta(void) {
if (state == 5) {
if (digitalRead(pinBQuitarAlerta) == 0) {
bQuitarAlertaPulsado = true;
} else {
bQuitarAlertaSuelto = true;
}
}
}
void IRAM_ATTR ISR_ConmutaLed(void) {
conmutaLed = true;
}
/**************************************** Funciones **************************************/
/*
PrintRow() escribe en la línea especificada el texto pasado como parámetro.
El texto aparecerá centrado en la fila.
*/
void PrintRow(const int row, const String text) {
String textRow = text;
// Calcula la posición inicial para que el texto
// aparezca centrado en la fila
const int startingPosition = (columnsLCD - textRow.length()) / 2;
// Muestra el texto centrado en la fila
lcd.setCursor(startingPosition, row);
lcd.print(textRow);
}
/*
SetLcdText() escribe en la pantalla LCD
el texto pasado como parámetro para cada fila.
*/
void SetLcdText(const String textR1,
const String textR2,
const String textR3,
const String textR4) {
lcd.clear();
PrintRow(0, textR1);
PrintRow(1, textR2);
PrintRow(2, textR3);
PrintRow(3, textR4);
}
void ResetFlags(void) {
bArmarSuelto = false;
bFuncionarSuelto = false;
bPararSuelto = false;
bDesarmarSuelto = false;
bAlertaSuelto = false;
bAlertaConocidaSuelto = false;
bQuitarAlertaSuelto = false;
bQuitarAlertaPulsado = false;
}
void MostrarEstado(void) {
Serial.print("Estado: ");
Serial.print(state);
Serial.print(" - ");
switch (state) {
case 1:
Serial.println("Desarmada");
SetLcdText("Estado:" + String(state), "", "Desarmada", "");
break;
case 2:
Serial.println("Armada");
SetLcdText("Estado:" + String(state), "", "Armada", "");
break;
case 3:
Serial.println("Funcionamiento");
SetLcdText("Estado:" + String(state), "", "Funcionamiento", "");
break;
case 4:
Serial.println("Alerta");
SetLcdText("Estado:" + String(state), "", "Alerta", "");
break;
case 5:
Serial.println("Alerta Conocida");
SetLcdText("Estado:" + String(state), "", "Alerta Conocida", "");
break;
default:
break;
}
}
void ToState1(void) {
digitalWrite(pinLedDesarmada, HIGH);
digitalWrite(pinLedArmada, LOW);
digitalWrite(pinLedFuncionamiento, LOW);
digitalWrite(pinLedAlerta, LOW);
MostrarEstado();
ResetFlags();
}
void ToState2(void) {
digitalWrite(pinLedDesarmada, LOW);
digitalWrite(pinLedArmada, HIGH);
digitalWrite(pinLedFuncionamiento, LOW);
digitalWrite(pinLedAlerta, LOW);
MostrarEstado();
ResetFlags();
}
void ToState3(void) {
digitalWrite(pinLedDesarmada, LOW);
digitalWrite(pinLedArmada, LOW);
digitalWrite(pinLedFuncionamiento, HIGH);
digitalWrite(pinLedAlerta, LOW);
MostrarEstado();
ResetFlags();
}
void ToState4(void) {
//Apago LEDs
digitalWrite(pinLedDesarmada, LOW);
digitalWrite(pinLedArmada, LOW);
digitalWrite(pinLedFuncionamiento, LOW);
digitalWrite(pinLedAlerta, LOW);
// Buzzer
tone(pinBuzzer, noteC5);
// Parpadeo
timerRestart(timerParpadeo); // Pone a 0 la cuenta
timerStart(timerParpadeo); // Hace que el timer comience a contar
MostrarEstado();
ResetFlags();
}
void ToState5(void) {
// Parpadeo
timerStop(timerParpadeo);
// LEDs
digitalWrite(pinLedDesarmada, LOW);
digitalWrite(pinLedArmada, LOW);
digitalWrite(pinLedFuncionamiento, LOW);
digitalWrite(pinLedAlerta, HIGH);
// Buzzer
noTone(pinBuzzer);
MostrarEstado();
ResetFlags();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
// Pantalla LCD
lcd.init();
lcd.backlight();
// Definicion I/0
pinMode(pinBArmar, INPUT_PULLUP);
pinMode(pinBFuncionar, INPUT_PULLUP);
pinMode(pinBParar, INPUT_PULLUP);
pinMode(pinBDesarmar, INPUT_PULLUP);
pinMode(pinBAlerta, INPUT_PULLUP);
pinMode(pinBAlertaConocida, INPUT_PULLUP);
pinMode(pinBQuitarAlerta, INPUT_PULLUP);
pinMode(pinLedDesarmada, OUTPUT);
pinMode(pinLedArmada, OUTPUT);
pinMode(pinLedFuncionamiento, OUTPUT);
pinMode(pinLedAlerta, OUTPUT);
// Interrupciones
attachInterrupt(digitalPinToInterrupt(pinBArmar), &ISR_bArmar, RISING);
attachInterrupt(digitalPinToInterrupt(pinBFuncionar), &ISR_bFuncionar, RISING);
attachInterrupt(digitalPinToInterrupt(pinBParar), &ISR_bParar, RISING);
attachInterrupt(digitalPinToInterrupt(pinBDesarmar), &ISR_bDesarmar, RISING);
attachInterrupt(digitalPinToInterrupt(pinBAlerta), &ISR_bAlerta, RISING);
attachInterrupt(digitalPinToInterrupt(pinBAlertaConocida), &ISR_bAlertaConocida, RISING);
attachInterrupt(digitalPinToInterrupt(pinBQuitarAlerta), &ISR_bQuitarAlerta, CHANGE);
// Timers
timerButton = timerBegin(1000000);
timerStop(timerButton); // Para el timer
timerParpadeo = timerBegin(1000000); // Se pone directamente la frecuencia en Hz
timerAttachInterrupt(timerParpadeo, &ISR_ConmutaLed);
timerAlarm(timerParpadeo, tiempoParpadeo, true, 0); // (Se pone el número hasta el que cuenta: 1e6 = 1s)
timerStop(timerParpadeo); // Para el timer
// Inicializo variables
state = 1;
ToState1();
}
void loop() {
switch (state) {
case 1:
if (bArmarSuelto) {
bArmarSuelto = false;
state = 2;
ToState2();
}
if (bAlertaSuelto) {
bAlertaSuelto = false;
state = 4;
ToState4();
}
break;
case 2:
if (bFuncionarSuelto) {
bFuncionarSuelto = false;
state = 3;
ToState3();
}
if (bDesarmarSuelto) {
bDesarmarSuelto = false;
state = 1;
ToState1();
}
if (bAlertaSuelto) {
bAlertaSuelto = false;
state = 4;
ToState4();
}
break;
case 3:
if (bPararSuelto) {
bPararSuelto = false;
state = 2;
ToState2();
}
if (bAlertaSuelto) {
bAlertaSuelto = false;
state = 4;
ToState4();
}
break;
case 4:
if (conmutaLed) {
conmutaLed = false;
digitalWrite(pinLedAlerta, !digitalRead(pinLedAlerta));
}
if (bAlertaConocidaSuelto) {
bAlertaConocidaSuelto = false;
state = 5;
ToState5();
}
break;
case 5:
if (bQuitarAlertaPulsado) {
bQuitarAlertaPulsado = false;
timerRestart(timerButton); // Pone a 0 la cuenta
timerStart(timerButton); // Hace que el timer comience a contar
}
if (bQuitarAlertaSuelto) {
bQuitarAlertaSuelto = false;
tiempoPulsado = timerReadMillis(timerButton);
timerStop(timerButton);
if (tiempoPulsado > tiempoPulsacionLarga){
state = 1;
ToState1();
} else {
Serial.println("Alarma no desactivada.");
Serial.print("Tiempo de pulsación: ");
Serial.print(tiempoPulsado);
Serial.println(" ms.");
SetLcdText("Estado:" + String(state),
"Alerta Conocida",
"Alarma Activa",
"TPulsacion:" + String(tiempoPulsado) + "ms");
}
}
break;
default:
break;
}
delay(10); // this speeds up the simulation
}