Files
jdillenburg-esphome/garage-door-controller.yaml
John Dillenburg 7dc846a6eb matthiazzz - The current adxl345 component in ESPHome relies on multiple external Adafruit libraries (Adafruit Unified Sensor, Adafruit BusIO, Adafruit ADXL345). This causes unnecessary dependencies, compilation overhead, and sometimes incompatibilities when used with tca9548a multiplexers.
I modified the component to remove all Adafruit library dependencies and instead use a lightweight, self-contained ESPHome driver for ADXL345. After these changes, multiple ADXL345 sensors can be used in combination with a TCA9548A I²C multiplexer without conflicts.
2025-09-06 15:38:59 -05:00

369 lines
10 KiB
YAML

esphome:
name: garage-door-controller
friendly_name: Garage door controller
packages:
beacon: !include { file: packages/beacon.yaml }
wifi: !include { file: packages/wifi.yaml, vars: { ssid: "garage-door-controller" }}
external_components:
- source: github://jdillenburg/esphome@main
components: [ tfmini ]
substitutions:
led_count: "60"
esp32:
board: esp32dev
framework:
type: esp-idf
# Enable logging
logger:
level: INFO
# Enable Home Assistant API
api:
encryption:
key: !secret garage_door_api_key
ota:
- platform: esphome
password: !secret garage_door_ota_password
globals:
- id: sensor_counter
type: int
initial_value: '0'
- id: effect_counter
type: int
initial_value: '0'
- id: safe_zone
type: bool
initial_value: 'false'
# Garage door button on GPIO16
switch:
- platform: gpio
device_class: switch
pin: GPIO17
id: relay
name: "Garage Door Relay"
restore_mode: ALWAYS_OFF
on_turn_on:
then:
- delay: 30000ms
- switch.turn_off: relay
# configurable distance thresholds
number:
- platform: template
name: Minimum distance
id: min_distance
icon: "mdi:cogs"
optimistic: true
restore_value: true
initial_value: "0.0"
min_value: 0.0
max_value: 20000.0
step: 1.0
unit_of_measurement: cm
- platform: template
name: Maximum distance
id: max_distance
icon: "mdi:cogs"
optimistic: true
restore_value: true
initial_value: "10000.0"
min_value: 0.0
max_value: 20000.0
step: 1.0
unit_of_measurement: cm
- platform: template
name: Buffer distance
id: buffer_distance
icon: "mdi:cogs"
optimistic: true
restore_value: true
initial_value: "10.0"
min_value: 0.0
max_value: 20000.0
step: 1.0
unit_of_measurement: cm
#**************** UART ********************
uart:
tx_pin: GPIO21 #TXD
rx_pin: GPIO22 #RXD
baud_rate: 115200
id: uart_bus
debug:
direction: BOTH
dummy_receiver: false
after:
delimiter: "\n"
sequence:
- lambda: UARTDebug::log_string(direction, bytes);
#******************** Binary Sensor *********************
binary_sensor:
- platform: gpio
pin: GPIO23
id: closed_sensor
internal: True
- platform: template
id: parked_sensor
name: "Car parked"
- platform: template
id: car_exiting
name: "Car exiting"
condition:
sensor.in_range:
id: vehicle_average_speed
above: 1.0
- platform: template
id: car_entering
name: "Car entering"
condition:
sensor.in_range:
id: vehicle_average_speed
below: -1.0
#******************** Sensor *********************
sensor:
- platform: tfmini
id: distance_sensor_raw
internal: True
distance_unit: cm
name: "Distance sensor raw"
unit_of_measurement: "cm"
on_value:
then:
- sensor.template.publish:
id: distance_sensor
state: !lambda 'return x;'
- sensor.template.publish:
id: distance_sensor_leds
state: !lambda 'return x;'
- lambda: |-
id(sensor_counter) = id(sensor_counter) + 1;
# - sensor.template.publish:
# id: reading_sensor_counter
# state: !lambda 'return id(reading_counter).state + 1;'
- platform: template
name: "Distance sensor"
id: distance_sensor
internal: False
unit_of_measurement: "cm"
filters:
- clamp:
min_value: 0.0
max_value: 800.0
ignore_out_of_range: True
- throttle_average: 1000ms
- platform: template
name: "Distance sensor for LEDs"
id: distance_sensor_leds
internal: True
unit_of_measurement: "cm"
filters:
- clamp:
min_value: 0.0
max_value: 800.0
ignore_out_of_range: True
- platform: template
name: "Sensor readings per second"
id: reading_counter
unit_of_measurement: "readings/s"
icon: "mdi:speedometer"
update_interval: 10s
lambda: |-
float current_count = id(sensor_counter);
id(sensor_counter) = 0;
return current_count/10.0;
- platform: template
id: light_speed
name: "Light effect changes per second"
unit_of_measurement: "Hz"
icon: "mdi:speedometer"
update_interval: 10s
lambda: |-
float current_count = id(effect_counter);
id(effect_counter) = 0;
return current_count/10.0;
#**************** TIMEOUT OF 30 SECONDS ************************
# See lights_off_when_still script for timeout value
- platform: template
name: "Vehicle average speed"
id: vehicle_average_speed
unit_of_measurement: "cm/s"
accuracy_decimals: 3
update_interval: 500ms
lambda: |-
static float previous_distance = 0;
static uint32_t last_update = 0;
float rate = 0;
if (last_update != 0) {
float time_delta = (millis() - last_update) / 1000.0;
float value_delta = id(distance_sensor_raw).state - previous_distance;
rate = value_delta / time_delta;
}
previous_distance = id(distance_sensor_raw).state;
last_update = millis();
return rate;
filters:
- sliding_window_moving_average:
window_size: 5 # average 5 x 0.5 seconds = 2.5 seconds worth of speed
send_every: 1 # send average speed every 1/2 second
on_value:
then:
- if:
condition:
- lambda: 'return abs(id(vehicle_average_speed).state) < 1.0;' # 0.02 mph really slow!
then:
- if:
condition:
- and:
- light.is_on: led_strip
- not:
script.is_running: lights_off_when_still
then:
script.execute: lights_off_when_still
else:
- if:
condition:
- light.is_off: led_strip
then:
- script.stop: lights_off_when_still
- light.turn_on:
id: led_strip
effect: "Distance Effect"
- binary_sensor.template.publish:
id: parked_sensor
state: false
#******************** Cover *********************
cover:
- platform: template
name: "Garage Door"
id: garage_door
device_class: garage
open_action:
then:
- switch.toggle: relay
close_action:
then:
- switch.toggle: relay
lambda: |-
return id(closed_sensor).state ? COVER_OPEN : COVER_CLOSED;
#********** LED Strip configuration **********
light:
- platform: esp32_rmt_led_strip
id: led_strip
chipset: WS2812
pin: GPIO16
num_leds: ${led_count}
rgb_order: GRB
name: "Parking Assistant LEDs"
restore_mode: RESTORE_DEFAULT_ON
effects:
- addressable_lambda:
name: "Distance Effect"
update_interval: 250ms
lambda: |-
float distance = id(distance_sensor_leds).state;
if (distance <= 0 || std::isnan(distance)) return; // Invalid reading
// Get the total number of LEDs
const int total_leds = it.size();
// Calculate safe zone boundaries
float min_safe = id(min_distance).state - id(buffer_distance).state;
float max_safe = id(min_distance).state + id(buffer_distance).state;
// Measure update rate
id(effect_counter) = id(effect_counter) + 1;
// Set safe_zone flag based on distance
if (distance >= min_safe && distance <= max_safe) {
id(safe_zone) = true;
} else {
id(safe_zone) = false;
}
// blink if less than min_safe
if (distance < min_safe) {
if ((millis() % 1000) < 500) {
it.all() = Color(255,0,0); // RED
}
else {
it.all() = Color::BLACK;
}
return;
}
// solid red in safe zone
if (distance < max_safe) {
it.all() = Color(255,0,0);
return;
}
// Above max_safe distance, calculate color and LED count
float ratio;
float denominator = id(max_distance).state - max_safe;
if (denominator <= 0.0) {
ratio = 1.0;
} else {
ratio = (distance - max_safe) / denominator;
ratio = std::max(0.0f, std::min(1.0f, ratio));
}
// Calculate colors - linear interpolation from red to yellow to green
uint8_t red, green;
if (ratio <= 0.5) { // Red to Yellow
red = 255;
green = 255 * ratio * 2; // Green goes from 0 to 1
} else { // Yellow to Green
red = 255 * 2 * (1.0 - ratio); // Red goes from 1 to 0
green = 255;
}
// Create the color object
auto color = Color(red, green, 0);
// Calculate the number of LEDs to light
int leds_to_light = static_cast<int>(ratio * total_leds + 0.5);
leds_to_light = std::max(0, std::min(total_leds, leds_to_light));
// Center the lit LEDs
int start_index = (total_leds - leds_to_light) / 2;
int end_index = start_index + leds_to_light - 1;
// Turn off all LEDs
it.range(0, start_index) = Color::BLACK;
it.range(start_index, end_index) = color;
it.range(end_index, total_leds) = Color::BLACK;
return;
script:
- id: lights_off_when_still
mode: restart
then:
- delay: 30s
- light.turn_off:
id: led_strip
transition_length:
seconds: 5
- if:
condition:
- lambda: 'return id(safe_zone);'
then:
- binary_sensor.template.publish:
id: parked_sensor
state: true