########################################################################################## ########################################################################################## # LB01 Athom 15W RGBCCT Bulb (ESP8266) - ESPHome # # V1.0 2025-09-09 Initial Version (Tasmota pinout import) # # Based on Tasmota template in screenshot: # GPIO4 -> PWM 1 # GPIO5 -> PWM 4 # GPIO12 -> PWM 2 # GPIO13 -> PWM_i 5 (inverted) # GPIO14 -> PWM 3 # # Assumed channel roles (adjust if colors are swapped on test): # PWM1 = Red, PWM2 = Green, PWM3 = Blue, # PWM4 = Cold White, PWM5 = Warm White (inverted) ########################################################################################## ########################################################################################## ########################################################################################## # SPECIFIC DEVICE VARIABLE SUBSTITUTIONS # If NOT using a secrets file, just replace these with the passwords etc (in quotes) ########################################################################################## substitutions: # Device Naming device_name: esp-rgblampbulb2 friendly_name: "Athom LB01 15W RGBCCT Bulb" description_comment: "Athom RGBCCT bulb using Tasmota pin mapping" device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Passwords If NOT using a secrets file, just replace these with the passwords etc (in quotes) api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-rgblampbulb2_ip # Preferred warm color temperature (use K or mireds, e.g. "2700K" or "370 mireds") white_temp: "3000K" # Device Settings log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE update_interval: "60s" # general sensors update # Effect timing defaults on_time_ms: "500ms" off_time_ms: "500ms" # >>> PWM frequency for all channels (easy to adjust in one place) <<< pwm_freq: "2000 Hz" # >>> ESPHome equivalent of Tasmota DimmerRange 24,100 <<< # 0.24 = 24% minimum PWM when the light is ON. OFF still goes to 0. dimmer_min_power: "0.24" ########################################################################################## # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html ########################################################################################## # Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors ########################################################################################## packages: common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" common_api: !include file: common/api_common.yaml vars: local_api_key: "${api_key}" #common_webportal: !include # file: common/webportal_common.yaml common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" common_sntp: !include file: common/sntp_common.yaml common_general_sensors: !include file: common/sensors_common.yaml vars: local_friendly_name: "${friendly_name}" local_update_interval: "${update_interval}" ######################################################################################### # ESPHome # https://esphome.io/components/esphome.html ######################################################################################### esphome: name: ${device_name} friendly_name: ${friendly_name} comment: ${description_comment} # appears on the esphome page in HA on_boot: # Run late so it wins over everything (Wi-Fi, light init, restore, etc.) priority: -10 then: - delay: 100ms - lambda: |- // Force WHITE mode @ 60% and 3000K (333 mireds) with no fade auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::WHITE); call.set_brightness(0.60f); call.set_color_temperature(333.0f); // 3000 K call.set_transition_length(0); call.perform(); # Optional project metadata and 2MB flash map (uncomment if you confirm ESP8285 2MB) project: name: "China Athom Technology.Athom RGBCCT Bulb" version: "v1.1.4" platformio_options: board_upload.flash_size: 2MB board_upload.maximum_size: 2097152 board_build.ldscript: eagle.flash.2m.ld ######################################################################################### # ESP Platform and Framework # https://esphome.io/components/esp8266.html ######################################################################################### esp8266: board: esp8285 early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout #restore_from_flash: true # restore some values on reboot mdns: disabled: false # Disabling will make the build file smaller (and it is still available via static IP) #preferences: #flash_write_interval: 2s ######################################################################################### # ESPHome Logging Enable # https://esphome.io/components/logger.html ######################################################################################### logger: level: ${log_level} #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 ########################################################################################## # OUTPUT COMPONENT ########################################################################################## output: - platform: esp8266_pwm id: output_red # PWM1 -> GPIO4 pin: GPIO4 frequency: ${pwm_freq} min_power: 0.000499 max_power: 1 zero_means_zero: true - platform: esp8266_pwm id: output_green # PWM2 -> GPIO12 pin: GPIO12 frequency: ${pwm_freq} min_power: 0.000499 max_power: 1 zero_means_zero: true - platform: esp8266_pwm id: output_blue # PWM3 -> GPIO14 pin: GPIO14 frequency: ${pwm_freq} min_power: 0.000499 max_power: 1 zero_means_zero: true - platform: esp8266_pwm id: output_cold_white # PWM4 -> GPIO5 pin: GPIO5 frequency: ${pwm_freq} min_power: 0.01 max_power: 0.9 zero_means_zero: true - platform: esp8266_pwm id: output_warm_white # PWM5 -> GPIO13 (inverted) pin: GPIO13 frequency: ${pwm_freq} inverted: true min_power: 0.01 max_power: 0.9 zero_means_zero: true ########################################################################################## # DIAGNOSTIC BUTTONS: Force individual channels (bypass light logic) ########################################################################################## ########################################################################################## # DIAGNOSTIC BUTTONS (use light API, not raw PWMs) ########################################################################################## button: - platform: template name: "Test WW 100%" on_press: then: - light.turn_on: id: my_light brightness: 100% color_temperature: 3000 K transition_length: 0s - platform: template name: "Test CW 100%" on_press: then: - light.turn_on: id: my_light brightness: 100% color_temperature: 6000 K transition_length: 0s - platform: template name: "All OFF (light)" on_press: then: - light.turn_off: id: my_light transition_length: 0s ########################################################################################## # LIGHT COMPONENT # https://esphome.io/components/light/ ########################################################################################## light: - platform: rgbct id: my_light name: ${friendly_name} restore_mode: RESTORE_DEFAULT_OFF red: output_red green: output_green blue: output_blue white_brightness: output_cold_white # GPIO5 color_temperature: output_warm_white # GPIO13 (inverted) # Keep total output reasonable on 15W bulbs and avoid mixing RGB with WW simultaneously. color_interlock: true # Typical white temperature mapping for RGBWW cold_white_color_temperature: 6000 K warm_white_color_temperature: 3000 K # Do NOT restore last color at boot; on_boot shapes warm 60% only after power loss # restore_mode: RESTORE_DEFAULT_OFF # Optional: small gamma tweak for nicer dimming curves # gamma_correct: 2.4 # Default fade for normal changes; boot uses its own 3s transition above. default_transition_length: 1s ###################################################################################### # CALM EFFECTS # - Night Light: steady warm, ~3% brightness # - Breathe (Soft): slow, gentle brightness wave on current color # - Amber Glow: very gentle warm amber wave # - Blue Calm: subtle cool blue drift # - Warm Dim: static warm preset around 15% ###################################################################################### effects: # Night Light (steady warm ~3%) - lambda: name: "Night Light" update_interval: 2s lambda: |- auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::WHITE); call.set_brightness(0.03f); call.set_color_temperature(333.0f); // ~3000K call.set_transition_length(1000); call.perform(); # Breathe (Soft) — gentle pulse on the current color - pulse: name: "Breathe (Soft)" transition_length: 3s update_interval: 3s min_brightness: 5% max_brightness: 35% # Amber Glow — very gentle warm wave (8–20%) - lambda: name: "Amber Glow" update_interval: 500ms lambda: |- static float t = 0.0f; t += 0.5f; // seconds step (approx) float phase = (sinf(t * 2.0f * (3.14159f/16.0f)) + 1.0f) / 2.0f; // ~16s cycle float b = 0.08f + phase * 0.12f; // 8%..20% auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::WHITE); call.set_brightness(b); call.set_color_temperature(333.0f); // 3000K call.set_transition_length(800); call.perform(); # Pastel Cycle — very slow, soft rainbow (~12–20% brightness) - lambda: name: "Pastel Cycle" update_interval: 1000ms lambda: |- static float t = 0.0f; t += 1.0f; // seconds const float period = 120.0f; // 120s full cycle float w = 2.0f * 3.14159f / period; // Three sine waves 120° apart for a pastel rainbow float r = 0.35f + 0.25f * sinf(w * t + 0.0f); float g = 0.35f + 0.25f * sinf(w * t + 2.094f); float b = 0.35f + 0.25f * sinf(w * t + 4.188f); auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(0.18f); call.set_rgb(r, g, b); call.set_transition_length(1200); call.perform(); # Ocean Fade — teal↔blue drift (~10–18% brightness) - lambda: name: "Ocean Fade" update_interval: 1200ms lambda: |- static float t = 0.0f; t += 1.2f; float phase = (sinf(t * 2.0f * (3.14159f/36.0f)) + 1.0f) / 2.0f; // ~36s cycle // Lerp between teal (0.0,0.6,0.6) and blue (0.25,0.45,1.0) float r = (1.0f - phase) * 0.00f + phase * 0.25f; float g = (1.0f - phase) * 0.60f + phase * 0.45f; float b = (1.0f - phase) * 0.60f + phase * 1.00f; auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(0.16f); call.set_rgb(r, g, b); call.set_transition_length(1400); call.perform(); # Sunset Drift — peach↔soft amber (~12–22% brightness) - lambda: name: "Sunset Drift" update_interval: 1000ms lambda: |- static float t = 0.0f; t += 1.0f; float phase = (sinf(t * 2.0f * (3.14159f/40.0f)) + 1.0f) / 2.0f; // ~40s // Peach (1.0,0.65,0.50) to Amber (1.0,0.75,0.30) float r = 1.00f; float g = (1.0f - phase) * 0.65f + phase * 0.75f; float b = (1.0f - phase) * 0.50f + phase * 0.30f; auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(0.20f); call.set_rgb(r, g, b); call.set_transition_length(1200); call.perform(); # Lavender Breeze — lavender↔rose (~10–18% brightness) - lambda: name: "Lavender Breeze" update_interval: 1200ms lambda: |- static float t = 0.0f; t += 1.2f; float phase = (sinf(t * 2.0f * (3.14159f/48.0f)) + 1.0f) / 2.0f; // ~48s // Lavender (0.70,0.55,1.00) to Rose (1.00,0.60,0.85) float r = (1.0f - phase) * 0.70f + phase * 1.00f; float g = (1.0f - phase) * 0.55f + phase * 0.60f; float b = (1.0f - phase) * 1.00f + phase * 0.85f; auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(0.15f); call.set_rgb(r, g, b); call.set_transition_length(1400); call.perform(); # Forest Calm — moss↔mint (~8–16% brightness) - lambda: name: "Forest Calm" update_interval: 1000ms lambda: |- static float t = 0.0f; t += 1.0f; float phase = (sinf(t * 2.0f * (3.14159f/44.0f)) + 1.0f) / 2.0f; // ~44s // Moss (0.25,0.55,0.25) to Mint (0.50,0.95,0.65) float r = (1.0f - phase) * 0.25f + phase * 0.50f; float g = (1.0f - phase) * 0.55f + phase * 0.95f; float b = (1.0f - phase) * 0.25f + phase * 0.65f; auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(0.14f); call.set_rgb(r, g, b); call.set_transition_length(1200); call.perform(); # Blue Calm — soft cool tint, tiny drift (6–14%) - lambda: name: "Blue Calm" update_interval: 1000ms lambda: |- static float t = 0.0f; t += 1.0f; float phase = (sinf(t * 2.0f * (3.14159f/20.0f)) + 1.0f) / 2.0f; // ~20s cycle float b = 0.06f + phase * 0.08f; // 6%..14% auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::RGB); call.set_brightness(b); call.set_rgb(0.45f, 0.55f, 1.00f); // gentle cool bluish tint call.set_transition_length(1200); call.perform(); # Warm Dim — static warm preset (~15%) - lambda: name: "Warm Dim" update_interval: 5s lambda: |- auto call = id(my_light).turn_on(); call.set_color_mode(ColorMode::WHITE); call.set_brightness(0.15f); call.set_color_temperature(333.0f); // ~3000K call.set_transition_length(800); call.perform();