#include <Button_SL.hpp> // https://github.com/DoImant/Button_SL
using ulong = unsigned long int;
enum class Condition : byte { ready, low, high };
class Timer {
public:
void start() { timeStamp = millis(); }
bool operator()(const ulong duration) const { return millis() - timeStamp >= duration; }
private:
ulong timeStamp {0};
};
struct PinData {
const uint8_t pin;
const ulong tHigh;
const ulong tLow;
};
Timer interval;
PinData pinData[] {
{3, 500, 500}, // Pinnr, Time High, Time Low in Milliseconds
{4, 500, 500},
{4, 500, 500},
{4, 500, 500},
{5, 500, 500},
{6, 500, 500},
{5, 500, 500}
};
Btn::ButtonSL btn {2};
Condition onePeriod(const PinData& pd, Timer& tm, Condition state) {
switch (state) {
case Condition::ready: // set given pin to HIGH (1)
tm.start();
{
state = Condition::high;
digitalWrite(pd.pin, HIGH);
}
break;
case Condition::low: // Wait for the end of the LOW period
if (tm(pd.tLow)) {
state = Condition::ready; // One period (High/Low) has been completed
}
break;
case Condition::high: // Wait for the end of the HIGH period
if (tm(pd.tHigh)) {
tm.start();
digitalWrite(pd.pin, LOW); // Set Pin to LOW (0)
state = Condition::low;
}
break;
default: break;
}
return state;
}
void setup() {
Serial.begin(115200);
for (const auto& data : pinData) {
pinMode(data.pin, OUTPUT);
}
btn.begin();
btn.releaseOn();
}
void loop() {
constexpr uint8_t sequenceSteps {sizeof(pinData) / sizeof(pinData[0])};
static bool isActive {false};
static size_t index {0};
static Condition state {Condition::ready};
if (btn.tick() != Btn::ButtonState::notPressed && !isActive) {
isActive = true;
Serial.println("Start");
}
if (isActive == true) {
switch (index) {
case 0 ... sequenceSteps-1:
state = onePeriod(pinData[index], interval, state);
if (state == Condition::ready) { ++index; }
break;
default:
Serial.println("Ende");
isActive = false;
index = 0;
break;
}
}
}