From a7d473121fba13e6fc7a5fb29ca193cb7a151591 Mon Sep 17 00:00:00 2001 From: "Jordan W. Cobb" Date: Fri, 16 Jan 2026 12:39:06 -0500 Subject: [PATCH] Added support for inverting logic of PIR pins --- .../Animated_Staircase/Animated_Staircase.cpp | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/usermods/Animated_Staircase/Animated_Staircase.cpp b/usermods/Animated_Staircase/Animated_Staircase.cpp index 2d2d27cf43..aed68028b1 100644 --- a/usermods/Animated_Staircase/Animated_Staircase.cpp +++ b/usermods/Animated_Staircase/Animated_Staircase.cpp @@ -25,6 +25,8 @@ class Animated_Staircase : public Usermod { unsigned int topMaxDist = 50; // default maximum measured distance in cm, top unsigned int bottomMaxDist = 50; // default maximum measured distance in cm, bottom bool togglePower = false; // toggle power on/off with staircase on/off + bool topAPinInvert = false; // invert output of top sensor + bool bottomAPinInvert = false; // invert output of bottom sensor /* runtime variables */ bool initDone = false; @@ -91,6 +93,8 @@ class Animated_Staircase : public Usermod { static const char _topEchoCm[]; static const char _bottomEchoCm[]; static const char _togglePower[]; + static const char _topPIRorTrigger_pin_invert[]; + static const char _bottomPIRorTrigger_pin_invert[]; void publishMqtt(bool bottom, const char* state) { #ifndef WLED_DISABLE_MQTT @@ -156,6 +160,12 @@ class Animated_Staircase : public Usermod { return pulseIn(echoPin, HIGH, maxTimeUs) > 0; } + bool readPIRPin(int8_t pin, bool invert) { + if (pin < 0) return false; + bool v = digitalRead(pin); + return invert ? !v : v; + } + bool checkSensors() { bool sensorChanged = false; @@ -164,15 +174,16 @@ class Animated_Staircase : public Usermod { bottomSensorRead = bottomSensorWrite || (!useUSSensorBottom ? - (bottomPIRorTriggerPin<0 ? false : digitalRead(bottomPIRorTriggerPin)) : + (bottomPIRorTriggerPin<0 ? false : readPIRPin(bottomPIRorTriggerPin, bottomAPinInvert)) : ultrasoundRead(bottomPIRorTriggerPin, bottomEchoPin, bottomMaxDist*59) // cm to us ); topSensorRead = topSensorWrite || (!useUSSensorTop ? - (topPIRorTriggerPin<0 ? false : digitalRead(topPIRorTriggerPin)) : + (topPIRorTriggerPin<0 ? false : readPIRPin(topPIRorTriggerPin, topAPinInvert)) : ultrasoundRead(topPIRorTriggerPin, topEchoPin, topMaxDist*59) // cm to us ); + if (bottomSensorRead != bottomSensorState) { bottomSensorState = bottomSensorRead; // change previous state sensorChanged = true; @@ -451,6 +462,8 @@ class Animated_Staircase : public Usermod { staircase[FPSTR(_topEchoCm)] = topMaxDist; staircase[FPSTR(_bottomEchoCm)] = bottomMaxDist; staircase[FPSTR(_togglePower)] = togglePower; + staircase[FPSTR(_topPIRorTrigger_pin_invert)] = topAPinInvert; + staircase[FPSTR(_bottomPIRorTrigger_pin_invert)] = bottomAPinInvert; DEBUG_PRINTLN(F("Staircase config saved.")); } @@ -462,10 +475,14 @@ class Animated_Staircase : public Usermod { bool readFromConfig(JsonObject& root) { bool oldUseUSSensorTop = useUSSensorTop; bool oldUseUSSensorBottom = useUSSensorBottom; + bool oldTopAPinInvert = topAPinInvert; + bool oldBottomAPinInvert = bottomAPinInvert; int8_t oldTopAPin = topPIRorTriggerPin; int8_t oldTopBPin = topEchoPin; int8_t oldBottomAPin = bottomPIRorTriggerPin; int8_t oldBottomBPin = bottomEchoPin; + + JsonObject top = root[FPSTR(_name)]; if (top.isNull()) { @@ -485,10 +502,13 @@ class Animated_Staircase : public Usermod { useUSSensorTop = top[FPSTR(_useTopUltrasoundSensor)] | useUSSensorTop; topPIRorTriggerPin = top[FPSTR(_topPIRorTrigger_pin)] | topPIRorTriggerPin; topEchoPin = top[FPSTR(_topEcho_pin)] | topEchoPin; + topAPinInvert = top[FPSTR(_topPIRorTrigger_pin_invert)] | topAPinInvert; + useUSSensorBottom = top[FPSTR(_useBottomUltrasoundSensor)] | useUSSensorBottom; bottomPIRorTriggerPin = top[FPSTR(_bottomPIRorTrigger_pin)] | bottomPIRorTriggerPin; bottomEchoPin = top[FPSTR(_bottomEcho_pin)] | bottomEchoPin; + bottomAPinInvert = top[FPSTR(_bottomPIRorTrigger_pin_invert)] | bottomAPinInvert; topMaxDist = top[FPSTR(_topEchoCm)] | topMaxDist; topMaxDist = min(150,max(30,(int)topMaxDist)); // max distance ~1.5m (a lag of 9ms may be expected) @@ -554,9 +574,11 @@ const char Animated_Staircase::_segmentDelay[] PROGMEM = "segment-d const char Animated_Staircase::_onTime[] PROGMEM = "on-time-s"; const char Animated_Staircase::_useTopUltrasoundSensor[] PROGMEM = "useTopUltrasoundSensor"; const char Animated_Staircase::_topPIRorTrigger_pin[] PROGMEM = "topPIRorTrigger_pin"; +const char Animated_Staircase::_topPIRorTrigger_pin_invert[] PROGMEM = "topPIRorTrigger_pin_invert"; const char Animated_Staircase::_topEcho_pin[] PROGMEM = "topEcho_pin"; const char Animated_Staircase::_useBottomUltrasoundSensor[] PROGMEM = "useBottomUltrasoundSensor"; const char Animated_Staircase::_bottomPIRorTrigger_pin[] PROGMEM = "bottomPIRorTrigger_pin"; +const char Animated_Staircase::_bottomPIRorTrigger_pin_invert[] PROGMEM = "bottomPIRorTrigger_pin_invert"; const char Animated_Staircase::_bottomEcho_pin[] PROGMEM = "bottomEcho_pin"; const char Animated_Staircase::_topEchoCm[] PROGMEM = "top-dist-cm"; const char Animated_Staircase::_bottomEchoCm[] PROGMEM = "bottom-dist-cm";