Small Railroad Town

I have four LEDs in various buildings. The LEDs are off (LOW) when the ambient light value is greater than 250.
When the light value is greater than 200 but less than 251, the LEDs for the station and street are on (HIGH) and the LEDs for the trailer and orchard are off (LOW). When the light value is less than 200 all LEDS are on (HIGH).

Now…what i wanted to occur next is upon one minute of elapsed time for the trailer light to turn off (LOW). This part of the code does not work as all LEDS remain on (HIGH).

Can someone assist me with the proper code?

Many thanks.

[code]


int trailerLed = 10; // trailer inside lamp
int stationLed = 11; // station inside lamp
int orchardLed = 12; // orchard warehouse inside lamp
int streetLed = 13; // street light
int light = 0; // store the current light value


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
 
}

void loop() {
  // put your main code here, to run repeatedly:
 

  light = analogRead(A0); // read and save value from LDR

  Serial.println(light); // print current light value

  if (light > 250) { // if it is bright all Lights are off
    Serial.println("It is very bright outside!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, LOW);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, LOW);
  }

  else if (light > 200 && light < 251)  { // It is average light, the station and street lights are on
    Serial.println("It is average light!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, HIGH);
  }
  else { // it is dark 
    Serial.println("It is very dark outside!");

    digitalWrite(trailerLed, HIGH);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, HIGH);
    digitalWrite(streetLed, HIGH);
delay(60000UL );
    digitalWrite(trailerLed, LOW);
   
  }
}

[/code]

do you know that blocking code prevents anything from happening ? it is like freezing everything where it is.

delay(60000UL );

do you know how long nothing happens ?
but, in the end, if you wait long enough,
[ op's 60000UL is not a number so might just crash. ]
[ See post #5 Thanks SteveMann for saying it's valid and post #6 by TMFKA AWOL for the time ]
it will reach

digitalWrite(trailerLed, LOW);

for some testing change (60000UL) to (6000)
and try again. see if it goes off after 6 seconds.
then try (60000)

delay() is not preferred, there are better ways.

dave-in-nj:
delay() is not preferred, there are better ways.

Would you like to know more?

I changed the delay to 6000 as suggested but nothing happens. All LEDS remain on (HIGH) as opposed to the trailer LED being off (LOW) and the 3 remaining LEDs being on (HIGH).

I don’t fully understand the millis code in terms of how i would insert this application into my program…so i avoided it and used delay which i thought would achieve the desired result.

int trailerLed = 10; // trailer inside lamp
int stationLed = 11; // station inside lamp
int orchardLed = 12; // orchard warehouse inside lamp
int streetLed = 13; // street light
int light = 0; // store the current light value


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
 
}

void loop() {
  // put your main code here, to run repeatedly:
 

  light = analogRead(A0); // read and save value from LDR

  Serial.println(light); // print current light value

  if (light > 250) { // if it is bright all Lights are off
    Serial.println("It is very bright outside!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, LOW);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, LOW);
  }

  else if (light > 200 && light < 251)  { // It is average light, the station and street lights are on
    Serial.println("It is average light!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, HIGH);
  }
  else { // it is dark 
    Serial.println("It is very dark outside!");

    digitalWrite(trailerLed, HIGH);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, HIGH);
    digitalWrite(streetLed, HIGH);
delay(6000);
    digitalWrite(trailerLed, LOW);
   
  }
}

As mentioned by others above, your code is blocking. That's to be avoided when possible.

Think about what happens in your code.
In the final "else" clause (triggered by dark):
4 LEDs go on
6 (or 60) seconds pass during which time the processor does NOTHING, and all LEDs are on
Trailer LED goes off
the loop cycles back to the top
and a fraction of a millisecond later, the sequence above repeats... the first step being that all of the LEDs go on again!
so....
The trailer LED IS going off, just for such a brief a time that it appears to always be on.

Nonblocking timers are not hard to understand, particularly when you understand that the main loop is typically cycling thousands of times per second. So you:

  1. save a time mark (call it "start time") -- e.g. start_time=millis()
  2. with each iteration of the loop, test the value of (millis()-start_time). When that difference exceeds a certain number which you set, then you take appropriate action. And don't forget to reset the start_time.
    S.

Put some Serial.println() statements into your code to watch where it's going.

BTW, delay() takes an unsigned long in the argument, so 60000UL is absolutely valid. But long. (One hour).

I have used a library in a few of my projects that hides the messiness of millis in a class. You just set the time in ms and start the timer. In loop() you just test if the timer has dinged.

The library is timeObj.h and you can get it at GitHub - leftCoast/LC_baseTools: Tools to make programming Arduinos easier.

SteveMann:
BTW, delay() takes an unsigned long in the argument, so 60000UL is absolutely valid. But long. (One hour minute).

Fixed

First forget getting into millis() AT THIS TIME.

get your lights to work.
if they do not go off after a 6 second delay, comment out the delay
maybe the logic is wrong. is it (LOW) when it should be (HIGH) ?
is something else turning them on/off where else do you turn them off or on?
[ forehead slap acceptable ]

once the lights actually work, only THEN should you start with trying to use millis()

It’s the old, ONE thing at a time approach

The code works fine with the LEDs going from LOW to HIGH as the ambient light value decreases. It is just the six second delay does not work at which point the Trailer Led should turn off (LOW). From previous comments I understand or at least appreciate the blocking concept given the commands are in a continuous loop and executed quickly. So I will rewrite the program to incorporate milis but have not done this before and expect some coding errors. I just hope someone can guide me when I stumble.

// Small Railroad Town
const byte trailerLed = 10; // trailer inside lamp
const byte stationLed = 11; // station inside lamp
const byte orchardLed = 12; // orchard warehouse inside lamp
const byte streetLed = 13;  // street light
int light;            // store the current light value
int timeout;          // One minute timer

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  timeout = 60;
}

void loop() {
  light = analogRead(A0); // read and save value from LDR
  Serial.println(light); // print current light value
  if (light > 250) { // if it is bright all Lights are off
    Serial.println("It is very bright outside!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, LOW);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, LOW);
    timeout = 60;
  } else if (light > 200 && light < 251)  { // It is average light, the station and street lights are on
    Serial.println("It is average light!");
    digitalWrite(trailerLed, LOW);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, LOW);
    digitalWrite(streetLed, HIGH);
    timeout = 60;
  } else { // it is dark
    Serial.println("It is very dark outside!");
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, HIGH);
    digitalWrite(streetLed, HIGH);
    if (--timeout < 0) {
      timeout = 0;
      digitalWrite(trailerLed, LOW);
    } else
      digitalWrite(trailerLed, HIGH);
    delay(1000);
  }
}

redliteal:
So I will rewrite the program to incorporate milis

No, I agree with dave-in-nj. Changing to millis() is a good idea for the future, but it won't fix the problem you have now.

Try this:

    Serial.println("It is very dark outside!");

    digitalWrite(trailerLed, HIGH);
    digitalWrite(stationLed, HIGH);
    digitalWrite(orchardLed, HIGH);
    digitalWrite(streetLed, HIGH);
delay(6000);
    digitalWrite(trailerLed, LOW);
delay(3000);

Does the trailer led come on for 6s, then off for 3s, then back on again?

What type of light sensor is it (link please) how is it connected (schematic please) and where is it physically (photo please)? Could the trailer light be influencing the sensor reading?

My thanks to everyone’s input/advice. The code written by Paul—B does the job perfectly. That’s what I am after.....so thank you very much.

redliteal:
The code written by Paul—B does the job perfectly. That’s what I am after.....

Ah, yes, a tasty fish! You will sleep with a full belly tonight.

redliteal:
The code written by Paul__B does the job perfectly.

But - no "millis()"! :astonished:

Which is ironic, since of course I routinely advocate avoidance of "delay()". Never mind, quick and dirty. :grinning:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.