#include <Arduino.h>
// Pin definitions
#define P_DOOR 2
#define P_WALL 3
#define P_LIGHT 10
#define P_BUZZER 11
#define P_READY 13
#define MAX_ON_TIME 60000 // One minute to go out
#define BEEP_PERIOD 1000
#define MAX_BEEPS 20
// Lamp states
enum LampState {
OFF,
ON_FROM_MANUAL_SWITCH,
ON_FROM_DOOR_SWITCH
};
// Events
enum LampEvent {
ManualSwitchClosed,
ManualSwitchOpened,
DoorSwitchClosed,
DoorSwitchOpened,
None // Represents no event
};
// Enable printf()
FILE f_out;
int sput(char c, __attribute__((unused)) FILE* f) {return !Serial.write(c);}
// Global variables
const int debounceDelay = 10; // Debounce delay in milliseconds
static unsigned long closeStart = 0;
static unsigned long closedTime = 0;
volatile bool doorSwState; // Shared variable for the switch state
volatile bool wallSwState; // Shared variable for the switch state
static bool doorSwLastState;
static bool wallSwLastState;
static unsigned long backToHomeTimer = 0;
// Current state
LampState currentState = OFF;
// Function declarations for event actions
typedef void (*EventAction)(LampState currentState);
// State transition struct
struct StateTransition {
LampState currentState;
LampEvent event;
EventAction action;
LampState nextState;
};
// Function prototypes
void handleManualSwitchClosed(LampState currentState);
void handleManualSwitchOpened(LampState currentState);
void handleDoorSwitchClosed(LampState currentState);
void handleDoorSwitchOpened(LampState currentState);
// Interrupt hadnlers
void handleDoorSwInterrupt() {
delay(debounceDelay); // Debounce the signal
doorSwState = digitalRead(P_DOOR); // Read stable pin state
}
void handleWallSwInterrupt() {
delay(debounceDelay); // Debounce the signal
wallSwState = digitalRead(P_WALL); // Read stable pin state
}
// Transition table
const StateTransition transitions[] = {
// OFF state
{OFF, ManualSwitchClosed, handleManualSwitchClosed, ON_FROM_MANUAL_SWITCH},
{OFF, DoorSwitchOpened, handleDoorSwitchOpened, ON_FROM_DOOR_SWITCH},
// ON_FROM_MANUAL_SWITCH state
{ON_FROM_MANUAL_SWITCH, ManualSwitchClosed, handleManualSwitchClosed, OFF},
{ON_FROM_MANUAL_SWITCH, ManualSwitchOpened, handleManualSwitchOpened, ON_FROM_MANUAL_SWITCH},
{ON_FROM_MANUAL_SWITCH, DoorSwitchClosed, handleDoorSwitchClosed, OFF},
// ON_FROM_DOOR_SWITCH state
{ON_FROM_DOOR_SWITCH, ManualSwitchClosed, handleManualSwitchClosed, OFF},
{ON_FROM_DOOR_SWITCH, DoorSwitchClosed, handleDoorSwitchClosed, ON_FROM_DOOR_SWITCH},
// Terminal state (no changes for other events in ON_FROM_DOOR_SWITCH)
};
// Number of transitions
const int numTransitions = sizeof(transitions) / sizeof(transitions[0]);
// Event handlers
void handleManualSwitchClosed(LampState state) {
closeStart = millis();
if (state == OFF) {
Serial.println("ManualSwitchClosed: Turning ON from Manual Switch");
// OFF -> ON_FROM_MANUAL_SWITCH transition
digitalWrite(P_LIGHT, HIGH);
} else if (state == ON_FROM_MANUAL_SWITCH) {
Serial.println("ManualSwitchClosed: Turning OFF from Manual Switch");
// ON_FROM_MANUAL_SWITCH -> OFF transition
digitalWrite(P_LIGHT, LOW);
} else if (state == ON_FROM_DOOR_SWITCH) {
Serial.println("ManualSwitchClosed: Turning OFF from Door Switch");
// ON_FROM_DOOR_SWITCH -> OFF transition
digitalWrite(P_LIGHT, LOW);
}
}
void handleManualSwitchOpened(LampState state) {
if (state == ON_FROM_MANUAL_SWITCH) {
Serial.println("ManualSwitchOpened: Calculating switch Close time");
// Add code to handle timing logic
closedTime = millis() - closeStart;
printf("[2] closedTime: %lumS\r\n", closedTime);
}
}
void handleDoorSwitchClosed(LampState state) {
if (state == ON_FROM_MANUAL_SWITCH) {
Serial.println("DoorSwitchClosed: Turning OFF");
// Add code for ON_FROM_MANUAL_SWITCH -> OFF transition
digitalWrite(P_LIGHT, LOW);
}else if (state == ON_FROM_DOOR_SWITCH) {
Serial.println("DoorSwitchOpened: Start the one minute timer");
// ON_FROM_DOOR_SWITCH -> ?????
backToHomeTimer = millis();
}
}
void handleDoorSwitchOpened(LampState state) {
if (state == OFF) {
Serial.println("DoorSwitchOpened: Turning ON from Door Switch");
// Add code for OFF -> ON_FROM_DOOR_SWITCH transition
// printf("[1] P_LIGHT: %d \r\n", digitalRead(P_LIGHT));
digitalWrite(P_LIGHT, HIGH);
// printf("[2] P_LIGHT: %d \r\n", digitalRead(P_LIGHT));
}
}
// Function to process an event
void processEvent(LampEvent event) {
for (int i = 0; i < numTransitions; i++) {
if (transitions[i].currentState == currentState && transitions[i].event == event) {
// Perform the action, passing the current state
if (transitions[i].action) {
transitions[i].action(currentState);
}
// Transition to the next state
currentState = transitions[i].nextState;
return;
}
}
// If no valid transition is found
printf("No transition for this event (%d) in current state(%d).\r\n", event, currentState);
}
void setup() {
Serial.begin(115200);
// printf
fdev_setup_stream(&f_out, sput, nullptr, _FDEV_SETUP_WRITE);
stdout = &f_out;
digitalWrite(P_READY, LOW);
digitalWrite(P_LIGHT, LOW);
digitalWrite(P_BUZZER, LOW);
pinMode(P_DOOR, INPUT);
pinMode(P_WALL, INPUT);
pinMode(P_LIGHT, OUTPUT);
pinMode(P_BUZZER, OUTPUT);
pinMode(P_READY, OUTPUT);
wallSwState = digitalRead(P_WALL); // Set initial state
doorSwState = digitalRead(P_DOOR);
doorSwLastState = doorSwState;
wallSwLastState = wallSwState;
attachInterrupt(digitalPinToInterrupt(P_DOOR), handleDoorSwInterrupt, CHANGE);
attachInterrupt(digitalPinToInterrupt(P_WALL), handleWallSwInterrupt, CHANGE);
digitalWrite(P_READY, HIGH);
digitalWrite(P_BUZZER, HIGH);
delay(50);
digitalWrite(P_BUZZER, LOW);
Serial.println("\r\n\n\nLucifero 2.00 is ready!");
}
void loop() {
if (doorSwState != doorSwLastState) {
doorSwLastState = doorSwState;
if(doorSwState == LOW) {
processEvent(DoorSwitchClosed);
}
else {
processEvent(DoorSwitchOpened);
}
}
if (wallSwState != wallSwLastState) {
wallSwLastState = wallSwState;
if(wallSwState == LOW) {
processEvent(ManualSwitchClosed);
}
else {
processEvent(ManualSwitchOpened);
}
}
if((backToHomeTimer != 0) && (millis() - backToHomeTimer ) > MAX_ON_TIME) {
printf("BTH Timer expired");
backToHomeTimer = 0;
}
}