//////////////////////////////////////////////////////////////////////
// Lamp Driver
// 06.10.2024
// V1.0
//////////////////////////////////////////////////////////////////////
// global variable definition & preprocessor def
// enum type for Finite State Machine
typedef enum {
FSM_REEDSW_SIGNAL_DETECTION,
FSM_LIGHT_ON,
FSM_LIGHT_OFF,
} light_fsm_t;
// debug level 0 - no debug, 1 - normal level, 2 - high level
#define DEBUG_LEVEL 1
// time grain for main loop, default time is 10ms
#define MAIN_LOOP_TIME_GRAIN_MS 10
// debounce time to check edge, default time is 20ms
#define DEBOUNCE_INTERVAL 20
// pinout definition for Arduino nano
int RELAY_Output = A0;
int MODESW_Input = 10;
int REEDSW_Input = 8;
// global variables
// reed switch variables
bool current_signal_level = 0, last_signal_level = 0;
bool rising_edge_flag = 0, falling_edge_flag = 0;
bool rising_edge_detected = 0, falling_edge_detected = 0;
// common variables
unsigned long previous_millis_Debounce = 0;
unsigned long previous_millis_Main_Loop = 0;
bool aux_flag = 1;
// initial state
light_fsm_t state = FSM_REEDSW_SIGNAL_DETECTION;
//////////////////////////////////////////////////////////////////////
// setup definition
void setup() {
Serial.begin(9600);
pinMode(RELAY_Output, OUTPUT);
pinMode(MODESW_Input, INPUT_PULLUP);
pinMode(REEDSW_Input, INPUT_PULLUP);
//safety: set drive stop during startup
digitalWrite(RELAY_Output, LOW);
// Log after restart
Serial.println("Controller restart ...");
}
//////////////////////////////////////////////////////////////////////
// function to detect REED switch signal
static void Reedsw_Signal_Detection(void)
{
current_signal_level = digitalRead(REEDSW_Input);
// rising edge detection
if ((current_signal_level == HIGH) && (last_signal_level == LOW)) {
rising_edge_flag = 1;
falling_edge_flag = 0;
last_signal_level = current_signal_level;
previous_millis_Debounce = millis();
}
// debounce time to check HIGH level is stable
if (rising_edge_flag == HIGH) {
if (millis() - previous_millis_Debounce > DEBOUNCE_INTERVAL) {
if (current_signal_level == HIGH) {
rising_edge_detected = 1;
falling_edge_detected = 0;
rising_edge_flag = 0;
falling_edge_flag = 0;
#if DEBUG_LEVEL > 1
Serial.println("RISING edge detected");
#endif
}
}
}
// falling edge detection
if ((current_signal_level == LOW) && (last_signal_level == HIGH)) {
rising_edge_flag = 0;
falling_edge_flag = 1;
last_signal_level = current_signal_level;
previous_millis_Debounce = millis();
}
// debounce time to check LOW level is stable
if (falling_edge_flag == HIGH) {
if (millis() - previous_millis_Debounce > DEBOUNCE_INTERVAL) {
if (current_signal_level == LOW) {
rising_edge_detected = 0;
falling_edge_detected = 1;
rising_edge_flag = 0;
falling_edge_flag = 0;
#if DEBUG_LEVEL > 1
Serial.println("FALLING edge detected");
#endif
}
}
}
}
//////////////////////////////////////////////////////////////////////
// function to Light turn On
static void Light_On(void)
{
digitalWrite(RELAY_Output, HIGH);
#if DEBUG_LEVEL > 1
Serial.println("Turn light ON");
#endif
}
//////////////////////////////////////////////////////////////////////
// function to Light turn Off
static void Light_Off(void)
{
digitalWrite(RELAY_Output, LOW);
#if DEBUG_LEVEL > 1
Serial.println("Turn light OFF");
#endif
}
//////////////////////////////////////////////////////////////////////
// Light Control Finite State Machine definition
static void LIGHT_FSM(void)
{
switch (state)
{
case FSM_REEDSW_SIGNAL_DETECTION:
//state FSM_REEDSW_SIGNAL_DETECTION
//call every 10ms according TIME_GRAIN
#if (DEBUG_LEVEL > 0)
if (aux_flag) Serial.println("State: REEDSW SIGNAL DETECTION"); aux_flag = 0;
#endif
Reedsw_Signal_Detection();
// Forced LIGHT_ON mode
if (digitalRead(MODESW_Input) == 0) {
state = FSM_LIGHT_ON;
// Auto LIGHT ON/OFF mode
} else {
if (rising_edge_detected == 1) {
if (digitalRead(RELAY_Output) == 0) {
state = FSM_LIGHT_ON;
rising_edge_detected = 0;
aux_flag = 1;
} else {
state = FSM_LIGHT_OFF;
rising_edge_detected = 0;
aux_flag = 1;
}
}
}
break;
case FSM_LIGHT_ON:
//state FSM_LIGHT_ON
#if (DEBUG_LEVEL > 0)
if (aux_flag) Serial.println("State: LIGHT ON");
#endif
Light_On();
state = FSM_REEDSW_SIGNAL_DETECTION;
break;
case FSM_LIGHT_OFF:
//state FSM_LIGHT_OFF
#if (DEBUG_LEVEL > 0)
if(aux_flag) Serial.println("State: LIGHT OFF");
#endif
Light_Off();
state = FSM_REEDSW_SIGNAL_DETECTION;
break;
default:
//IN CASE OF ERROR
#if (DEBUG_LEVEL > 0)
if(aux_flag) Serial.println("State: DEFAULT in case of error");
#endif
Light_Off();
state = FSM_REEDSW_SIGNAL_DETECTION;
break;
}
}
//////////////////////////////////////////////////////////////////////
// Main program here
void loop()
{
// call LIGHT_FSM state machine every TIME_GRAIN
if (millis() - previous_millis_Main_Loop > MAIN_LOOP_TIME_GRAIN_MS)
{
// call state machine
LIGHT_FSM();
// set current time as previous
previous_millis_Main_Loop = millis();
}
}