#include <Arduino.h>
//////////////////////////////////////////////////
// Object definitions
//////////////////////////////////////////////////
class Timer {
public:
void start() {
timeStamp = millis();
}
bool operator()(const unsigned long duration) const {
return (millis() - timeStamp >= duration) ? true : false;
}
private:
unsigned long timeStamp {0};
};
class DurationSwitch {
public:
template <size_t MAX>
DurationSwitch(const unsigned long (&stArray)[MAX]) : switchingTimes {stArray}, maxIndex {MAX - 1} {}
byte next() {
index = (index < maxIndex) ? index + 1 : 0;
return index;
}
unsigned long signalDuration() const {
return switchingTimes[index];
}
private:
const unsigned long *switchingTimes;
byte maxIndex;
byte index {0};
};
enum class LedSwitchState : uint8_t { off = 0, start, on, locked };
//////////////////////////////////////////////////
// Global constants
//////////////////////////////////////////////////
constexpr byte IR_PIN {2};
constexpr byte LED_SWITCH_PIN {13};
//////////////////////////////////////////////////
// Global variables and instances
//////////////////////////////////////////////////
// LED light duration 5 seconds and 1 second lock against switching on again.
const unsigned long msTimes[] {5000, 1000};
DurationSwitch swLed(msTimes);
LedSwitchState ledState {LedSwitchState::off};
Timer timer;
//////////////////////////////////////////////////
// Main Program
//////////////////////////////////////////////////
void checkDetection(DurationSwitch &ds, Timer &t, LedSwitchState& lss) {
switch (lss) {
case LedSwitchState::start:
t.start();
lss = LedSwitchState::on;
digitalWrite(LED_SWITCH_PIN, HIGH);
Serial.print(F("LED lights up for: "));
Serial.print(ds.signalDuration());
Serial.println(F(" ms"));
break;
case LedSwitchState::on:
if (t(ds.signalDuration())) {
digitalWrite(LED_SWITCH_PIN, LOW);
lss = LedSwitchState::locked;
ds.next();
Serial.print(F("LED is locked: "));
Serial.print(ds.signalDuration());
Serial.println(F(" ms"));
t.start();
}
break;
case LedSwitchState::locked:
if (t(swLed.signalDuration())) {
lss = LedSwitchState::off;
ds.next();
Serial.println(F("Ready"));
}
break;
default: break;
}
}
void setup() {
Serial.begin(115200);
pinMode(IR_PIN, INPUT_PULLUP); // IR signal simulated by a button
pinMode(LED_SWITCH_PIN, OUTPUT);
}
void loop() {
static bool isReleased {true};
static byte irVal {HIGH};
irVal = digitalRead(IR_PIN);
if (!irVal && ledState == LedSwitchState::off) { // Obstacle detected when PIN goes LOW (= !irVal)
if (isReleased) { ledState = LedSwitchState::start; }
isReleased = false;
} else if (irVal) {
delay(20); // Debounce;
if (ledState == LedSwitchState::off) { isReleased = true; }
}
checkDetection(swLed, timer, ledState);
}