1

I am trying to write a code where photoresistors (a or b) sense blinking of the light, and lights LED (k and d) simultaneosly with that blinking. And I want that when both photoresistors sense dark for more than 3 secs, the LEDs would light up and stay until one of them again gets lighting. But I cannot understand in which part should I put millis time count?

int k = 2;
int d = 3;
int fk = A0;
int fd = A1;
int a = 0;
int b = 0;

void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  a = analogRead (fk);
  b = analogRead (fd);
  while (a < 1000 && b < 1000)
  {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    a = analogRead (fk);
    b = analogRead (fd);
  }
  if (a > 1000)
    digitalWrite(2, HIGH);
  else
    digitalWrite(2, LOW);
  if (b > 1000)
    digitalWrite(3, HIGH);
  else
    digitalWrite(3, LOW);
}
VE7JRO
  • 2,515
  • 19
  • 27
  • 29

3 Answers3

3

This is one of those cases where the solution is simply to implement a finite state machine. Consider a state machine with these three states:

  • LIGH: light has been detected by at least one of the sensors, the LEDs follow the light sensors
  • SHORT_DARK: neither sensor sees light, both LEDs are off
  • LONG_DARK: it has been at least three seconds since neither sensor saw light, both LEDs are on.

The transitions between those states can be depicted by the following state diagram:

state transitions

where “darkness detected” means that no sensor sees light, and “light detected” means that at least one sensor sees light.

As a general rule, it is a good practice to always draw a state diagram before you start writing code. Once you are sure your diagram describes the desired behavior, it is almost trivial to translate it into code. Here is how I would code it:

void loop()
{
    bool light_k = analogRead(IN_K) >= 1000;
    bool light_d = analogRead(IN_D) >= 1000;

    static enum { LIGHT, SHORT_DARK, LONG_DARK } state;
    static uint32_t darkness_start;
    switch (state) {
    case LIGHT:
        digitalWrite(OUT_K, light_k ? HIGH : LOW);
        digitalWrite(OUT_D, light_d ? HIGH : LOW);
        if (!light_k && !light_d) {
            darkness_start = millis();
            state = SHORT_DARK;
        }
        break;
    case SHORT_DARK:
        if (light_k || light_d) {
            state = LIGHT;
        } else if (millis() - darkness_start >= 3000) {
            digitalWrite(OUT_K, HIGH);
            digitalWrite(OUT_D, HIGH);
            state = LONG_DARK;
        }
        break;
    case LONG_DARK:
        if (light_k || light_d) {
            state = LIGHT;
        }
        break;
    }
}
Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81
2

Millis gives you a measure of time. You can store that measure and compare to it later. I don't know what in your code represents a sense of dark/light in your code (resistors can be used to raise or lower the measured input depending on your circuit) so you will have to work the following in by replacing stuff in <>

unsigned long lastlight;
void loop()
{
    if (<isLitSensorA>) lastlight = millis();
    if (<isLitSensorB>) lastlight = millis();
    if(millis() - lastlight > 3000){ //3 sec since lastlight
        <LightsAlwaysOn>
    }
    else{
        <BlinkWithLights>
    }
}
Abel
  • 41
  • 2
0

Here is a more elegant way to do this. This program doesn't require you to actually count it has been dark, instead it just remembers the time it has last seen the light (how poetic ;). I also added some commentary alongside the code.

// All the variables
int k = 2;        // LED 1
int d = 3;        // LED 2
int fk = A0;      // photoresistor 1
int fd = A1;      // photoresistor 2
int lastLight = 0;

// Set up the LEDs
void setup() {
  pinMode(k, OUTPUT);
  pinMode(d, OUTPUT);
}

void loop()
{
  // Check the photoresitors
  int a = analogRead (fk);
  int b = analogRead (fd);
  if (a > 1000 || b > 1000)
  {
    // Turn LEDs on if one photoresitor senses light
    digitalWrite(k, HIGH);
    digitalWrite(d, HIGH);
    // Also set the last time it was bright to the current time
    lastLight = millis();
  }
  else if (abs(millis() - lastLight) > 3000)
  {
    // Turn LEDs on if it has been dark for more than 3 seconds (that is 3000 milliseconds)
    digitalWrite(k, HIGH);
    digitalWrite(d, HIGH);
  }
  else
  {
    // Turn LEDs off
    digitalWrite(k, LOW);
    digitalWrite(d, LOW);
  }
}
LukasFun
  • 295
  • 1
  • 4
  • 17