Toggle sequentially between four dim levels with a single contact sensor?

I'd like to use a single Z-wave contact sensor as a pushbutton to toggle a dimmer through four dimming levels: 100%, 50%, 25%, Off, for my under-counter lights. The hardware is no problem. What is HE's easiest built-in app and structure to accomplish this task with? Rule machine? Room Lighting? Basic Rules? Thank you!

I use rule machine to toggle through various color temperatures. It is a similar concept. You would have something with less IF/Else IF statements.

Basically, I use a local to rule variable (in this case "intColorTemp") to hold the current color temp, and based on what it is now will determine which step it takes in the ladder. The last IF conditional causes it to only work if the light is off because I use a different button to toggle on/off. If you want to turn it on with the same button, then remove the if condition, replace the Color Temp command with your DIM command (have it dim to the variable value), and remove the End If in that block

Ladder Color Temp Logic

(NOTE: Most dimmers do not report 100. They usually top out at 99. But, you can still send commands to set to 100)
Variable should be initialized with a starting value. After that, it updates from the conditionals in the rule.
I think you can do the same in the button controller app to. But, I have had this set up in legacy RM for a very long time and just never updated it to RM or Button controller.

For you, it would likely be:
If Variable < 25 or >=99 set
set variable to 25
Else if variable >= 25 AND < 50 then
set variable to 50
Else if variable >=50 AND <75 then
set variable to 75
Else if variable >= 75 <99 then
set variable to 100
End If
DIM: Name of light:variable

Thank you very much! Looks like just the solution for my project. I appreciate your time in answering.

If you add a 75% step you can do it in three lines.

Edit: Or steps of 33 (99, 66, 33, 0). These aren't your exact values but might be close enough.

1 Like

Just FYI, half your conditions here are unnecessary. The nature of an ELSE IF is that the previous conditions were not true, so if you already have a condition that var < X OR var > Y, you can reliably assume that var is between X and Y in all remaining branches.

So you could just do:

  • IF var < 2300 OR var >= 4000 (out-of-bounds case)
  • ELSE IF var < 2700 (2300-2700)
  • ELSE IF var < 3000 (2700-3000)
  • ELSE IF var < 3350 (3000-3350)
  • ELSE IF var < 3700 (3350-3700)
  • ELSE (3700-4000)
1 Like

So, a Var of 1500 meets all the conditions above. So, yes, you need an upper bound for each set of values. I had tried leaving them out before and it did not evaluate properly, always setting to the lowest.

It does, but only the first branch will execute. That's the difference between ELSE IF and a series of distinct IF statements. If you had each as its own IF/END-IF block, you would need the other conditions.

1 Like

It didn't work that way when I first wrote it. That is why I added the upper bounds on each condition.

There's a whole lot of talk here about variables, and that's really not the right way to do this. If the brightness or color temp or whatever you're controlling with said variable is changed outside of this rule, the rule breaks down.

Let's say you're at 50% brightness and you expect the next press to take it to 75%. Now let's assume someone adjusted the brightness with HomeKit, so while the light is at 50%, but 'myVar' is still at 0 because the last time it was adjusted via rule was a press that took the light from 100% to 0%.

So you press your button and the light goes from 50% to 25% rather than from 50% to 75% as you'd expect.

Instead just base the if/else off the current state of the light itself.

if light level < 25, set it to 25.
if light level >= 25 and < 50, set it to 50
if light level >= 50 and < 75, set it to 75
if light level >= 75, set it to 100

That way you don't end up with a situation where your variable is out of sync with what brightness the light is currently at.

Edit: I suppose you could start your rule by getting the brightness of the light and setting your variable to that level... but that's just extra steps for no reason.


But I'd suggest doing something like this. The ELSE-IF is needed depending on your lights. Some lights will set their level to 0 AND turn off when you turn them off/set the level to 0. My ZigBee bulbs I tested this with do not. If they're at 100 and you do "set level = 0", they don't actually set the level to 0. It stays at 100 but the switch turns off. Other lights I have will do both, set the level to 0 and turn the switch off. The ELSE-IF here will catch ones that don't update the level when turning off.

1 Like

There is nothing wrong with using variables no matter how bold you want to make the text. The same can be said of nested if statements or multiple else ifs. The logic becomes harder to follow and debug.

Case in point: Your example will not give the desired results. If the light is currently set in the 0-98 range the rule will set it to 50% (assuming 50 is what’s under the “edit action” tag).

If the light is set to 99 or 100 it will set it to 25% if the switch is off otherwise it will set it to 0. These two values will only be used if the light is 99 or 100 since every other value satisfies the first conditional.

So once it is set to 50% the rule will never change it to anything else.

That wasn’t the question asked. If that were a concern then the code would be different. Each input source could set the variable appropriately or use the current value like you suggested.

As an example I use two variables for color temp and level. Every light in my house references them and the values are updated every minute. As I move from room to room the lights are consistent.

Then if I want to go into a special condition the lights don’t use those variables. For example, in theater mode the lights in my living room are colored and much dimmer.

This is also not what the original poster asked so I didn’t go into that much detail with the solution offered.

That’s enough off topic for this post. :wink:

1 Like

Didn't notice the silly edit action thing on the screenshot. But you can see that it's "Adjust", not "Set" on that action. That action is "Adjust +25". So if it's anything other than 99 or 100 (which is "full" brightness, or close enough, depending on whether that specific light goes to 99 or 100), it will adjust it by +25. If it's "off", it sets it to 25. Otherwise it's 99+ so it turns it off.

Unless every room in your house is the same size, shape, wall color, and lit with the same lamps, with the same bulbs, and same shades, that's not going to be the case. "50% brightness and 3000K" in one room of my house looks VERY different than the same settings in another.

1 Like

Huh, I guess I don’t know my own house. :man_shrugging:t3:

1 Like

Thanks all! Here is what I wound up doing - works great and my wife is very happy:

If I’m following that logic correctly it won’t do anything if the dimmer is set between 1 and 9.

Edit: This should clean that up:

Right, If I change that 10 to a 0, it'll always work. I'll fix that. My use of a range with else statements isn't minimal, but I hadn't done any work with Rule Machine in a year or so and struggled with the interface a bit.

1 Like

Yes, that should fix it. I was just offering another take on the logic. Neither approach is wrong. Sometimes it’s good to see a different view. (I still prefer my original post :wink: but then your levels would be 0/33/66/99 and while close it may not be close enough to what you want.)

Yes, eyeballs have a logarithmic response to illumination, so I really wanted 0/25/50/100.

1 Like

Just for reference, this is what I do with a couple lamps in webCoRE. One tap turns it off or on to the last level. Two taps, low. Three, medium. Four, high. WebCoRE has a switch case function. Each case number corresponds to a number of button presses. I set the levels and devices in the variables at the top. That way, I can use this same piston for different lamps and adjust the levels accordingly.

1 Like

Fair enough.

On a related note LEDs typically don’t act linearly either. I have a coat with lights and there isn’t much difference between 50 and 100% in brightness but the power savings is quite large. I typically run it at 10-20% brightness and it will last all night on a charge.