Keeping a light bulb on when a value is reached

Hi. I'm doing this very simple project where a light bulb is turned on when a photoresistor detects certain light intensity. I did this using a simple "If" statement as you can see below. Now, what I want is to leave the lightbulb on once a certain value is reached. For example, once I read a value of, say 100, my light bulb is gonna turn on and no matter if further on I go back to a value of 95, my light bulb is gonna stay on because I have reached the value I wanted. I've been reading some topics and they say it can be donde by using some of those true or false checks, but honestly I don't understand how they work. Thanks a lot in advance.

By the way. The reason I want to do this is because I want to turn on the lights of my garden automatically when is dark but I noticed that the values I read from the monitor change a lot at any given time, so my light bulbs are gonna be turning on and off very fast once I'm near the values I've put as conditions in my code. So if you think of any other way to avoid this little bug I'd really appreciate it.

float entrada;
const int relay = 10;


void setup() {

  pinMode(relay, OUTPUT);
  Serial.begin(9600);

}

void loop() {

  entrada = analogRead(A0);

  if (entrada > 102) {
    Serial.println(entrada);
    digitalWrite(relay, HIGH);
  }
  else if (entrada < 100) {
    Serial.println(entrada);
    digitalWrite(relay, LOW);
  }
}

First off, Google Hysteresis.

If that all you really want to do, then just remove the 'elseif' part of your code and you should be good to go!

hope that helps...

PS: it seem a waste of a microprocessor for such a basic opertation. a transitor and a DPDT relay would do just that job! :wink:

Hi. I tried doing that but it doesn't work. When I remove the else part I don't get any readings from the monitor. And I know it could be done in a much easier way, Is just that this is the way Im trying to learn Arduino, by doing simple stuff Im learning about their components and how they work.

if (entrada > 102)
{
Serial.println(entrada);
digitalWrite(relay, HIGH);
}

if (entrada < 80)
{
Serial.println(entrada);
digitalWrite(relay, LOW);
}

Yes.
Exact example of hysteresis input.
Maybe you need to pick more difference between "turn on/off" readings for proper functioning.

Some other thoughts .

  1. The light from bulb may interfere with photoresistor readings.

  2. You send signal to turn on|off again and again in fast loop.
    For simple circuits it's not a issue.
    But maybe better use a little more bulky code with saving bulb current state and made digitalWrite on state change only.
    (Also, you made a constant "Serial.println" loop, that is not good too)

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


Make sure the lamp isn’t near the sensor.


You can also turn the lamp ON for at least 1 hour to let the ambient light further degrade.

No, that's not what you want :wink: You want the light to turn off in the morning when the sun rises again - or perhaps even sooner than that, during the night when they're not needed. So I think you need to think a bit deeper about your actual specifications.

Hi, no, this is exactly what I want because I can just turn off the lamp with a manual switch when I go to sleep. I just want the lamp to be turned on when a certain reading is reached and I want it to stay on until I manually turn if off. I know it probably doesnt make sense or it is a waste of Arduino like some say but, believe me it works for me. :slight_smile:

So the moment you flip the switch again in the morning, the lights go on because the Arduino still believes they should be on - it turned them on hours ago, after all, so it will keep them on.

So again, some more thought is needed.

Hint: don't use a physical switch for the 'manual override' function, but a button that sends a signal to the Arduino and let the Arduino have full control over the lights.

Hi, thanks for replying. Im working on the schematics. Let me raise you a similar situation. Let's say I have a common led which response depends on the readings of a sensor. The led will stay off until a certain threshold value is reached by the sensor, in that point the led will turn on. Now, according to my code, if at a certain point in time I go back below of my threshold value, the led will turn off again because that’s how my code is written. Now, all I want is to have my led on once I’ve reached the threshold value (until I manually switch it off), and I want it to stay that way no matter if further on for some reason I go back below that value. Is there a simple way to do that? I mean in general, it doesn't have to be for my specific project.

Yeah, no. I already solved all of what you're saying. My simple device works perfectly for my own purposes. All Im asking here is if there's an easy way to override my If conditions once a certain value is reached. I just want my lamp to stay on once a threshold value has been reached and I want it to stay that way no matter if further on for whatever reason I go back below that certain value. Is there a simple way to do that? I mean in general, it doesn't have to be for my specific project.

Sure, just make a boolean variable called 'turned_the_light_on' or something, set it to false on startup, as soon as the lamp is turned on by the Arduino, also toggle that 'turned_the_light_on' bool to 'true' and then make sure in the main loop to only read and process the ADC input if 'turned_the_light_on' is false.
I'm still not convinced about your story about the manual override, but since you specifically want to tackle the issue addressed above, I won't complain about it any further :wink:

Thanks a lot. That's what I wanted, I read it could be done with the boolean variables but I don't understand how they work, I've never used them before. If it is not too much to ask, would you mind adding that part to my code? or if you could link me to a similar example where it is explained. Of course I tried searching but had no luck. Thank you again.

And about the manual override. Works for me because I'm no planning to use the Arduino everyday, I just want to use it for the days nobody's home to manually turn on the lights. I know there's probably I 2$ device on amazon that can do that much better, but like I said, this is the way Im trying to teach myself Arduino.

float entrada;
const int relay = 10;
bool turned_the_light_on = false;

void setup() {

  pinMode(relay, OUTPUT);
  Serial.begin(9600);

}

void loop() {

  if (turned_the_light_on) return;

  entrada = analogRead(A0);

  if (entrada > 102) {
    Serial.println(entrada);
    digitalWrite(relay, HIGH);
    turned_the_light_on =  true;
  }
  else if (entrada < 100) {
    Serial.println(entrada);
    digitalWrite(relay, LOW);
  }
}
1 Like

Of course you could simplify as a large part of your code is actually redundant:

const int relay = 10;
bool turned_the_light_on = false;

void setup() {

  pinMode(relay, OUTPUT);
  Serial.begin(9600);

}

void loop() {
  
  if (turned_the_light_on) return;

  int entrada = analogRead(A0);
  if (entrada > 102) {
    Serial.println(entrada);
    digitalWrite(relay, HIGH);
    turned_the_light_on =  true;
  }
}

Also note that you used float for entrada, while analogRead really returns an int. There's no good purpose for using a float there and can only be confusing.

1 Like

Finally, I'd like to emphasize what @sherzaad said earlier: this is kind of a waste of a perfectly good microcontroller :wink: He's right in that you can easily do the same with about 4 discrete components that cost even less than an Arduino Nano.

1 Like

Try this:



#define PUSHED                  LOW
#define lampON                  true
#define lampOFF                 false

#define HOURS                   1000ul * 60 * 60 * 2  // two hours        <----<<<< change to what's needed
//#define HOURS                   5000ul //for testing, 5 seconds

const byte OFFswitch          = 2;     //+5v----INPUT_PULLUP (50k)----[input pin]----[switch]----GND
const byte relay              = 10;
const byte heartbeatLED       = 13;

const byte LDR                = A0;

bool lampFlag                 = lampOFF;

int entrada;

unsigned long heartbeatMillis;
unsigned long lampMillis;
unsigned long lampOnDuration  = HOURS;


//**************************************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(OFFswitch, INPUT_PULLUP);
  pinMode(relay, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);

} //END of setup()


//**************************************************************************
void loop()
{
  //*************************************
  //time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis > 500)
  {
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  entrada = analogRead(LDR);

  //*************************************
  //is it dark enough ?
  if (lampFlag == lampOFF && entrada > 102)
  {
    Serial.println(entrada);

    //turn on the light
    digitalWrite(relay, HIGH);

    //start the TIMER
    lampMillis = millis();

    //enable the TIMER
    lampFlag = lampON;
  }

  //*************************************
  //has the manual OFF switch been pushed ?
  if (digitalRead(OFFswitch) == PUSHED)
  {
    //turn OFF the lamp
    digitalWrite(relay, LOW);

    //disable the TIMER
    lampFlag = lampOFF;
  }

  //*************************************
  //comment the: if()block, when no automatic OFF time is needed
  //if the lamp is ON, is it time to turn OFF the lamp ?
  if (lampFlag == lampON && millis() - lampMillis > lampOnDuration)
  {
    //turn OFF the lamp
    digitalWrite(relay, LOW);

    //disable the TIMER
    lampFlag = lampOFF;
  }

  //*************************************
  //other non-blocking code goes here
  //*************************************
  
} //END of loop()
1 Like

Hi. I just wanted to let you know that this works perfectly, it does exactly what I wanted. I think I could 've saved us some time if I had explained myself better from the beginning, I apologize for that. But seriously, thank you so much for taking the time to answer, I really appreciate it. Just one las thing, I was wondering if you know about some online article I could read to understand better what is it that you did here cause I don't quite get it. I mean it works but I'm not sure why :laughing: I understand boolean variables and I know we declared one at the begining as false, then if the condition is met the state of the variable will change to true, but I don't understand how you managed to override the "if" function or what exactly the "return" function does, I'm reading the reference in the Arduino page but I'm not sure how the description of those functions relates to what you did. Thank you so much again for your time.

It basically ends the loop(), but since it's the main loop, it immediately restarts the loop() again, so it just keeps evaluating that first if-condition indefinitely.