Switching problem.

Hi guys! First of all i would like to say hello to all uP enthusiast. I just started to discover Arduino, and I'm fully suprised how powerfull thing it is.

But now I need your help I have a problem and totally don't know why it happens.

I wrote simple program, making my output pin HI when two of my input pins are HI otherwise output pin = LOW.

I'm a bit confused couse It seems to be easy but it's doesn't work as it should.
When I have HI signal on two my inputs, my output voltage going to HI directly, but when one of my input going LOW then output should be LOW as well but it's LOW after 5 seconds, so switching to HI is ok, but switching to LOW takes always 5 seconds.

Here is the proof:

And here is my last tested program:

int button_1 = 8;
int button_2 = 9;
int output_pin = 13;

int buttonState_1 = 0; 
int buttonState_2 = 0; 

void setup ()
{ 
  pinMode(button_1, INPUT);
  pinMode(button_2, INPUT);
  pinMode(output_pin, OUTPUT);

}

void loop()
{
  buttonState_1 = digitalRead(button_1);
  buttonState_2 = digitalRead(button_2);


    if (buttonState_1 == HIGH && buttonState_2 == HIGH)
  {
    digitalWrite(output_pin, HIGH); 
  }
  else
  {
  digitalWrite(output_pin, LOW);
  }
}

Switching problem? Have no idea. Maybe I should use FOR or WHILE loop as a control structure?

Thanks for your time!
Best regards!

How are the inputs wired, and to what?

Wire from +5V to pins 8 and 9.

What voltage is present on pins 8 and 9 when the buttons are not connecting them to 5V ?

You cannot assume that they are at 0V because they are floating at an uncertain voltage. Tie them to GND with 10K resistors so that you know that they are at 0V or enable the internal pullup resistors
pinMode(button_1, INPUT_PULLUP);and reverse the logic of your tests.

UKHeliBob Thanks for help, I'm gong to test your solution .

It's working fine right now. Hard to believe pull-down resistor solved problem. Thanks for help. Now I can go ahead with my program.

Taking the opportunity I would like to ask about one more thing, when I have code like this:

if (button == HIGH && photocell == HIGH && level_sensor == LOW)
 {
  digitalWrite(output, HIGH);
else 
  digitalWrite(output, LOW);
}

How to make button level HIGH for ex. 5 second when I just pressed button once. Should I use a variable that saves the state of the button change or there is some kind of delay I can use in that case?

ADesign:
How to make button level HIGH for ex. 5 second when I just pressed button once. Should I use a variable that saves the state of the button change or there is some kind of delay I can use in that case?

The code needs to be very different to what you showed. There are two parts to it. You need to determine whether the button is changing from pressed to unpressed or vice versa. This is called edge detection, and there's an example sketch 'StateChangeDetection' that shows you how to do it. Then when the button becomes pressed you need to set your output HIGH and record when you set it high by storing the value of millis() in a variable. Subsequently you will use the approach demonstrated in the blink without delay example sketch to test whether the pin is high and whether it has been high for longer than your defined interval, and if so then set it low.

ADesign:
Hard to believe pull-down resistor solved problem.

Pulldown resistors were invented to solve exactly this problem. That's like saying, "Hard to believe that hammer shoved that nail into that wood so effectively."

PeterH:

ADesign:
How to make button level HIGH for ex. 5 second when I just pressed button once. Should I use a variable that saves the state of the button change or there is some kind of delay I can use in that case?

The code needs to be very different to what you showed. There are two parts to it. You need to determine whether the button is changing from pressed to unpressed or vice versa. This is called edge detection, and there's an example sketch 'StateChangeDetection' that shows you how to do it. Then when the button becomes pressed you need to set your output HIGH and record when you set it high by storing the value of millis() in a variable. Subsequently you will use the approach demonstrated in the blink without delay example sketch to test whether the pin is high and whether it has been high for longer than your defined interval, and if so then set it low.

Peter I spent almost two days to testing it in many different combination :frowning: and it doesnt really work for me.
In blinkingwithoutdelay example there is 'milis()' value which contains value of time since Arduino started and I don't really need it.

I wrote code which is almost working as I want, but with delay() and as We know delay stoped programm for some time, and my problem is I would like to make it running instead of delay.

I only need to "hold" value of momentary switch in variable called "momentary_switch_value" for some time and use it later in if function like this:

if (momentary_switch_state == HIGH && photocell == HIGH && level_sensor == LOW )
 {
  digitalWrite(output, HIGH);
else 
  digitalWrite(output, LOW);
}

So when I pressed switch once I woul like to have momentary_switch_state value in HIGH level for 10 seconds.
This supposed to be so easy and make me crazy.

Could U guys please give me any example how it should be done couse all my ideas disappered.

Something like this pseudo code

if momentary_switch_state has just become HIGH
  set countDown = millis()  //start of the countdown
  set pressed = true   //flag that the key has been pressed
end of if

if millis() - countDown >= 10000  //end of the 10 second countdown
  set pressed = false  //indicator that the time is up
end of if

if (momentary_switch_state == HIGH && photocell == HIGH && level_sensor == LOW && pressed == true)
 {
  digitalWrite(output, HIGH);
else 
  digitalWrite(output, LOW);
}

NOTE that it is the change from LOW to HIGH that starts the countdown, and that the principle used here will only work if the loop() function has no blocking code in it, such as delay(), because it depends on the program continually checking the countdown against the current number of milliseconds that have elapsed. Look at the BlinkWithoutDelay example in the IDE to see a full program that uses this principle.

ADesign:
Peter I spent almost two days to testing it in many different combination :frowning: and it doesnt really work for me.
In blinkingwithoutdelay example there is 'milis()' value which contains value of time since Arduino started and I don't really need it.

I may be misunderstanding you, but I think you definitely do need millis() to implement what you are asking for. Any time you are counting elapsed time, you need to know what time it is now, so you can know how much time it has been since you started counting. For example, if I said to you, "Meet me for lunch in a half hour," what's the first thing you would do? Look at what time it is now.

now = millis();

Then you would take the amount of time you needed to wait...

waitTime = 30; // let's just pretend for the sake of example that millis() returns minutes, not milliseconds

And you would add it to the current time, to find out what time you needed to meet me for lunch...

meetingTime = now + waitTime;

So if it is 11:30 AM (now) and you need to meet me in a half hour (30 minutes), you would meet me at 11:30 + 30 minutes = 12:00 PM. Okay, so now you know what time you need to meet me. Now let's say that you get a phone call, and halfway through the call, you think, "Oh heck! Am I late for lunch?" You check the time.

now = millis();

Has the lunch time already passed or not?

if (now > meetingTime)
    // you're late!
  else
    // you're not late yet.

These types of time-keeping operations are exactly what you will need to use to keep the output high for ten seconds after the button is pressed. The button pressed will be the phone call from your friend, saying, "Meet me in a half hour," except instead of saying that, it will be saying, "Turn the input off in ten seconds." The "meetingTime" will be the time at which you will turn the input off. During loop, you will continually check the time now to see if the meetingTime has passed or not, and when it has, you will turn the input off.

One final addition: there is a nuance to the implementation of the millis() function that means that you should not do this:

if (millis() > meetingTime)

but rather must do this:

if ((millis() - triggerTime) > period)

where triggerTime is the time that the timer was started, button was pressed, and so forth, and "period" is the duration of the event--in your case, 10 seconds.

The reasons for this have to do with rollover of variables and two's-complement arithmetic, but I suspect they are not worth delving into here.

Thanks guys for explanations how it should be done. Ive made many test with millis() function and it still do not working in proper way.

I wrote simple program with your instruction:

int button_1 = 8;
int output_1 = 12;
int momentary_switch_state; 

void setup ()
 { 
     pinMode(button_1, INPUT);
     pinMode(output_1, OUTPUT);   
 }
  
void loop()
 {
    momentary_switch_state = digitalRead(button_1);
    boolean pressed; 
    long interval = 10000; 
    long countDown;
    
    if (momentary_switch_state == HIGH)
      {
      countDown = millis();
      pressed = true;
      }
      
    if ((millis() - countDown) >= interval)
      {
      pressed = false;
      }
   
    if (momentary_switch_state == HIGH && pressed == true)
    {
    digitalWrite(output_1, HIGH); 
    }
    else
    {
    digitalWrite(output_1, LOW);
    }
  }

Tested many times, many different options and still same. There is HIGH level on output only when I hold push button, when release push button, output became LOW.

Could someone check code structure maybe i wrote something wrong.

One more time big thanks for your time!
Best regards.

Change:

if (momentary_switch_state == HIGH && pressed == true)

to

if( pressed )

Tested many times, many different options and still same. There is HIGH level on output only when I hold push button, when release push button, output became LOW.

It sounds like you are wanting to control the voltage at the button. Since it is an input, you cannot control it. You can only respond to what it is reporting.

If you want it to act like the button is holding the state it had when it was pushed, (1) go ahead and do what it is supposed to do when pushed, then (2) ignore its input for the five seconds. At the end of the five seconds, start listening to it again.

Did this answer the question you were asking?

Yes Arduinonerd, kind of.

I would like to have something like "time lag relay" and just press the button once (don`t want to hold it whole 5 or 10 sec) then if Arduino detect that the button was pressed I would like Arduino to hold this value for next 10 sec.

BR!

Try this

byte currentButtonState;
byte previousButtonState;
const byte buttonPin = 9;
const byte ledPin = 13;
byte ledState = LOW;
unsigned long waitTime = 19000;
unsigned long startOfWait;
boolean waiting = false;

void setup() 
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
}

void loop() 
{
  previousButtonState = currentButtonState;
  currentButtonState = digitalRead(buttonPin);

  if  ( (currentButtonState != previousButtonState) && currentButtonState == LOW)
  {
    startOfWait = millis(); 
    waiting = true;
    ledState = HIGH;
  }

  if ( (millis() - startOfWait >= waitTime) && waiting == true)
  {
    ledState = LOW;
    waiting = false;
  }
  digitalWrite(ledPin, ledState);
}

Note that the button pin is not debounced so will sometimes trigger the LED when released if it is held down whilst the LED is on.