When you start writing a sketch, a good starting point is to consider each part of you problem as a separate function()
For example, checking a switch/sensor/button to turn on an output for 2-seconds...
At the top of your sketch, before setup - declare all your 'global' variables to be shared across other functions.
void setup() will initialise all your variables to their starting values.
Within loop() make a call to determine the input state... e.g. getInputState()
That function should take care of everything associated with polarity, debounce (and anything else) related to detecting the input state.
With that input state known, you can make a confident, well informed decision whether to trigger the output pin(s).
If it's more than just on/off, you might implement another function setOutputState().
That will also isolate the requirements of output polarity and 'start time' if needed.
In loop(), calling another checkOutputState() may be use millis() to turn the outputs off/on relative to setOutputState()
In pseudo-code this looks like -
bool inputState;
unsigned long outputMillis;
void setup() {
// set pin directions
// set initial values
}
void loop() {
getInputState(); // check the input pin(s)
if (inputState != prevInputState) { // input has changed state
setOutputState(); // set outputs and start millis() timer if needed
prevInputState = inputState; // keep a copy of previous input state
}
checkOutputState(); // if millis() has elapsed - reset affected outputs
}
// you need to write the in/out functions to suit your project!
It's that easy! And to isolate, fix or replace each function separately - do exactly that - without affecting the functionality of everything else.
e.g for debugging, if you think the code is faulty, simply comment out that line, and assign a temporary value to test the rest of the code.
Of course, there is more to the actual code required above (not much), but it was left out so you can see how to isolate your logic for faster debugging.
Keep backups between edited versions!