//
// Programm zum Emulieren von Tasterbetätigungen über einen Wechselschalter
// Schalterstellungen
// 1 0 1
// Effekt schnell Effekt aus Effekt langsam
// 2 x Taster 1 1 X Taster 2 1 x Taster 1
//
#include <Streaming.h>
Print &cout {Serial};
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 EffectSelection : uint8_t { effectA, effectB, effectsOff };
template <size_t N> EffectSelection checkPinState(const uint8_t (&pins)[N]) {
for (size_t i = 0; i < N; ++i) {
if (digitalRead(pins[i]) == LOW) { return static_cast<EffectSelection>(i); }
}
return EffectSelection::effectsOff;
}
template <size_t N> void switchPins(const uint8_t (&pins)[N], uint16_t mask) {
uint16_t bitmask = 1 << (N - 1);
for (size_t i = 0; i < N; ++i) { (mask << i & bitmask) ? digitalWrite(pins[i], HIGH) : digitalWrite(pins[i], LOW); }
}
//
// Konstanten und Variablendefinitionen
//
constexpr uint8_t deviceCheckPins[2] {4, 5}; // Pins am Umschalter
constexpr uint8_t devicePins[2] {6, 7}; // Pins für die Effektschaltung
// Bitmasken zum Schalten der Effektpins
constexpr uint8_t SW_MASK_ALL_OFF {0x00};
constexpr uint8_t SW_MASK_DEV_D {0x02};
constexpr uint8_t SW_MASK_DEV_E {0x01};
constexpr uint32_t PIN_ENABLE_DURATION_MS {200}; // Dauer des emulierten Tasterdrucks in Millisekunden
constexpr uint32_t PIN_WAIT_DURATION_MS {300}; // Dauer zwischen zwei Tasterdrücken in Millisekunden
Timer checkTimer;
Timer impulseTimer;
//
// Hauptprogramm
//
void setup() {
Serial.begin(115200);
for (auto pin : deviceCheckPins) { pinMode(pin, INPUT_PULLUP); }
switchPins(devicePins, SW_MASK_ALL_OFF);
for (auto pin : devicePins) { pinMode(pin, OUTPUT); }
}
void deviceSelect() {
static EffectSelection prevCheck {EffectSelection::effectsOff};
static bool isPinHigh {false};
EffectSelection check = checkPinState(deviceCheckPins);
// Es hat eine Schaltebetätigung stattgefunden und das Abfragedelay ist abgelaufen
if (check != prevCheck && checkTimer(PIN_WAIT_DURATION_MS) == true) {
prevCheck = check;
checkTimer.start();
impulseTimer.start();
isPinHigh = true;
switch (check) {
case EffectSelection::effectA:
cout << F("Schalte Taster D - Effekt schnell\n");
switchPins(devicePins, SW_MASK_DEV_D);
break;
case EffectSelection::effectB:
cout << F("Schalte Taster D - Effekt langsam\n");
switchPins(devicePins, SW_MASK_DEV_D);
break;
default:
cout << F("Mittelstellung -> Schalte Taster E - Effekt aus\n");
switchPins(devicePins, SW_MASK_DEV_E);
break;
}
}
if (isPinHigh == true && impulseTimer(PIN_ENABLE_DURATION_MS)) {
switchPins(devicePins, SW_MASK_ALL_OFF);
isPinHigh = false;
}
}
void loop() { deviceSelect(); }
Schalter anklicken