class Timer {
public:
void start() { timeStamp = millis(); }
bool operator()(const uint32_t duration) const { return (millis() - timeStamp >= duration) ? true : false; }
private:
uint32_t timeStamp {0};
};
enum class ProgramMode : byte { stop, modeA, modeB };
enum class LightStatus : byte { start, on, off };
// constexpr uint32_t TIME_MODE_A {1000 * 3600UL * 2}; // 2 Hours
// constexpr uint32_t TIME_MODE_B {1000 * 3600UL * 8}; // 8 Hours
// constexpr uint32_t LIGHT_ON_MS {1000 * 5UL}; // 5 Seconds
// constexpr uint32_t LIGHT_OFF_MS {1000 * 60UL * 15}; // 15 Minutes
constexpr uint32_t TIME_MODE_A {1000 * 120UL}; // 2 Minutes
constexpr uint32_t TIME_MODE_B {1000 * 60UL}; // 1 Minute
constexpr uint32_t LIGHT_ON_MS {1000 * 2UL};
constexpr uint32_t LIGHT_OFF_MS {1000 * 1UL};
constexpr uint32_t mainIntervalls[3] {0, TIME_MODE_A, TIME_MODE_B};
constexpr uint32_t ledIntervalls[3] {0, LIGHT_ON_MS, LIGHT_OFF_MS};
constexpr uint8_t LED_PIN {4};
constexpr uint8_t BUTTON_MODE_A {5};
constexpr uint8_t BUTTON_MODE_B {6};
constexpr uint8_t BUTTON_STOP {7};
Timer mainTimer;
Timer ledTimer;
ProgramMode checkButtons(ProgramMode md, Timer &mt) {
if (md == ProgramMode::stop) { // Check Mode buttons only when mode "Stop" is active
if (digitalRead(BUTTON_MODE_A) == LOW) {
Serial.println("Start Mode A (2 Minutes)");
md = ProgramMode::modeA;
mt.start();
} else if (digitalRead(BUTTON_MODE_B) == LOW) {
Serial.println("Start Mode B (1 Minute)");
md = ProgramMode::modeB;
mt.start();
}
} else { // Check Stop button only if modeA or modeB is active.
if (digitalRead(BUTTON_STOP) == LOW) {
md = ProgramMode::stop;
Serial.println("Stop");
}
}
return md;
}
LightStatus switchLight(LightStatus ls) {
if (ledTimer(ledIntervalls[static_cast<byte>(ls)])) {
ledTimer.start();
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
ls = (ls != LightStatus::on) ? LightStatus::on : LightStatus::off;
}
return ls;
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_MODE_A, INPUT_PULLUP);
pinMode(BUTTON_MODE_B, INPUT_PULLUP);
pinMode(BUTTON_STOP, INPUT_PULLUP);
}
void loop() {
static LightStatus ledStatus {LightStatus::start};
static ProgramMode mode {ProgramMode::stop};
mode = checkButtons(mode, mainTimer);
if (mainTimer(mainIntervalls[static_cast<byte>(mode)])) {
if (digitalRead(LED_PIN)) { digitalWrite(LED_PIN, LOW); }
mode = ProgramMode::stop;
} else {
ledStatus = switchLight(ledStatus);
}
}