On_Boot interfering with Sensor:On_Value_Range?

The sensor doesnt need a “warm up” time. That 1-30min/30second turn on time is its pre-configured discontinuous mode and that 30s is how long it turns on each minute. The sensor itself is capable of taking a reading every 1 second.

What type of light are you using here? How is it configured in esphome?

Single neopixel.

#neopixel config
light:
  - platform: neopixelbus
    type: GRB
    variant: WS2811
    pin: GPIO15
    num_leds: 1
    name: "StatusLED"
    id: status_light

I’m able to address & control it directly through dashboard. It generally changes properly when crossing the on_value_range threshholds, but the reverting back to blue is the issue here.

My overall use-case is this:

I live in Chiang Mai, Thailand and the air gets pretty terrible around here this time of year. We’re with a childrens’ home foundation, and I’m trying to come up with cost-effective solutions for our kids (and at-risk neighbors) to have air filtration and the means of measuring. I’ve already got a pretty good filtration system designed, just trying to get the indicator piece.

I do have a small display too, but trying to use the dummy-light as a 100% clear & notable indication of when they should have the filtration running. Note that when these go out, they won’t have wi-fi so I won’t have means of monitoring remotely.

I’m not sure about this particular model but for sure some similar ones need some time for the fan to warm up.

time for the “fan to warm up”? Like I said earlier, nothing needs to warm up and the fan especially doesn’t need to warm up if you can even make sense of that. The fan does 2 things, the fan passes air/particulates across the laser when it takes a measurement and when it’s in default mode, taking one measurement per second, the fan also helps to cool the device. Instead of pointing to some random dude in a forum who is wrong too, all you or anyone else should have done is just read the data sheet and then all this misinformation would stop being spread all over.

Everyone keeps quoting this 30 seconds as “warm up time” or this is a new one, “the data needs 30 seconds to stabilize” The only thing needing stabilized is that person’s medication.

All BS and nonsense because no one can do 5 minutes of reading. If anyone had done the reading they’d know the 30 seconds was just an example they use in the data sheet.

Not sure who hurt you, or why you’re so upset about this. Again, I’m new to all this…

But this is from the manufacturer’s own guide regarding their laser sensor protocol.


source: NovaFitness Laser Dust Sensor Control Protocol V1.3

My understanding is it’s fine to work without a [trigger warning] “warmup period” if you are continuously reading. Once you stop polling, the fan and laser stop and will optimally need a [trigger warning] “warmup time” to provide stable data.

Though we’re off-topic from the original question of the optimal way of changing LED color based on current value (range) even if it didn’t move outside. I’m thinking maybe just a nested if-then lambda. I’ll start looking at that (while still confused about the blue LED)

1 Like

The other data sheet doesn’t say that. Why they’re different, i’m not sure.

try this.

sensor:
  - platform: sds011
    update_interval: 2min
    pm_2_5:
      name: "PM 2.5µm"
      id: "pm25"
      filters:
        offset: 1 #this was to test issues coming from a 0 value
      on_value_range:
        - above: 0.0
          below: 11.9
          then:
            #green
            - light.control:
                id: status_light
                brightness: 50%
                red: 0.0
                green: 1.0
                blue: 0.0
        - above: 12
          below: 34.9
          then:
            #yellow
            - light.control:
                id: status_light
                brightness: 50%
                red: 1.0
                green: 1.0
                blue: 0.0
        - above: 35
          below: 54.9
          then:
            #orange
            - light.control:
                id: status_light
                brightness: 50%
                red: 1.0
                green: 0.65
                blue: 0.0      

The difference in publications doesn’t surprise me. Could’ve been different engineers, or one is just standard (safest) practice, but not necessary in all cases.

try this.

I see, so maybe do “control” changes instead of just turning it on each time. So power it on during boot, then just push changes on range change. I’ll give it a shot, thanks.

it’s Blue because you’re setting it to Blue on_boot while at the same time it’s restoring the last sensor value/color that was saved before reboot. You’re basically telling it to go Left and Right at the same time.

remove that on_boot section… Whatever the last state/color it was on will be the color set on_boot.

light.control Action
This Action is a generic call to change the state of a light - it is essentially just a combination of the turn_on and turn_off calls.

it basically does a on/off or resets the light each time the color values are changed.

How is the on_boot command not getting overwritten by the On_Value_Range?

If the On_Boot is called, that means the system restarted, right?

And if so, it should have forgotten the sensor values, correct? Which means any value read in the sensor should trigger the on_value_range like it crossed for the first time?

I would ask if maybe it doesn’t call the execution if it boots within the range, but it will go to Green first, then fallback.

…while at the same time it’s restoring the last sensor value/color that was saved before reboot…

Is it actually restoring the sensor value? If so, isn’t there a way to just to disable that and then the problem would be solved as it would trigger the on_value_range call every time

I’m not sure why exactly but these little bugs/quirks with the light component have been around for a while.

I think it has something to do with this.

" All percentage options accept values in the range 0% to 100% or 0.0 to 1.0 , and default to not changing the current value (which might be the value from before the light was last turned off). To reset values, explicitly set them to zero."

That makes sense in my head if I’m strictly running procedures based on the light’s state. But I can’t wrap my head around why it wouldn’t go back to green when it’s running based on the on_value_range under a sensor.

This is the logic in my head.

  1. Boot-up. On_boot tells the light to turn blue (all sensors states are null until called)
  2. Sensor value is returned (let’s assume pm25 = 2, so should be in green range).
  3. On_value_range is triggered for the first time, light is changed to green.
  4. Sensor returns again and pm25 = 5. No change since still in range.
  5. REBOOT
  6. Due to quirk, light value is retained as “green” but sensors are cleared and we return to step 1. (on_boot makes light turns blue, then should call on_value_range again when populated for first time).

The only thing that makes sense is that the sensor state is somehow being retained? So when it goes back it’s not seeing as a change. but everything I’ve read said it should clear. If that’s not the case, is there a way to tell it just not to save the state of the sensor?

They’re not Null values. Your on_boot action is happening at the same time the sensors are initialized, not before.

Interesting… So if that’s the case, moving the priority up (not down) should help as it would call before it initializes the sensors. I’ve tried between 0-500, but maybe I need to go 700 (appears as though sensors come online at 600)

I’ll give that a shot next. Otherwise, I think it might be fixable with In_Range conditions versus the on_value_range call. I really want to keep the on_boot as a just-in-case-i-want-visual-troubleshooting-lights-later-on deal.

The link I provided quotes the data sheet for that product.

“Stable data should be got at least 30 seconds after the sensor wakeup from the sleep mode because of the fan’s performance.”

I have also personally measured and observed the measurements change rapidly during the warm up period for that particular device, which you can see in this post.

Again, not claiming it applies to this device, but it’s a thing for similar devices (edit: and I see in the chat it appears to now be confirmed for this device).

Some ESPHOME components have options for restoring last value on boot (E.G restore_value: , restore_mode:)

The sensor you’re working with doesn’t appear to have restore options (from what I can see). I suspect it doesn’t restore a value but don’t know how that works.

If you haven’t already, it’s worth looking over restore mode of the light. Possibly on_boot some restoration is occurring. I’ve seen reports on other chats of restore modes not quite working as expected and momentarily causing unexpected states through boot (mainly seen for switches iirc).

restore_mode:

This is looking slick BTW. Looks like you’re making really good progress for such a short time using HA and ESPHome. Nice one.

P.S in case you haven’t found it yet, you can also dig into the API reference and source code if you need to.

https://esphome.io/api/classesphome_1_1sds011_1_1_s_d_s011_component
https://esphome.io/api/sds011_8cpp_source

There’s also the Debug component, which can report reset reason which could be handy if you are getting unplanned reboots, but you already mentioned adding features is problematic…

1 Like
on_value: 
  then:
      - lambda:
          if (isnan(id(pm25).state {id(blue).execute();}

What about instead of turning on blue light on boot you run a acript called blue when sensor gives a value of nan for being unavailable yet . You will have to write script to turn on the light to blue. You may have to adjust the indentation of my code as typed on phone

Hmm, that could work. The only thing I’m thinking is that it seems like the sensor gives NaN while updating the reading already. If I change during the read (State: Nan), when it returns a value that’s in the same range as before, it probably won’t run the on_value_range script again if it didn’t cross a different threshhold, so it’d be stuck on blue, right?

I did try (and failed) pushing a .publish_state(NaN) during the On_Boot to make sure it cleared, but I don’t think it sees a NaN as a valid value for consideration on whether it’s crossed ranges. I’d almost have to push a dummy value outside the range (i.e. -5), but that would mess with my history.

There’s also the option to filter NaNs if you need.

filter_out: nan

But sounds like you’d probably need to use that conditionally.

SOLVED!

I did a mixture of recommendations, but ultimately decided to do all the LED calls in scripts (format: led_), then abandon sensor:on_value_range in favor of a lambda under on_value. So, it looks like this…

On_boot:

on_boot:
    priority: 500
    then:
      #turn on blue light
      - script.execute: led_blue

Sensor:

sensor:
  - platform: sds011
    update_interval: 1min
    pm_2_5:
      name: "PM 2.5µm"
      id: "pm25"
      force_update: true
      on_value:
        then:
          - lambda: 
              if (isnan(id(pm25).state)) {id(led_blue).execute();}
              else if (id(pm25).state <= 12) {id(led_green).execute();}
              else if (id(pm25).state <= 35.4) {id(led_yellow).execute();}
              else if (id(pm25).state <= 55.4) {id(led_orange).execute();}
              else if (id(pm25).state <= 150.5) {id(led_red).execute();}
              else if (id(pm25).state <= 9999) {id(led_purple).execute();}

I like the additional reset to blue when it’s reading. For some reason if the sensor gets stuck and pulls in a NaN, it won’t give a false indication on the LED by staying from a previous state.

1 Like

Finished product w/ 3D-printed case I designed.
image

2 Likes