if statement with sensors and timing

I'm completely stuck with writing an If statement for my Arduino Uno, checking for 2 sensor states and a clock statement.

What do I want to achieve:

if:

  • LightBarrier is high
  • LightSensor is high
  • time is in between 23.00 and 07:00

==> digitalWrite(8,LOW);
==> digitalWrite(9,HIGH);

if (LightBarrier == HIGH && LightSensor == HIGH && hour() >= 23 || hour() < 7) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);

But this statement doesn't work :frowning:
In this case when the time is in between 0:00 and 07:00, the actions will be performed, even if the LightBarrier and LightSensor are low, just because the time statement (|| hour() <7) is true.

On the other hand, hour() >= 23 && hour() < 7 neither does work, since these can never be true at the same time...

Who helps me with a brilliant answer? :slight_smile:

Operator precedence issue. Needs brackets:

if (LightBarrier == HIGH && LightSensor == HIGH && (hour() >= 23 || hour() < 7))

I would make it even more explicit

if ((LightBarrier == HIGH && LightSensor == HIGH) && (hour() >= 23 || hour() < 7))

Thank you! That helped. I already tried the extra () brackets, I think I did something else wrong.
Looking at the code below:

    if (LightBarrier == HIGH && LightSensor == HIGH && (hour() >= 23 || hour() < 7)) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
    
    if (LightBarrier == HIGH && LightSensor == HIGH && hour() >=7 && hour() <23) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);

makes PIN 9 go HIGH between 23.00 and 07:00 when the 2 sensors are HIGH :slight_smile:
I made a mistake with the second if statement, saying: && (hour() >=7 || hour() <23))

When the number gets above 7, both if statements are true, and PIN 9 is 'half-high' because of 2 if statements telling it what to do.

Now by putting the between 7 and 23 with &&, the problem is solved! :smiley:

yellowfish:
Thank you! That helped. I already tried the extra () brackets, I think I did something else wrong.
Looking at the code below:

    if (LightBarrier == HIGH && LightSensor == HIGH && (hour() >= 23 || hour() < 7)) {

digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
   
    if (LightBarrier == HIGH && LightSensor == HIGH && hour() >=7 && hour() <23) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);




makes PIN 9 go HIGH between 23.00 and 07:00 when the 2 sensors are HIGH :)
I made a mistake with the second if statement, saying: && (hour() >=7 || hour() <23))

When the number gets above 7, both if statements are true, and PIN 9 is 'half-high' because of 2 if statements telling it what to do.

Now by putting the between 7 and 23 with &&, the problem is solved! :D

Now by putting the between 7 and 23 with &&, the problem is solved! :smiley:
Yes if you want to process between 7 and 22.
BTW in your original code the processing precedence was OK, but the logic was incorrect.
Hope this will help you to understand the real issues, not just the customary "it works and I don't care why" .
Happy New year.

What do you want to happen when either LightBarrier or LightSensor are LOW ?

As both of the tests that you have shown depend on them both being HIGH then you could do this

if (LightBarrier == HIGH && LightSensor == HIGH)
{
  digitalWrite(8, LOW);
  if (hour() >= 23 || hour() < 7)
  {
    digitalWrite(9, HIGH);
  }
  else
  {
    digitalWrite(9, LOW);
  } 
}

This avoids having 4 conditions in one if test and the value of hour() needs only to be tested once to see if it is between 23 and 7.

and the value of hour() needs only to be tested once to see if it is between 23 and 7.

Well, twice, but who's counting... 8)

Well, to be pedantic, the test to see whether it is between 23 and 7 only occurs once, but I wouldn't be pedantic, would I... :wink:

Thank you all for the replies.
Actually what I want to achieve is a little more difficult...

Attached is the code in the loop() which should do the hard work.
The difficult thing with the LightBarrier is, that it's triggered physically for a second or so. So I'm not able to write my if statements with LightBarrier == HIGH and perform certain actions, as I want one output to be triggered for a second, and the second output for a longer time. As soon as the Barrier isn't triggered anymore, my code won't work anymore.

So I'm saving the trigger in the memory as in the code below, and with that number I tried to create all unique IF statements during day and night time.

So to give a short explanation of the goal:

  • daytime, LightSensor == HIGH --> triggering of the LightBarrier should set pin 8 HIGH for a second, PIN 9 (which is lightning) should stay LOW

  • as soon as it gets dark, PIN 9 should get high, triggered by LightSensor == LOW until 23:00. When the LightBarrier gets triggered output 8 should get HIGH for a second. PIN 9 should always be HIGH during this time.

  • between 23:00 and 6:00 the next day, the LightSensor is still LOW, PIN9 should get LOW. When the LightBarrier gets triggered, PIN 8 should get high for the time of the BarrierTimer, and PIN 9 should get HIGH for the LightningTimer

  • between 6:00 until daytime, same actions as in dot 2

I hope this makes sense. The code below is the last test which I did 10 minutes ago after some changes.
It seems that my Arduino is behaving strange now, triggering of the different sensors/timers now. Going to do more research, any help is appreciated :slight_smile: The first conclusion is though, that the scenario during daytime works correctly. When LightSensor == LOW the problems seem to occur. Maybe I'm making a mathematical mistake, or my IF statements are not unique...

BTW a last comment, I've replaced hour() for second() in my tests, as I don't want to run the test in cycles of 24 hours :wink:

void loop() {
  
  LightBarrier = digitalRead(switchPin);
  LightSensor = digitalRead(switchPin2);
  
  DigitalClockDisplay();
    
    //alarm triggered, setting timers for barrier and light sensor
    if (LightBarrier == HIGH) {
    x = millis();
    }
    
    //alarm, situation day, from triggering LightBarrier up to end BarrierTimer
    if (LightSensor == HIGH && x + BarrierTimer > millis() && x + LightTimer > millis()) {
      digitalWrite(8,HIGH);
      digitalWrite(9,LOW);
    }
    //alarm, situation day phase 2, between BarrierTimer and LightTimer
    if (LightSensor == HIGH && x + BarrierTimer < millis() && x + LightTimer > millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);
    }
    
    //no alarm, situation dark, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && x + LightTimer < millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
    
    //no alarm, situation dark, between 23:00 en 6:00 hour
    if (LightSensor == LOW && (second() >= 23 || second() < 6) && x + LightTimer < millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);
    }

        //alarm, situation dark, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && x + BarrierTimer > millis() && x + LightTimer > millis()) {
      digitalWrite(8,HIGH);
      digitalWrite(9,HIGH);
    }

    //alarm, situation dark phase 2, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && x + BarrierTimer < millis() && x + LightTimer > millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
}

Alright, that was pretty stupid... I missed two if statements during 23:00 and 6:00 hour, specifying the alarm situations triggering output 8 and 9. After that I made a mistake with placing a } on the wrong place, which totally messed my sketch up :frowning:

It seems to be running smoother now, only in the first sequence it's doing some weird timing thing, which probably have to do with the initial value of x.

x = -1000, and LightBarrier = 1000, LightSensor = 10000.
I think I need to define y = -10000 somewhere and work with that.

But that's for tomorrow :slight_smile:

Code attached.

void loop() {
  
  LightBarrier = digitalRead(switchPin);
  LightSensor = digitalRead(switchPin2);
  
  DigitalClockDisplay();
    
    //alarm triggered, setting timers for barrier and light sensor
    if (LightBarrier == HIGH) {
    x = millis();
    y = millis() + BarrierTimer;
    }
    
    //alarm, situation day, from triggering LightBarrier up to end BarrierTimer
    if (LightSensor == HIGH && x + BarrierTimer > millis() && x + LightTimer > millis()) {
      digitalWrite(8,HIGH);
      digitalWrite(9,LOW);
    }
    //alarm, situation day phase 2, between BarrierTimer and LightTimer
    if (LightSensor == HIGH && x + BarrierTimer < millis() && x + LightTimer > millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);
    }
    
    //alarm, situation dark, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && x + BarrierTimer > millis() && x + LightTimer > millis()) {
      digitalWrite(8,HIGH);
      digitalWrite(9,HIGH);
    }
  
    //alarm, situation dark phase 2, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && x + BarrierTimer < millis() && x + LightTimer > millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
        
    //no alarm, situation dark, between 6:00 and 23:00 hour
    if (LightSensor == LOW && second() >=6 && second() <23 && y + LightTimer < millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }
    
    // alarm, situation dark, between 23:00 and 6:00 hour
    if (LightSensor == LOW && (second() >= 23 || second() < 6) && x + BarrierTimer > millis() && x + LightTimer > millis()) {
      digitalWrite(8,HIGH);
      digitalWrite(9,HIGH);
    }
    
    // alarm, situation dark phase 2, between 23:00 and 6:00 hour
    if (LightSensor == LOW && (second() >= 23 || second() < 6) && x + BarrierTimer < millis() && x + LightTimer > millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,HIGH);
    }

    //no alarm, situation dark, between 23:00 and 6:00 hour
    if (LightSensor == LOW && (second() >= 23 || second() < 6) && x + LightTimer < millis()) {
      digitalWrite(8,LOW);
      digitalWrite(9,LOW);
    }
}

I'm not very clued up on this, but isn't this project a prime candidate for a state machine approach, for which there is a library in the playground.

Search the forum too- there have been loads of posts concerning this lately.

I have looked into the state machine yes, but to be honest I wasn't aware of that library!
Will have a look to that later to make the code smarter.

So the code now seems to perform as expected, with one exception that I don't understand (is solved already)

I have a comparison in a IF statement, at boot of the arduino saying -10001 + 10000 > 0
What I don't understand is that this seems to return a TRUE, instead of an expected FALSE, since the logical outcome is -1 which is smaller then 0 and not bigger... Is this Arduino logic?

I've changed the -10001 to -10000 which solved the issue... weird :astonished: