// TASTENFUNKTION:
// Einmal Klick für leichte Lüftung
// Lüftung definiert auf Off schalten (Code 0x10)
// Kurze Pause
// 1 x Pfeil nach oben (Code 0x5) Gerät geht in STANDBY
// Kurze Pause
// 3 x Pfeil nach oben (Code 0x5) Gerät schaltet auf Stufe 3
// Zweimal Klick für mittlere Lüftung
// Lüftung definiert auf Off schalten (Code 0x10)
// Kurze Pause
// 1 x Pfeil nach oben (Code 0x5) Gerät geht in STANDBY
// Kurze Pause
// 5 x Pfeil nach oben (Code 0x5) Gerät schaltet auf Stufe 5
// Dreimal Klick für starke Lüftung
// Lüftung definiert auf Off schalten (Code 0x10)
// Kurze Pause
// 1 x Pfeil nach oben (Code 0x5) Gerät geht in STANDBY
// Kurze Pause
// 8 x Pfeil nach oben (Code 0x5) Gerät schaltet auf Stufe 8
// Langer Click
// Luftreiniger aus
#include <iostream>
#include <IRremote.hpp>
#include <Button2.h>
//
// Own datatypes
//
using Millis_t = decltype(millis());
//
// Global constants
//
constexpr uint_fast8_t gcButtonPins[1] {15};
constexpr uint_fast8_t gcLedPins[5] {16, 17, 18};
// IR parameter
constexpr uint_fast8_t gcSenderPin {4};
constexpr uint_fast16_t gcAddress {0xEF00};
constexpr uint_fast8_t gcRepeats {0};
// Switching parameter
constexpr Millis_t gcDefaultDelay_ms {500}; // Delay between arrow commands
constexpr Millis_t gcSwitchOffDelay_ms {2000}; // Delay after switch device off command
constexpr uint_fast8_t gcLevelLow {3};
constexpr uint_fast8_t gcLevelLowMask {0x01};
constexpr uint_fast8_t gcLevelMedium {5};
constexpr uint_fast8_t gcLevelMediumMask {0x02};
constexpr uint_fast8_t gcLevelHigh {8};
constexpr uint_fast8_t gcLevelHighMask {0x04};
enum class IrCommands { arrowUp = 0x05, off = 0x10 } irCommands;
//
// global objects / variables
//
Button2 button;
bool isOn {false};
uint_fast8_t activeLevel {0};
//
// functions
//
template <std::size_t N> void switchLED(const uint_fast8_t (&leds)[N], uint_fast8_t mask) {
for (std::size_t i {0}; i < N; ++i) { digitalWrite(leds[i], bitRead(mask, i)); }
}
void sendIrSignalWithDelay(uint_fast8_t pin, uint_fast16_t address, uint_fast16_t cmd, uint_fast8_t repeats,
Millis_t delay_ms) {
IrSender.setSendPin(pin);
IrSender.sendNEC(address, cmd, repeats); // Switch device arrowUp
delay(delay_ms);
}
bool airConditionerOff(uint_fast8_t pin, Millis_t delay_ms, uint_fast8_t ledBitMask) {
std::cout << "Sende IR: Lueftung aus" << std::endl;
sendIrSignalWithDelay(pin, gcAddress, static_cast<uint16_t>(IrCommands::off), gcRepeats, gcDefaultDelay_ms);
switchLED(gcLedPins, ledBitMask);
delay(delay_ms);
return false;
}
bool airConditionerToLevel(uint_fast8_t pin, uint_fast8_t level, uint_fast8_t ledBitMask) {
if (activeLevel == level) {
std::cout << "Die gewählte Stufe " << level << " ist bereits aktiv\r\n";
return true;
}
// 1. Switch off code 0x10
airConditionerOff(pin, gcSwitchOffDelay_ms, 0);
std::cout << "Sende IR: Lueftung Stufe: " << level << "\r\n";
// 2. Switch to standby
sendIrSignalWithDelay(pin, gcAddress, static_cast<uint16_t>(IrCommands::arrowUp), gcRepeats, gcDefaultDelay_ms);
// 3. Switch to the desired fan speed (level)
for (size_t i {0}; i < level; ++i) {
sendIrSignalWithDelay(pin, gcAddress, static_cast<uint16_t>(IrCommands::arrowUp), gcRepeats, gcDefaultDelay_ms);
}
switchLED(gcLedPins, ledBitMask);
return true;
}
void click(Button2& btn) {
isOn = airConditionerToLevel(gcSenderPin, gcLevelLow, gcLevelLowMask);
activeLevel = gcLevelLow;
}
void doubleClick(Button2& btn) {
isOn = airConditionerToLevel(gcSenderPin, gcLevelMedium, gcLevelMediumMask);
activeLevel = gcLevelMedium;
}
void tripleClick(Button2& btn) {
isOn = airConditionerToLevel(gcSenderPin, gcLevelHigh, gcLevelHighMask);
activeLevel = gcLevelHigh;
}
void longClick(Button2& btn) {
if (isOn) {
isOn = airConditionerOff(gcSenderPin, gcSwitchOffDelay_ms, 0); // Mask 0 = all LEDs off
} else {
std::cout << "Luftreiniger ist bereits aus\r\n";
}
}
void setup() {
Serial.begin(115200);
std::cout << "Start" << std::endl;
IrSender.begin(gcSenderPin);
button.begin(gcButtonPins[0]);
button.setDebounceTime(50); // 50ms entprellen
button.setLongClickTime(2000); // 1.5 Sekunden für langes Drücken
button.setDoubleClickTime(800); // 400ms für Doppelklicks
button.setClickHandler(click);
button.setDoubleClickHandler(doubleClick);
button.setTripleClickHandler(tripleClick);
button.setLongClickDetectedHandler(longClick);
for (const auto& pin : gcLedPins) { pinMode(pin, OUTPUT); }
}
void loop() { button.loop(); }
Fan level
Active fan level