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 uint8_t LED_PIN {4};
// 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 * 4UL};
constexpr uint32_t mainIntervalls[3] {0, TIME_MODE_A, TIME_MODE_B};
constexpr uint32_t ledIntervalls[3] {0, LIGHT_ON_MS, LIGHT_OFF_MS};
Timer ledTimer;
Timer mainTimer;
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);
mainTimer.start();
}
void loop() {
static LightStatus ledStatus {LightStatus::start};
static ProgramMode mode {ProgramMode::modeB};
// Depending on the pressed button, the variable mode must be set to either
// ProgramMode::modeA, ProgramMode::modeB or ProgramMode::stop.
// When the mode (A or B) is set, mainTimer.start() must also be executed (once).
if (mainTimer(mainIntervalls[static_cast<byte>(mode)])) {
if (digitalRead(LED_PIN)) { digitalWrite(LED_PIN, LOW); }
mode = ProgramMode::stop;
} else {
ledStatus = switchLight(ledStatus);
}
}