This is my first attempt at working with an ESP32-C3, a WS2812 led strip (12 LEDs), and an LD2410C mmWave sensor.
Problem statement:
- By detecting human presence near a sink, which is far from the water heater, I can momentarily turn on a small hot-water recirculation pump. Indicate the return water temperature from cold (blue) to hot (red) near the sink.
Plan:
- Node 1 near the sink, detects human presence and controls WS2812 LED strip.
- Node 2 near the water heater, controls the recirculation pump.
Status:
- Presence detection is working fine, so I’m not focused on that right now.
- My problem is I can’t seem to control the LED strip reliably, yet the ‘out of the box’ demos seem to work fine.
I have a lights | effects section in my yaml. Getting the demo ‘effects’ to work was about as easy as copy/paste. I couldn’t find a cold to hot fader in pure yaml, so I’ve been trying to create a lambda function to do what I need.
I created 3 lambda functions to use each to try to learn how to make it work. I can only say, “they sometimes work” and sometimes they don’t - and I haven’t figured out why.
What I observe:
- effects: random, strobe, addressable_rainbow, addressable_scan, addressable_twinkle and addressable_color_wipe all seem to work fine.
- one of my 3 lambda attempts works pretty reliably, and the other two “occasionally” work, but not reliably.
- I also get a bit of flicker when my lambda’s are running.
yaml
light:
- platform: status_led
name: ESP32C_Status
pin:
number: GPIO8
inverted: True
internal: False
restore_mode: ALWAYS_OFF
- platform: neopixelbus
id: temperature_led
name: "LED Strip"
type: GRBW
variant: WS2812
pin: GPIO5
num_leds: 12
effects:
- random:
- strobe:
- addressable_rainbow:
- addressable_scan:
- addressable_twinkle:
- addressable_color_wipe:
name: "Color Wipe"
add_led_interval: 0.1s
colors:
- red: 100%
green: 0%
blue: 0%
white: 0%
num_leds: 12
- red: 0%
green: 100%
blue: 0%
white: 0%
num_leds: 12
- red: 0%
green: 0%
blue: 100%
white: 0%
num_leds: 12
- lambda:
# This one works, including picking up the intensity from the web slider
# The logi function reports
# [16:06:42][I][rgbw:300]: SEQU: 0.00,0.00,0.25,0.00, 0.67
# [16:06:43][I][rgbw:300]: SEQU: 0.00,0.00,0.00,0.25, 0.67
# [16:06:44][I][rgbw:300]: SEQU: 0.25,0.25,0.25,0.00, 0.67
# [16:06:45][I][rgbw:300]: SEQU: 0.25,0.00,0.00,0.00, 0.67
# [16:06:46][I][rgbw:300]: SEQU: 0.00,0.25,0.00,0.00, 0.67
# [16:06:47][I][rgbw:300]: SEQU: 0.00,0.00,0.25,0.00, 0.67
# [16:06:48][I][rgbw:300]: SEQU: 0.00,0.00,0.00,0.25, 0.67
name: Custom - RGBW Sequence
update_interval: 1s
lambda: |-
static int state = 0;
auto br = id(intensity_channel).state/100;
float r,g,b,w;
if (state == 0) {
r = 0.25; g = 0.25; b = 0.25; w = 0.0;
} else if (state == 1) {
r = 0.25; g = 0.0; b = 0.0; w = 0.0;
} else if (state == 2) {
r = 0.0; g = 0.25; b = 0.0; w = 0.0;
} else if (state == 3) {
r = 0.0; g = 0.0; b = 0.25; w = 0.0;
} else {
r = 0.0; g = 0.0; b = 0.0; w = 0.25;
}
ESP_LOGI("rgbw", "SEQU: %3.2f,%3.2f,%3.2f,%3.2f, %3.2f", r,g,b,w, br);
auto call = id(temperature_led).turn_on();
call.set_transition_length(500);
call.set_rgbw(r,g,b,w);
call.set_color_brightness(br);
call.perform();
state += 1;
if (state == 5)
state = 0;
- lambda:
# This one does not work. The sliders, even the intensity are picked up
# BUT the led strip usually does not update (and sometimes it does).
#
# The logi function reports
# [16:07:07][I][rgbw:300]: SEQU: 0.00,0.00,0.25,0.00, 0.67
# [16:07:08][I][rgbw:300]: SEQU: 0.00,0.00,0.00,0.25, 0.67
# [16:07:09][I][rgbw:300]: SEQU: 0.25,0.25,0.25,0.00, 0.67
# [16:07:10][I][rgbw:300]: SEQU: 0.25,0.00,0.00,0.00, 0.67
# [16:07:11][I][rgbw:300]: SEQU: 0.00,0.25,0.00,0.00, 0.67
# [16:07:12][I][rgbw:300]: SEQU: 0.00,0.00,0.25,0.00, 0.67
# [16:07:13][I][rgbw:300]: SEQU: 0.00,0.00,0.00,0.25, 0.67
# [16:07:14][I][rgbw:300]: SEQU: 0.25,0.25,0.25,0.00, 0.67
name: Custom - RGBW
update_interval: 0.5s
lambda: |-
float br = id(intensity_channel).state/100;
float r = id(red_channel).state/100;
float g = id(green_channel).state/100;
float b = id(blue_channel).state/100;
float w = id(white_channel).state/100;
ESP_LOGI("rgbw", "RGBW: %3.2f,%3.2f,%3.2f,%3.2f, %3.2f", r,g,b,w, br);
auto call = id(temperature_led).turn_on();
call.set_rgbw(r,g,b,w);
call.set_color_brightness(br);
call.perform();
- lambda:
# This one does not work. The sliders, even the intensity, are picked up
# BUT the led strip usually does not update (and sometimes it does).
#
# The logi function reports
# [16:11:03][I][temp:346]: Temp: 1.00,0.00,0.00,0.00, 0.87, 130.0°F
# [16:11:04][I][temp:346]: Temp: 1.00,0.29,0.00,0.00, 0.87, 120.0°F
# [16:11:04][I][temp:346]: Temp: 1.00,0.71,0.00,0.00, 0.87, 105.0°F
# [16:11:05][I][temp:346]: Temp: 0.60,0.60,0.40,0.00, 0.87, 81.0°F
# [16:11:05][I][temp:346]: Temp: 0.60,0.60,0.40,0.00, 0.87, 81.0°F
# [16:11:06][I][temp:346]: Temp: 0.26,0.26,0.74,0.00, 0.87, 69.0°F
# [16:11:06][I][temp:346]: Temp: 0.26,0.26,0.74,0.00, 0.87, 69.0°F
name: Custom - Temp
update_interval: 0.5s
lambda: |-
float temp_f = id(water_temp).state;
float br = id(intensity_channel).state / 100.0f;
const float tCold = 60.0;
const float tWarm = 95.0;
const float tHot = 130.0;
const float w = 0.0f; // white is off
if (temp_f < tCold) temp_f = tCold;
if (temp_f > tHot) temp_f = tHot;
float r, g, b;
if (temp_f <= tWarm) {
r = (1.0f * (temp_f - tCold)) / (tWarm - tCold);
g = (1.0f * (temp_f - tCold)) / (tWarm - tCold);
b = 1.0f - ((1.0f * (temp_f - tCold)) / (tWarm - tCold));
} else {
r = 1.0f;
g = 1.0f - (temp_f - tWarm) / (tHot - tWarm);
b = 0.0f;
}
ESP_LOGI("temp", "Temp: %3.2f,%3.2f,%3.2f,%3.2f, %3.2f, %3.1f°F", r,g,b,w, br, temp_f);
auto call = id(temperature_led).turn_on();
call.set_rgbw(r,g,b,w);
call.set_color_brightness(br);
call.perform();
number:
- platform: template
name: A- Water Temperature
id: water_temp
optimistic: true
mode: slider
min_value: 60
max_value: 140
step: 1
- platform: template
name: A- Color Red
id: red_channel
optimistic: true
mode: slider
min_value: 0
max_value: 100
step: 1
- platform: template
name: A- Color Green
id: green_channel
optimistic: true
mode: slider
min_value: 0
max_value: 100
step: 1
- platform: template
name: A- Color Blue
id: blue_channel
optimistic: true
mode: slider
min_value: 0
max_value: 100
step: 1
- platform: template
name: A- Color A-Intensity
id: intensity_channel
optimistic: true
mode: slider
min_value: 0
max_value: 100
step: 1
- platform: template
name: A- Color White
id: white_channel
optimistic: true
mode: slider
min_value: 0
max_value: 100
step: 1
Bonus item - I’ve seen some projects with a color wheel, but I haven’t found enough examples and code to duplicate that - if you can point me to a project.