Smoothly dim the light on the move sensor release

Hello Home Assistant and ESPHome comunity.

I am working on this project for two weeks now and cannot figure out how to dim the LEDs on exit of (on_release) of the move sensor.

Can I kindly ask you guys for a little bit help please?

Details

What I want to achieve is to:
Going to the room, and:

  1. If there is a day or the ceiling light is on - do nothing.
  2. If there is dark, turn on LEDs
  3. After 10 seconds check is there any move in the room:
    if yes, keep light on
    if not, slowly dim the LEDs down.

I already checked “id(output_component1).set_level(0.7);” in the “on_release” and it is dimming the light. But it is doing it from 1 to 0.7. What I want to achieve is to slowly dim it to the 0.0 value. The code in the “on_release” section is completely messed up. Not sure how to repair it.

  • Environment
    – Heart: ESP8266
    – PIR (Move) Sensor: HC-SR501
    – Light Sensor: LM393
    – PWM 12V

  • The code

esphome:
  name: esp773ba
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "XXXX"
  password: "XXXX"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "XXXX"
    password: "XXXX"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

globals:
  - id: glob_var
    type: int
    restore_value: no
    initial_value: '100'

light:
  - platform: monochromatic
    name: "PWM Light"
    output: output_component1
    id: output_component1_light
output:
  - platform: esp8266_pwm
    pin: 4
    id: output_component1
    inverted: False
binary_sensor:
  - platform: gpio
    pin: 2
    name: "Light Sensor"
    device_class: light
    id: light_detect
  - platform: gpio
    pin: 1
    name: "Motion Sensor"
    device_class: motion
    id: move
    on_press:
      then:
        - lambda: !lambda |-
            if (id(light_detect).state) {
              id(output_component1).turn_on();
            } else {
              id(output_component1).turn_off();
            }
    on_release:
      - while:
          condition:
            lambda: 'id(glob_var) != 0;'
          then:
            - light.dim_relative:
                id: output_component1_light
                relative_brightness: 5%
                transition_length: 0.1s
            - lambda: 'id(glob_var) -= 1;'
            - delay: 0.1s

Since there is no answer, maybe I will share complete and working project but written for Arduino. So feel free to copy.

//Arduino Pro Mini
//ATmega328P (5V, 16MHz)
#define LAMP 5     // choose the pin for the RELAY
#define PIR 3      // choose the input pin (for PIR sensor)    
int ledPin = 6;    // LED connected to digital pin 9
int fadestatus = 0;
int fadevalue = 0;
void setup(){
  Serial.begin(9600);
  pinMode(LAMP, OUTPUT);  // declare lamp as output
  pinMode(PIR, INPUT);    // declare sensor as input  
  }                                                                                                                        
void loop(){
  int value_ldr = analogRead(A3);   // read LDR value
  int value_pir = digitalRead(PIR); // read input value

if(300 > value_ldr && fadestatus == 1){
  fadevalue = 0;
  analogWrite(ledPin, fadevalue);
  }
if((300 < value_ldr) && (value_pir == HIGH)){
  if(fadestatus < 2){
    for (int fadeValue = fadevalue; fadeValue <= 220; fadeValue += 5){
      fadevalue = fadeValue;
      analogWrite(ledPin, fadeValue);
      delay(5);  // wait for 5 milliseconds to see the dimming effect
      fadestatus = fadeValue;
      }
    }
  delay(10000);  // Start dimming after...
  }
else {
  if (fadestatus > 1){
    fadestatus = 1;
    for (int fadeValue = fadevalue; fadeValue >= 0; fadeValue -= 1){
      fadevalue = fadeValue;
      int value_pir = digitalRead(PIR); // read input value
      int value_ldr = analogRead(A3);   // read LDR value  
      if (fadeValue == 160){ 
        fadeValue = 1;
        }
      if (300 > value_ldr ){
        Serial.println(value_ldr);
        break;
        }
      if (value_pir == HIGH){
        break;
        }
      Serial.println(value_pir);
      Serial.println(fadevalue);
      analogWrite(ledPin,fadeValue);
      delay(90);
      }
    }  
   }
  }

Regarding ESPHome, unfortunately I am new in the ESPHome programming and still have some problems with creating the loops and values.

OK, i figured this out. Probably it can be done much nicer but I haven’t got so much experience yet. So here you go:

esphome:
  name: esp773ba
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "XXXX"
  password: "XXXX"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "XXXX"
    password: "XXXX"

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

globals:
  - id: dimme
    type: float
    restore_value: no
    initial_value: '0.99'
light:
  - platform: monochromatic
    name: "PWM Light"
    output: output_component1
    id: output_component1_light
    default_transition_length: 20ms
output:
  - platform: esp8266_pwm
    pin: 4
    id: output_component1
    inverted: False
binary_sensor:
  - platform: gpio
    pin: 2
    name: "Light Sensor"
    device_class: light
    id: light_detect
  - platform: gpio
    pin: 1
    name: "Motion Sensor"
    device_class: motion
    id: move
  - platform: template
    name: "WC motion delayed"
    lambda: |-
      return id(move).state;
    filters:
      - delayed_off: 100ms
    on_press:
      then:
        - lambda: !lambda |-
            static int coun = 0;
            while (coun < 5) {
              if (id(light_detect).state) {
                id(output_component1).turn_on();
		delay(1000);
              }
            }
            coun = 0;
    on_release:
      then:
        - lambda: !lambda |-
            static int coun = 0;
            static float dimme = 0.99;
            if (id(light_detect).state) {
              while (coun < 20) {
                id(output_component1).set_level(dimme);
                delay(100);
                coun += 1;
                dimme -= 0.02;              
              }
            }
            id(output_component1).turn_off();
            coun = 0;
            dimme = 0.99;

1 Like

Slightly OT, but have you tested that sr501 with the esp yet? In my experience, that combo will false trigger on more than half of the devices I built (even with ridiculous attention to power filtering). Sometimes they can work, but wanted to mention before you go too far down the rabbit hole without testing it. The sr501 is notoriously sensitive to wifi noise… am312 do much better near wifi noise.

Hello truglodite,

yes, I have tested. But thanks for asking.
In fact i haven’t have any false positives on this device. What I did (maybe wrong, but it’s working) is to connect VCC on the 501 to VV on the ESP board to get 5V. I have read, that it is not stable with 3V.

I have different problem though. It is retriggering time which I described here.
I really starting to think, to test it on RCWL-0516. I even ordered one and waiting for a delivery. Once I will get it and test it, I will give you the note in this topic or the other one (from the above link).

Yeah they are a bit slow. Am312 hold high about 2.5seconds (not adjustable).

I also use rcwl’s… awesome sensors as long as triggering through thin walls isn’t an issue. They also need decent separation from the esp (few inches), and any metallic surfaces. They work much better if you power them at about 11V (mt3608 DC-DC converter is good, and the rcwl still puts out a 3v3 signal). There is a lot of writing on this subject on github. Rcwl’s also cycle super fast (like milliseconds), don’t care about moving shadows, and work good at high ambient temps (unlike pir). In fact I programmed my ESP’s to delay 2.5sec to reduce the network traffic (that was fast enough for me). If it helps you decide… I recently swapped all my am312’s for rcwl’s (312’s replaced 501’s… but like you said I powered them off 3v by bypassing the onboarding ldo, and they weren’t stable that way, and 5v needs a level shift). :wink:

Thanks for your advise. That are precious words for me.

What I wanted to do is to connect 0516 to the 12 volts output of my LED power supply since I will use it in my project anyway. I believe, I need to connect the positive wire to the VCC in the detector and negative to the ESP.
Tell me please when you were connecting 0516 to your board did you have immediate retriggers straight out the box or did you have to program it?

So i have just received 0516 module. Technically it works but there is the same 3 seconds delay. I even simplified the code to be sure, that I don’t have error anywhere.

@truglodite how did you managed to make it work without this delay?

Heyho,
i tried to rewrite your script to be used without so much lambdas (just for the fun) and since i am not experienced either i have no idea, wether this could work or not. But as far as i understand the docs, the following rewrite could be an option:

light:
  - platform: monochromatic
    name: "PWM Light"
    output: output_component1
    id: output_component1_light
    default_transition_length: 20ms
output:
  - platform: esp8266_pwm
    pin: 4
    id: output_component1
    inverted: False
binary_sensor:
  - platform: gpio
    pin: 2
    name: "Light Sensor"
    device_class: light
    id: light_detect
  - platform: gpio
    pin: 1
    name: "Motion Sensor"
    device_class: motion
    id: move
  - platform: template
    name: "WC motion delayed"
    lambda: |-
      return id(move).state;
    filters:
      - delayed_off: 10s
    on_press:
      - if:
          condition:
            binary_sensor.is_on: light_detect
          then:
            - light.turn_on: output_component1_light
    on_release:
      - if:
          condition:
            binary_sensor.is_on: light_detect
          then:
            - while: 
                condition:
                  - light.is_on: output_component1_light
                then:
                  - light.dim_relative:
                      id: output_component1_light
                      relative_brightness: 2%
                      transition_length: 0.1s
                  - delay: 0.1s

Would love to get some feedback since i haven’t tested anything =) It’s more about the idea…

Hello @Klops

Thanks for the reply.
Ok I have tested your code. I have to admit, that it looks much more clean than mine.

But, since sensors (light and move) are working fine (detecting), the light (LEDs) not lighting up.
I played a little bit with the relative_brightness, transition_length and delay and I cannot push the LEDs to show me the light…
I played with the “output_component1_light” previously but cannot make it run as expected. That is why I moved to output_component1.
There is one small detail more. The 0516 movement detector still running “arming” itself after 3 seconds.

For now I am going back to my dirty code, and will try to fight with that evil till the end haha

So i took another look at the code and saw several things. First off, if you do not need the exact shutoff from the motionsensor for anything else, we could remove the double definition of the sensor (“WC motion delayed”) and put the whole automation and delayed_off directly into the motion sensor.

And i think i got the whole dimming process wrong in my head, because i just took the direction from your previous code, but why not just let the light turn off with a specified transition_time instead of looping steps with relative brightness? Should be the same result i think.

Lastly i got some hiphens wrong in the conditions. So here is another example:

light:
  - platform: monochromatic
    name: "PWM Light"
    output: output_component1
    id: output_component1_light
    default_transition_length: 20ms
output:
  - platform: esp8266_pwm
    pin: 4
    id: output_component1
    inverted: False
binary_sensor:
  - platform: gpio
    pin: 2
    name: "Light Sensor"
    device_class: light
    id: light_detect
  - platform: gpio
    pin: 1
    name: "Motion Sensor"
    device_class: motion
    id: move
    filters:
      - delayed_off: 10s
    on_press:
      if:
        condition:
          binary_sensor.is_on: light_detect
        then:
          - light.turn_on: 
              id: output_component1_light
              brightness: 100%
    on_release:
      then:
        - light.turn_off:
            id: output_component1_light
            transition_length: 5s

I’m not sure wether i understand the light component parts correctly in your answer. And what do you mean by the motion sensor is “arming itself after 3 seconds”? If it fires on incorrectly, then it seems more like truglodite is on the right path about the sensor itself.

Anyways, if the other code works, then fine. Never touch a running system =)

OK, let me briefly explain what I am trying to achieve and where I see the problem (in points):

  1. Target is to create lighting solution to bedroom with the below rules/conditions:
  • when I am walking in to bedroom - the LEDs are lighting up,
  • when there is the daytime, LEDs will stay off,
  • when I am in the bedroom and LEDs are ON (there is a move), and I am switching on the ceiling light, the LEDs should go OFF ASAP,
  • when I am in the bedroom with my ceiling light ON, and switching them OFF but being on the move at the same time, the LEDs are switching ON ASAP.
  1. Issues:
  • LEDs should dim while on the OFF process (LEDs shouldn’t switch OFF quick as they has been switch ON)
  • the move sensor should be active only when there is a move - not longer (at the moment, when sensor detects move it stays ON for a 3 seconds)
    Why it is important? Because if during the move I will switch ON or OFF ceiling light I cannot push the LEDs to switch ON or OFF since I have to wait without move for 3 seconds to allow move sensor to reset (to change status to “armed”).

Thanks for the code update. And again let me tell you - it looks much more pretty thank mine, but:

  • Once I cover the light sensor I need to wait for a few seconds (more than 5 or 10 seconds - hard to say) before I will move. If I will move quicker than that time - the LEDs won’t go ON.

Update/Edit

I hashed out:

    filters:
      - delayed_off: 10s

And it seems, that it is working much nicer now. But still I have this 3 seconds delay between the move state:

[19:02:31][D][binary_sensor:036]: 'Motion Sensor': Sending state ON
[19:02:34][D][binary_sensor:036]: 'Motion Sensor': Sending state OFF

That is good.

Yeah i think the delay in the motion sensor is built into the sensor itself. I can’t remember where i read this, becaus i got my motion sensors up and runnig back in 2017. But i think to remeber having read this. Some internal debounce or so. Maybe someone can put some light on this topic.

Sounds to me like the repeat trigger from rcwl0516:

Adjustment components

On the back of the board (the side without components) are pads for 3 optional components (0805 dimensions).

Pad Function
C-TM Regulate the repeat trigger time. The default (unpopulated) time is 2s. A SMD capacitor to extend the repeat trigger time. Pin 3 of the IC emits a frequency (f), and the tigger time in seconds is given by (1/f) * 32678

This can be the reason, thank you, but the problem is, that I don’t want to extend the repeat time. I want make it shorter. orange-assistant please correct me if I am wrong, but from the text quoted and from the website you provided I cannot find any information how to make it shorter.