1

As the sensor "sees" an object nearby, it makes the LED go to full brightness and it remains like that for as long as the sensor keeps on sensing the object. Then, as soon as the sensor stops sensing it, the LED goes OFF instantly... and so on, endlessly. This part of the code works perfectly as it is right now.

MY PROBLEM:

I need all of this ON and OFF switching to happen with smooth PWM fades instead of with abrupt "instant ON" and "instant OFF" changes. I need to have a 1.5 seconds PWM fade-in of the LED from 0% to 100% as soon as the sensor gets activated; and then a 3.5 seconds fade-out as soon as the sensor stops sensing something nearby. As long as the sensor is activated, the LED needs to remain at full brightness. So, simply put: I need the LED to dim smoothly between the sensor's state-changes, instead of changing instantly in an abrupt manner.

  • Look at the Fade example sketch under Examples/Basics. – Dean Franks Dec 22 '17 at 5:07
  • But i am not getting how to synchronize it with the sensor,, i want that as the sensor remains high the LED should remain high Fade in and vice versa – prasang sethi Dec 22 '17 at 5:10
  • In the loop function, check the value of the sensor. Based on that value set a goal for the led brightness of 0 or 255. Maintain another variable for the current brightness, if the current brightness is not equal to the goal brightness, move it a little closer and do an analogWrite. Put a delay at the bottom of the loop to make the fade transition more gradual (delay = time to go from 0 to 100 in milliseconds divided by 256). The PWM will be 0..255 which corresponds to 0..100%. – Dean Franks Dec 22 '17 at 5:20
2

This is the typical problem which calls for a finite state machine. You create a “state” variable to keep track of the LED state, which can be OFF, FADING_IN, ON or FADING_OUT. You also need another variable to remember when you started the fade-in or the fade-out. I would start the program some declarations like the following:

const uint8_t  LED_PIN       = 3;
const uint32_t FADE_IN_TIME  = 1500;
const uint32_t FADE_OUT_TIME = 3500;

static enum { OFF, FADING_IN, ON, FADING_OUT } led_state;
static uint32_t fade_start;

Now that you know the LED state, you use it to condition the LED handling on the current state. For example, the brightness at any given time can be computed as:

/* Compute the LED brightness after the given fade time */
static uint8_t led_brightness(uint32_t fade_time)
{
    int mapped;
    switch (led_state) {
        case FADING_IN:
            mapped = map(fade_time, 0, FADE_IN_TIME, 0, 255);
            return constrain(mapped, 0, 255);
        case FADING_OUT:
            mapped = map(fade_time, 0, FADE_OUT_TIME, 255, 0);
            return constrain(mapped, 0, 255);
        case ON:
            return 255;
        default:
            return 0;
    }
}

where fade_time would be millis() - fade_start. Note the use of the standard map() function to generate a linear ramp, and constrain() to avoid overflowing the range 0 – 255.

Now, switching the LED on or off is just a matter of setting the correct state... and updating fade_start as necessary:

/* Set the LED pin to HIGH or LOW, through fading. */
void ledWrite(uint8_t value)
{
    uint32_t now = millis();
    if (value == HIGH) {
        if (led_state == OFF) {
            fade_start = now;
        }
        else if (led_state == FADING_OUT) {
            fade_start = now - map(now - fade_start,
                    0, FADE_OUT_TIME,
                    FADE_IN_TIME, 0);
        }
        if (led_state != ON)
            led_state = FADING_IN;
    }
    else {
        if (led_state == ON) {
            fade_start = now;
        }
        else if (led_state == FADING_IN) {
            fade_start = now - map(now - fade_start,
                    0, FADE_IN_TIME,
                    FADE_OUT_TIME, 0);
        }
        if (led_state != OFF)
            led_state = FADING_OUT;
    }
}

A few things worth noting:

  • trying to switch the LED on has no effect if it's already on or fading in, and trying to switch it off has no effect if it's either off or fading out
  • if you switch it on while it's fading out, it will move to the state FADING_IN, and the fade_start time will be set to a value that ensures continuity of the brightness; same thing when switching from FADING_IN to FADING_OUT.

There is one more thing to do. Your program should periodically update the LED state, not only to update its brightness, but also to enforce the transitions FADING_INON and FADING_OUTOFF when needed:

/* This should be called periodically to update the LED. */
void update_led()
{
    uint32_t fade_time = millis() - fade_start;
    if (led_state == FADING_IN && fade_time >= FADE_IN_TIME)
        led_state = ON;
    else if (led_state == FADING_OUT && fade_time >= FADE_OUT_TIME)
        led_state = OFF;
    analogWrite(LED_PIN, led_brightness(fade_time));
}

With all this in place, you can write the main program just as you did with no fading, only with the extra call to update_led() on every loop iteration:

void setup()
{
    // Initialize the sensor.
    sensor.begin();
}

void loop()
{
    // Set the LED as per the sensor reading.
    if (sensor.detects_object())
        ledWrite(HIGH);
    else
        ledWrite(LOW);

    // Update the LED brightness on every loop iteration.
    update_led();
}

Oh, and beware not to do anything blocking in loop() (e.g., no calls to delay()). Otherwise the LED brightness would be “jumpy”.

| improve this answer | |
2

Do analogRead(sensor) and check what range of values you are getting. Arduino has 10 bit adc which means you can get 0-1023 in readings. However the sensor might not go complete LOW (0) or complete HIGH (1023). So just measure what's the range you are getting. Assume the range is 125 - 980.

PWM on arduino - This one is 8 bit, which means you can write 0-255. 0 means LED is OFF and 255 means LED is fully ON. Now you need to map 125-980 to 0-255 (as far as I can understand from your comments about synchronizing it with the sensor).

Here is what your code will look like:

/* Map an analog value (125-980) to 8 bits (0 to 255) */


    void loop()
    {
      int val = analogRead(0); //sensor attached to A0
      val = map(val, 125, 980, 0, 255);
      analogWrite(9, val); //LED attached to D9
    }
| improve this answer | |
  • Thank you very much for your support this is what i tested and its working fine – prasang sethi Dec 22 '17 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.