I am using an infrared beam break QT50CM sensor that I need to monitor and then send ground signals to 2 buttons. Button "A" is ON and button "B" is Open The device I am making this for has a function and to turn it on button A needs to be held down while you press button B, after this both buttons are released. This turns on the function and to turn it off you push either button, pretty simple.
ok, so your two outputs go to buttons on some device. To turn the button off you set the output pin to pinMode(pin, INPUT), which makes the pin float, and to turn the button on you set the output pin to pinMode(pin, OUTPUT), digitalWrite(pin, LOW).
So your problem is in getting the timing logic going.
We rely on the fact that loop() gets spammed many thousands of times a second.
At any given moment, your sketch can be doing one of three things: it can be waiting for the beam to break, it can have pressed button A and be waiting until it's time to press button B, and it can have pressed both B and A and be waiting to release them.
Most of the time, loop() does nothing. But occasionally an event happens in its environment (the beam, the time) to which it must respond.
enum State {
IDLE, ON, OPEN
} state = IDLE;
uint32_t start_time; // the time at which we entered the current state
// we don't bother with start_time in IDLE state, but ON and OPEN are timed
const uint32_t ON_TIME = 2000; // wait two seconds for power up
const uint32_t OPEN_TIME = 500; // press the open switch for half a second
void setup() {
float button A
float button B
state = IDLE;
}
void loop() {
switch(state) {
case IDLE:
if(beam is broken) {
start_time = millis();
ground button A
state = ON;
}
break;
case ON:
if(millis()-start_time >= ON_TME) {
start_time = millis();
// don't need to ground button A - it's already grounded.
ground button B
state = OPEN;
}
break;
case OPEN:
if(millis()-start_time >= OPEN_TME) {
float button A
float button B
state = IDLE;
}
break;
}
}
like that.
There might be some more logic to do with if the beam is still broken when the OPEN phase times out. Maybe OPEN state should be:
case OPEN:
if(millis()-start_time >= OPEN_TME and button B is not floating) {
float button B;
}
if(millis()-start_time >= OPEN_TME and the beam is not broken) {
float button A;
state = IDLE;
}
break;
Alternatively, you might want to introduce another state for "I have opened the door, but the beam is still broken", and another one for "I have closed the door, and I am not going to open it again for another 5 seconds irrespective of the state of the beam".
Oh incidentally, my code above has a bug. What happens if the open time clicks over after the first if() statement but before the second one? How would you fix it?