I need to know the times when an LED strip turns on and turns off. The LED switch is driven by light dependent resistor. When the sun goes down the LED strip turns on. This is all happening on a circuit that I did not create nor is it Arduino driven. I need to know the times (in local time) that the LED turns on and off. I have another light dependent resistor near the LED strip and I am using the Arduino Uno to print to the serial monitor its state every second. I can listen to the serial port via Python and record the seconds via Python. No worries What I would like to do is have the Arduino code print to the serial monitor only if the state of the LED changes. For example, when the LDR turns on the LED strip, Arduino prints to the serial monitor once, then in the morning when the LED goes off, print to the serial monitor once. I am having trouble figuring out the code to do that. The LDR is not like a button since it is always reporting back analog data. Any help is appreciated.
-
1You need to keep track of the previous value and compare the current value to that. (It may work better to keep track of the last few dozen previous values and compare the averages of, e.g., the last dozen to the dozen before that.) Does this help you try to write some code that you could put into your question for us to help you further with?– cjsCommented Apr 22, 2017 at 1:07
-
Ditto. Especially the idea of taking multiple readings before deciding it is a for-real change and not just a glitch.– SDsolarCommented Apr 23, 2017 at 1:27
4 Answers
You wrote: “I am using the Arduino Uno to print to the serial monitor its state every second.” This is exactly the right thing to do. Make a record of the analog readings for a few days, then plot the readings as a function of time.
Once you have a nice plot, take a close look at it. You should be able, by reading the plot, to decide on a threshold value that you can use to tell whether the LEDs are on or off. Or, better yet, two thresholds in order to have some hysteresis.
Then you can write something like this:
const uint8_t LDR_PIN = ...;
const uint16_t THRESHOLD_LOW = ...;
const uint16_t THRESHOLD_HIGH = ...;
uint8_t state = LOW;
void loop()
{
uint16_t reading = analogRead(LDR_PIN);
if (state == LOW && reading >= THRESHOLD_HIGH) {
Serial.println("Reading is now HIGH.");
state = HIGH;
} else if (state == HIGH && reading < THRESHOLD_LOW) {
Serial.println("Reading is now LOW.");
state = LOW;
}
}
-
+1 for the hysteresis -- it quickly handles the debouncing since it will trigger once on the first observation above the threshold, and won't reset until it is definitely lower.– Dave XCommented Jan 22, 2022 at 14:51
If you have already set the resistor to print to Serial
every second, then it is simple to modify. Your code is probably like this:
void loop() {
// something something
Serial.println(analogRead(resistorPin));
// other other
}
and you want something like this:
int lastValue,newValue;
int treshold=200; // or some other empirical value,
// analogRead() returns 0..1024, so it should be safely inside
void loop() {
// something something
newValue=analogRead(resistorPin);
if (newValue-lastValue > treshold) {
Serial.print("Value increased to ");
Serial.println(newValue);
lastValue=newValue;
};
if (lastValue-newValue > treshold) {
Serial.print("Value decreased to ");
Serial.println(newValue);
lastValue=newValue;
};
// other other
}
the treshold
value should be set so the event is triggered if substantial change in value happend (so probably those LEDs went on/of) but not trigger when there is a smal change (like cloud going on sky).
Eventually you can also print the time, at which the event happened, using something like http://playground.arduino.cc/Code/DateTime or http://playground.arduino.cc/Code/Time or any other library suiting your needs. You may also consider to use some real time module like https://www.pololu.com/product/2770 or https://www.adafruit.com/product/264 or https://learn.adafruit.com/adafruit-ds3231-precision-rtc-breakout/overview or any other RTC module you like/have.
-
Python
datetime
module can also be used to timestamp the events, this will eliminate the need for syncing or using external RTCs.– FauzanCommented May 24, 2017 at 12:01
An LDR doesn't have a "state", being a resistor that varies continuously, and inversely with the light intensity. The LED strip has distinct states: lit and not lit. It sounds like you want your code to deduce the LED state from the sensor value. You'll need to define lighting states based on the the LDR readings, and those readings won't be consistent; they'll vary from measurement to measurement of the same lighting conditions and they'll be affected by changes in the ambient lighting. If you can exclude ambient light falling on the LDR, the job will be easier. @Edgar_Bonet described a way to ranges of LDR readings corresponding to 'lit' and 'not lit'
When a moving average of LDR readings, or some number of consecutive LDR readings falls within the range contrary to the state your code been keeping for the LED lighting, it should change the state and print.
If ambient lighting changes are unavoidably affecting the LDR, you'll definitely need to keep some sort of moving average and watch for a large difference between a small number of averaged readings and the longer-term moving average used to correct for ambient. This is a kind of auto-zeroing and it can lead to its own errors: sensing the room lights being turned on or off, cloud shadows, or a person or animal passage throwing a shadow, can all cause false change-of-state detection.
Update:
I'd add that you might compare the LDR output to 3 ranges: [0 - MAXDARK], [MINLIGHT - 1023], and "neither" - the gray zone in between. This is analogous to how the digital input-pin receivers in the MUC decide whether a digital signal (which is inherently analog) is HIGH or LOW. You'll have to experiment with the values of MAXDARK and MINLIGHT to find the right values for your environment.
Then you you'd print, once, whenever the LDR signal solidly enters either the MAXDARK or MINLIGHT zones, and not again until after the signal has solidly exited that zone, or equivalently, solidly entered the gray zone.
"Solidly" is probably something like NCONSECUTIVE averaged samples. Again, you'll have to find a value for NCONSECUTIVE that is both reliable and responsive. Too low a value may give you several time-stamps for the same event; too high a value will delay how quickly you detect the event (which might be totally irrelevant for a twice-a-day event).
I need to know the times (in local time) that the LED turns on and off. .. I am having trouble figuring out the code to do that.
simple.
attach a pin to the circuit's output that turn on / off the led.
set up your arduino to read the state or state changes of that pin. this can be done via interrupts or polling.
based on the state of the pin, determine if the led is on or off, and record the current time.
step #1 can be done with light sensors (on the led's light output). but that can be slightly trickier.
The LDR is not like a button since it is always reporting back analog data.
you can set up the ldr to read it like a button.