I have a light I want to control from ESP-Home with a rotary encoder.
The idea is if the light is off then it should do light turn on with brightness 10 ( one step).
sensor:
- platform: homeassistant
id: david_brightness
entity_id: light.davids_lampa
attribute: brightness
- platform: rotary_encoder
name: "Brightness Encoder"
id: brightness_encoder
pin_a: GPIO5
pin_b: GPIO6
internal: true
on_value:
- lambda: |-
// Calculate change from last position
int current = (int)x;
int delta = current - id(last_encoder_value);
id(last_encoder_value) = current;
// Adjust brightness (step of 10 per click)
ESP_LOGI("encoder", "David brightness %.0f", id(david_brightness).state);
int david = 0;
if (id(david_brightness).state == nan) {
david = 0;
} else {
david = (int)id(david_brightness).state;
}
ESP_LOGI("encoder", "David %d", david);
float new_brightness = david + (delta * 10);
// Clamp to valid range
if (new_brightness < 0) new_brightness = 0;
if (new_brightness > 255) new_brightness = 255;
with the above I get this:
/config/esphome/david-sang.yaml: In lambda function:
/config/esphome/david-sang.yaml:221:35: error: invalid operands of types 'float' and 'double(const char*)' to binary 'operator=='
221 | if (id(david_brightness).state == nan) {
| ~~~~~~~~~~~~~~~~~~~~~ ^~ ~~~
| | |
| float double(const char*)
*** [.pioenvs/david-sang/src/main.cpp.o] Error 1
I have also tried == NULL and if (std::isnan(id(david_brightness).state)).
What is the correct way to make the rotary encoder to send 10 as brightness when the light is off.
Using isnan results in it sending 255.
If isnan is correct way, but I’m not sure how the values go here. Where are you turning the light on ?
I think you should check if david_brightness isnan and if delta>0 then set new_brightness to 10 and turn light on.
I believe from my testing that isnan returns false and with the code I had it then read the value of Davids lampa brightness and placed that as the variable David.
I believe that then was (somehow) interpreted as 255.
I honestly have no clue how that has happened.
The current code I have now does not compile but I can change it to something where it can compile with some debug prints so that I can show you the values of the variables.
Give me a few minutes.
So this is the complete code that is not installed with a few debug prints.
sensor:
- platform: homeassistant
id: david_brightness
entity_id: light.davids_lampa
attribute: brightness
- platform: rotary_encoder
name: "Brightness Encoder"
id: brightness_encoder
pin_a: GPIO5
pin_b: GPIO6
internal: true
on_value:
- lambda: |-
HomeassistantActionRequest svc;
svc.service = StringRef("light.turn_on");
svc.data.init(2);
auto &kv1 = svc.data.emplace_back();
kv1.key = StringRef("entity_id");
kv1.value = StringRef("light.davids_lampa");
auto &kv2 = svc.data.emplace_back();
kv2.key = StringRef("brightness");
// Calculate change from last position
int current = (int)x;
int delta = current - id(last_encoder_value);
id(last_encoder_value) = current;
// Adjust brightness (step of 10 per click)
ESP_LOGI("encoder", "David brightness as float %.0f", id(david_brightness).state);
ESP_LOGI("encoder", "David brightness as string %s", id(david_brightness).state);
int david = 0;
if (std::isnan(id(david_brightness).state)) {
david = 0;
} else {
david = (int)id(david_brightness).state;
}
ESP_LOGI("encoder", "Variable david after IF %d", david);
float new_brightness = david + (delta * 10);
// Clamp to valid range
if (new_brightness < 0) new_brightness = 0;
if (new_brightness > 255) new_brightness = 255;
ESP_LOGI("encoder", "Variable david after 'clamp' %d", david);
// Update brightness
if (new_brightness != id(david_brightness).state) {
static char brightness_buffer[10];
sprintf(brightness_buffer, "%d", (int)new_brightness);
kv2.value = esphome::StringRef(brightness_buffer);
global_api_server->send_homeassistant_action(svc);
ESP_LOGI("encoder", "Brightness adjusted to %.0f", new_brightness);
}
I’m aware people does not like that method of turning on a light, but it works for now and I do not intend to update the ESP version of the code.
The light is turned off and I rotate the encoder one step to turn on, that gives:
[18:01:40][D][sensor:118]: 'Brightness Encoder' >> 35 steps
[18:01:40][I][encoder:219]: David brightness nan
[18:01:40][I][encoder:226]: David 2147483647
[18:01:40][I][encoder:242]: Brightness adjusted to 0
[18:01:42][D][sensor:118]: 'Brightness Encoder' >> 36 steps
[18:01:42][I][encoder:219]: David brightness nan
[18:01:42][I][encoder:226]: David 2147483647
[18:01:42][I][encoder:242]: Brightness adjusted to 0
And that makes me clueless… it’s not the correct debug prints.
I don’t understand this. And it doesn’t even turn on the light anymore…
It seems as if the device reboots when I use the rotary encoder.
I figured it out.
The rotary encoder value started at what it saved to the EEPROM.
When I added restore_mode: ALWAYS_ZERO then it would use 0 and compare that against the last_encoder_value which also has initial value 0.
That means it does a small step as it should.