Edit esp-astroclockstepper1.yaml
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-astroclockstepper.yaml
|
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-astroclockstepper.yaml
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# VERSIONS:
|
# VERSIONS:
|
||||||
|
# V1.3 2026-06-22 Added SNTP year auto-positioning button and restored boot auto-position switch
|
||||||
# V1.2 2026-06-22 Added DHCP IPv4 address flash sequence on onboard LED after WiFi connects
|
# V1.2 2026-06-22 Added DHCP IPv4 address flash sequence on onboard LED after WiFi connects
|
||||||
# V1.1 2026-06-22 Added onboard D1 Mini LED flash on each motor step
|
# V1.1 2026-06-22 Added onboard D1 Mini LED flash on each motor step
|
||||||
# V1.0 2026-06-22 Initial Version
|
# V1.0 2026-06-22 Initial Version
|
||||||
@@ -52,6 +53,10 @@
|
|||||||
# - After WiFi connects, the onboard LED flashes the DHCP IPv4 address.
|
# - After WiFi connects, the onboard LED flashes the DHCP IPv4 address.
|
||||||
# - IPv4 flash sequence is decimal digit based.
|
# - IPv4 flash sequence is decimal digit based.
|
||||||
# - A digit of 0 is represented as 10 flashes.
|
# - A digit of 0 is represented as 10 flashes.
|
||||||
|
# - SNTP is used for current year-position calculation.
|
||||||
|
# - User should manually align the dial to year-zero, then press Zero Position Counter.
|
||||||
|
# - Auto Position Now moves forward only to the current calculated year position.
|
||||||
|
# - Auto Position On Boot is off by default, restored on power loss, and runs after boot/IP flash.
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# OFFLINE NOTES:
|
# OFFLINE NOTES:
|
||||||
# a) Home Assistant OFFLINE, but Network ONLINE
|
# a) Home Assistant OFFLINE, but Network ONLINE
|
||||||
@@ -62,9 +67,14 @@
|
|||||||
# - Physical buttons continue to work
|
# - Physical buttons continue to work
|
||||||
# - Normal motor timing continues from device uptime
|
# - Normal motor timing continues from device uptime
|
||||||
# - Fallback AP / captive portal should become available from network_common_dhcp.yaml
|
# - Fallback AP / captive portal should become available from network_common_dhcp.yaml
|
||||||
# c) Device power loss / reboot
|
# c) SNTP NOT SYNCED
|
||||||
# - V1 does not restore exact astronomical position after reboot
|
# - Normal motor timing continues
|
||||||
# - Re-align manually using the web or physical button controls
|
# - Manual controls continue
|
||||||
|
# - Auto Position Now will not run until SNTP time is valid
|
||||||
|
# d) Device power loss / reboot
|
||||||
|
# - Current position counter is restored from flash
|
||||||
|
# - Auto Position On Boot setting is restored from flash
|
||||||
|
# - Physical position is assumed valid because the motor housing/dial is fixed
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
|
|
||||||
|
|
||||||
@@ -81,7 +91,7 @@ substitutions:
|
|||||||
|
|
||||||
# Project Naming
|
# Project Naming
|
||||||
project_name: "zorruno.Astronomical Clock Stepper"
|
project_name: "zorruno.Astronomical Clock Stepper"
|
||||||
project_version: "v1.2"
|
project_version: "v1.3"
|
||||||
|
|
||||||
# Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names)
|
# Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names)
|
||||||
api_key: !secret esp-api_key
|
api_key: !secret esp-api_key
|
||||||
@@ -92,6 +102,9 @@ substitutions:
|
|||||||
sensor_update_interval: "1s"
|
sensor_update_interval: "1s"
|
||||||
calculated_sensor_update_interval: "60s"
|
calculated_sensor_update_interval: "60s"
|
||||||
|
|
||||||
|
# Time Settings
|
||||||
|
timezone_name: "Pacific/Auckland"
|
||||||
|
|
||||||
# Astronomical Clock Settings
|
# Astronomical Clock Settings
|
||||||
rotation_days: "365.2422"
|
rotation_days: "365.2422"
|
||||||
steps_per_rotation: "4096"
|
steps_per_rotation: "4096"
|
||||||
@@ -105,6 +118,10 @@ substitutions:
|
|||||||
manual_fast_rotation_seconds: "30"
|
manual_fast_rotation_seconds: "30"
|
||||||
manual_slow_rotation_seconds: "300"
|
manual_slow_rotation_seconds: "300"
|
||||||
|
|
||||||
|
# Auto Position Speed
|
||||||
|
# Default is the same as Slow Forward: one full rotation every 300 seconds.
|
||||||
|
auto_position_rotation_seconds: "300"
|
||||||
|
|
||||||
# Coil Release
|
# Coil Release
|
||||||
coil_release_ms: "500"
|
coil_release_ms: "500"
|
||||||
|
|
||||||
@@ -121,9 +138,9 @@ substitutions:
|
|||||||
# Suggested human-countable timing
|
# Suggested human-countable timing
|
||||||
ip_flash_on_ms: "200"
|
ip_flash_on_ms: "200"
|
||||||
ip_flash_between_flash_gap_ms: "450"
|
ip_flash_between_flash_gap_ms: "450"
|
||||||
ip_flash_digit_gap_ms: "1000"
|
ip_flash_digit_gap_ms: "1500"
|
||||||
ip_flash_octet_gap_ms: "4500"
|
ip_flash_octet_gap_ms: "3500"
|
||||||
ip_flash_repeat_gap_ms: "10000"
|
ip_flash_repeat_gap_ms: "8000"
|
||||||
|
|
||||||
# Stepper Output Pins
|
# Stepper Output Pins
|
||||||
stepper_in1_pin: GPIO14
|
stepper_in1_pin: GPIO14
|
||||||
@@ -151,6 +168,11 @@ substitutions:
|
|||||||
zero_position_name: "Zero Position Counter"
|
zero_position_name: "Zero Position Counter"
|
||||||
replay_ip_flash_name: "Replay IP Address Flash"
|
replay_ip_flash_name: "Replay IP Address Flash"
|
||||||
|
|
||||||
|
auto_position_now_name: "Auto Position Now"
|
||||||
|
auto_position_on_boot_name: "Auto Position On Boot"
|
||||||
|
auto_position_active_name: "Auto Position Active"
|
||||||
|
sntp_time_valid_name: "SNTP Time Valid"
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# PACKAGES: Included Common Packages
|
# PACKAGES: Included Common Packages
|
||||||
@@ -181,13 +203,8 @@ packages:
|
|||||||
#common_webportal: !include common/webportal_common.yaml
|
#common_webportal: !include common/webportal_common.yaml
|
||||||
common_webportal: !include common/webportal_common_nopasswd.yaml
|
common_webportal: !include common/webportal_common_nopasswd.yaml
|
||||||
|
|
||||||
#### SNTP (Only use if you want/need accurate timeclocks) ####
|
|
||||||
#common_sntp: !include common/sntp_common.yaml
|
|
||||||
common_sntp: !include common/sntp_common_public.yaml
|
|
||||||
|
|
||||||
#### DIAGNOSTICS Sensors ####
|
#### DIAGNOSTICS Sensors ####
|
||||||
diag_basic: !include common/include_basic_diag_sensors.yaml
|
diag_basic: !include common/include_basic_diag_sensors.yaml
|
||||||
diag_more: !include common/include_more_diag_sensors_nomqtt.yaml
|
|
||||||
#diag_more: !include common/include_more_diag_sensors.yaml
|
#diag_more: !include common/include_more_diag_sensors.yaml
|
||||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||||
@@ -210,6 +227,7 @@ esphome:
|
|||||||
priority: -100
|
priority: -100
|
||||||
then:
|
then:
|
||||||
- output.turn_off: onboard_step_led
|
- output.turn_off: onboard_step_led
|
||||||
|
|
||||||
- logger.log:
|
- logger.log:
|
||||||
level: INFO
|
level: INFO
|
||||||
format: "Astronomical Clock Stepper started. Normal rotation is %s days per full revolution."
|
format: "Astronomical Clock Stepper started. Normal rotation is %s days per full revolution."
|
||||||
@@ -221,9 +239,38 @@ esphome:
|
|||||||
- wait_until:
|
- wait_until:
|
||||||
condition:
|
condition:
|
||||||
wifi.connected:
|
wifi.connected:
|
||||||
|
|
||||||
- delay: 3s
|
- delay: 3s
|
||||||
|
|
||||||
- script.execute: start_ip_flash_script
|
- script.execute: start_ip_flash_script
|
||||||
|
|
||||||
|
# Give the IP flash state machine time to start.
|
||||||
|
- delay: 100ms
|
||||||
|
|
||||||
|
# Wait for the boot IP flash sequence to finish before optional auto-positioning.
|
||||||
|
- wait_until:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
return !id(ip_flash_active);
|
||||||
|
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
switch.is_on: auto_position_on_boot_switch
|
||||||
|
then:
|
||||||
|
- globals.set:
|
||||||
|
id: auto_position_on_boot_pending
|
||||||
|
value: "true"
|
||||||
|
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
return id(sntp_time).now().is_valid();
|
||||||
|
then:
|
||||||
|
- globals.set:
|
||||||
|
id: auto_position_on_boot_pending
|
||||||
|
value: "false"
|
||||||
|
- script.execute: start_auto_position_script
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# ESP PLATFORM AND FRAMEWORK:
|
# ESP PLATFORM AND FRAMEWORK:
|
||||||
@@ -234,7 +281,7 @@ esp8266:
|
|||||||
restore_from_flash: true
|
restore_from_flash: true
|
||||||
|
|
||||||
preferences:
|
preferences:
|
||||||
flash_write_interval: 5min
|
flash_write_interval: 1min
|
||||||
|
|
||||||
mdns:
|
mdns:
|
||||||
disabled: false
|
disabled: false
|
||||||
@@ -249,20 +296,42 @@ logger:
|
|||||||
baud_rate: 0
|
baud_rate: 0
|
||||||
|
|
||||||
|
|
||||||
|
#:########################################################################################:#
|
||||||
|
# TIME:
|
||||||
|
# SNTP time source for year-position calculation
|
||||||
|
# https://esphome.io/components/time/sntp.html
|
||||||
|
#:########################################################################################:#
|
||||||
|
time:
|
||||||
|
- platform: sntp
|
||||||
|
id: sntp_time
|
||||||
|
timezone: "${timezone_name}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: |-
|
||||||
|
return id(auto_position_on_boot_pending) && id(auto_position_on_boot_switch).state;
|
||||||
|
then:
|
||||||
|
- globals.set:
|
||||||
|
id: auto_position_on_boot_pending
|
||||||
|
value: "false"
|
||||||
|
- script.execute: start_auto_position_script
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# GLOBALS:
|
# GLOBALS:
|
||||||
# Internal position, timing, mode, held-button state, and IP flash state
|
# Internal position, timing, mode, held-button state, IP flash state, and auto-position state
|
||||||
# https://esphome.io/components/globals.html
|
# https://esphome.io/components/globals.html
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
globals:
|
globals:
|
||||||
- id: current_position_step
|
- id: current_position_step
|
||||||
type: int
|
type: int
|
||||||
restore_value: no
|
restore_value: yes
|
||||||
initial_value: "0"
|
initial_value: "0"
|
||||||
|
|
||||||
- id: current_phase_index
|
- id: current_phase_index
|
||||||
type: int
|
type: int
|
||||||
restore_value: no
|
restore_value: yes
|
||||||
initial_value: "0"
|
initial_value: "0"
|
||||||
|
|
||||||
- id: last_loop_ms
|
- id: last_loop_ms
|
||||||
@@ -300,6 +369,7 @@ globals:
|
|||||||
# 2 = Slow Forward
|
# 2 = Slow Forward
|
||||||
# 3 = Fast Reverse
|
# 3 = Fast Reverse
|
||||||
# 4 = Slow Reverse
|
# 4 = Slow Reverse
|
||||||
|
# 5 = Auto Position
|
||||||
- id: current_motion_mode
|
- id: current_motion_mode
|
||||||
type: int
|
type: int
|
||||||
restore_value: no
|
restore_value: no
|
||||||
@@ -403,6 +473,27 @@ globals:
|
|||||||
restore_value: no
|
restore_value: no
|
||||||
initial_value: "0"
|
initial_value: "0"
|
||||||
|
|
||||||
|
# Auto Position State
|
||||||
|
- id: auto_position_active
|
||||||
|
type: bool
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "false"
|
||||||
|
|
||||||
|
- id: auto_position_on_boot_pending
|
||||||
|
type: bool
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "false"
|
||||||
|
|
||||||
|
- id: auto_position_target_step
|
||||||
|
type: int
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
- id: auto_position_steps_remaining
|
||||||
|
type: int
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# OUTPUT:
|
# OUTPUT:
|
||||||
@@ -490,10 +581,115 @@ script:
|
|||||||
${ip_flash_repeat_count}
|
${ip_flash_repeat_count}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
- id: start_auto_position_script
|
||||||
|
mode: restart
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
const int STEPS_PER_ROTATION = ${steps_per_rotation};
|
||||||
|
|
||||||
|
auto now = id(sntp_time).now();
|
||||||
|
|
||||||
|
if (!now.is_valid()) {
|
||||||
|
ESP_LOGW("auto_position", "SNTP time is not valid yet. Auto position cancelled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int year = now.year;
|
||||||
|
const int month = now.month;
|
||||||
|
const int day_of_month = now.day_of_month;
|
||||||
|
|
||||||
|
const bool is_leap_year =
|
||||||
|
((year % 4 == 0) && (year % 100 != 0)) ||
|
||||||
|
(year % 400 == 0);
|
||||||
|
|
||||||
|
const int days_in_year = is_leap_year ? 366 : 365;
|
||||||
|
|
||||||
|
const int days_before_month_common[12] = {
|
||||||
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||||
|
};
|
||||||
|
|
||||||
|
const int days_before_month_leap[12] = {
|
||||||
|
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
|
||||||
|
};
|
||||||
|
|
||||||
|
int safe_month = month;
|
||||||
|
|
||||||
|
if (safe_month < 1) {
|
||||||
|
safe_month = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safe_month > 12) {
|
||||||
|
safe_month = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
int safe_day_of_month = day_of_month;
|
||||||
|
|
||||||
|
if (safe_day_of_month < 1) {
|
||||||
|
safe_day_of_month = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safe_day_of_month > 31) {
|
||||||
|
safe_day_of_month = 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int day_of_year =
|
||||||
|
(is_leap_year ? days_before_month_leap[safe_month - 1] : days_before_month_common[safe_month - 1]) +
|
||||||
|
safe_day_of_month;
|
||||||
|
|
||||||
|
const uint32_t seconds_elapsed_this_year =
|
||||||
|
((uint32_t) (day_of_year - 1) * 86400UL) +
|
||||||
|
((uint32_t) now.hour * 3600UL) +
|
||||||
|
((uint32_t) now.minute * 60UL) +
|
||||||
|
((uint32_t) now.second);
|
||||||
|
|
||||||
|
const double seconds_in_year = (double) days_in_year * 86400.0;
|
||||||
|
|
||||||
|
int target_step =
|
||||||
|
(int) (((double) seconds_elapsed_this_year / seconds_in_year) *
|
||||||
|
(double) STEPS_PER_ROTATION);
|
||||||
|
|
||||||
|
target_step = target_step % STEPS_PER_ROTATION;
|
||||||
|
|
||||||
|
int current_step = id(current_position_step) % STEPS_PER_ROTATION;
|
||||||
|
|
||||||
|
if (current_step < 0) {
|
||||||
|
current_step += STEPS_PER_ROTATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int steps_to_move =
|
||||||
|
(target_step - current_step + STEPS_PER_ROTATION) % STEPS_PER_ROTATION;
|
||||||
|
|
||||||
|
id(auto_position_target_step) = target_step;
|
||||||
|
id(auto_position_steps_remaining) = steps_to_move;
|
||||||
|
|
||||||
|
if (steps_to_move == 0) {
|
||||||
|
id(auto_position_active) = false;
|
||||||
|
ESP_LOGI(
|
||||||
|
"auto_position",
|
||||||
|
"Already at correct year position. Year: %d, target step: %d.",
|
||||||
|
year,
|
||||||
|
target_step
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id(auto_position_active) = true;
|
||||||
|
|
||||||
|
ESP_LOGI(
|
||||||
|
"auto_position",
|
||||||
|
"Auto positioning started. Year: %d, day_of_year: %d/%d, target step: %d, current step: %d, moving forward %d steps.",
|
||||||
|
year,
|
||||||
|
day_of_year,
|
||||||
|
days_in_year,
|
||||||
|
target_step,
|
||||||
|
current_step,
|
||||||
|
steps_to_move
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# SWITCH:
|
# SWITCH:
|
||||||
# Web held-button controls
|
# Web held-button controls and restored auto-position boot option
|
||||||
# https://esphome.io/components/switch/template.html
|
# https://esphome.io/components/switch/template.html
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
switch:
|
switch:
|
||||||
@@ -569,6 +765,13 @@ switch:
|
|||||||
id: web_slow_reverse_active
|
id: web_slow_reverse_active
|
||||||
value: "false"
|
value: "false"
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "${auto_position_on_boot_name}"
|
||||||
|
id: auto_position_on_boot_switch
|
||||||
|
icon: mdi:calendar-sync
|
||||||
|
optimistic: true
|
||||||
|
restore_mode: RESTORE_DEFAULT_OFF
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# BINARY SENSORS:
|
# BINARY SENSORS:
|
||||||
@@ -652,6 +855,20 @@ binary_sensor:
|
|||||||
id: physical_slow_reverse_active
|
id: physical_slow_reverse_active
|
||||||
value: "false"
|
value: "false"
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "${auto_position_active_name}"
|
||||||
|
id: auto_position_active_sensor
|
||||||
|
icon: mdi:calendar-sync
|
||||||
|
lambda: |-
|
||||||
|
return id(auto_position_active);
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "${sntp_time_valid_name}"
|
||||||
|
id: sntp_time_valid_sensor
|
||||||
|
icon: mdi:clock-check-outline
|
||||||
|
lambda: |-
|
||||||
|
return id(sntp_time).now().is_valid();
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# BUTTON:
|
# BUTTON:
|
||||||
@@ -673,6 +890,12 @@ button:
|
|||||||
- globals.set:
|
- globals.set:
|
||||||
id: step_accumulator_ms
|
id: step_accumulator_ms
|
||||||
value: "0.0"
|
value: "0.0"
|
||||||
|
- globals.set:
|
||||||
|
id: auto_position_active
|
||||||
|
value: "false"
|
||||||
|
- globals.set:
|
||||||
|
id: auto_position_steps_remaining
|
||||||
|
value: "0"
|
||||||
- logger.log:
|
- logger.log:
|
||||||
level: INFO
|
level: INFO
|
||||||
format: "Position counter zeroed."
|
format: "Position counter zeroed."
|
||||||
@@ -684,6 +907,13 @@ button:
|
|||||||
on_press:
|
on_press:
|
||||||
- script.execute: start_ip_flash_script
|
- script.execute: start_ip_flash_script
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "${auto_position_now_name}"
|
||||||
|
id: auto_position_now_button
|
||||||
|
icon: mdi:calendar-clock
|
||||||
|
on_press:
|
||||||
|
- script.execute: start_auto_position_script
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# SENSOR:
|
# SENSOR:
|
||||||
@@ -740,6 +970,34 @@ sensor:
|
|||||||
lambda: |-
|
lambda: |-
|
||||||
return (${rotation_days} * 24.0 * 60.0 * 60.0) / ${steps_per_rotation};
|
return (${rotation_days} * 24.0 * 60.0 * 60.0) / ${steps_per_rotation};
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Auto Position Target Step"
|
||||||
|
id: auto_position_target_step_sensor
|
||||||
|
icon: mdi:target
|
||||||
|
accuracy_decimals: 0
|
||||||
|
update_interval: "${sensor_update_interval}"
|
||||||
|
lambda: |-
|
||||||
|
return id(auto_position_target_step);
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Auto Position Steps Remaining"
|
||||||
|
id: auto_position_steps_remaining_sensor
|
||||||
|
icon: mdi:counter
|
||||||
|
accuracy_decimals: 0
|
||||||
|
update_interval: "${sensor_update_interval}"
|
||||||
|
lambda: |-
|
||||||
|
return id(auto_position_steps_remaining);
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Auto Position Target Days"
|
||||||
|
id: auto_position_target_days_sensor
|
||||||
|
icon: mdi:calendar-clock
|
||||||
|
unit_of_measurement: "days"
|
||||||
|
accuracy_decimals: 4
|
||||||
|
update_interval: "${sensor_update_interval}"
|
||||||
|
lambda: |-
|
||||||
|
return ((double) id(auto_position_target_step) * ${rotation_days}) / ${steps_per_rotation};
|
||||||
|
|
||||||
|
|
||||||
#:########################################################################################:#
|
#:########################################################################################:#
|
||||||
# TEXT SENSOR:
|
# TEXT SENSOR:
|
||||||
@@ -762,6 +1020,8 @@ text_sensor:
|
|||||||
return {"Fast Reverse"};
|
return {"Fast Reverse"};
|
||||||
case 4:
|
case 4:
|
||||||
return {"Slow Reverse"};
|
return {"Slow Reverse"};
|
||||||
|
case 5:
|
||||||
|
return {"Auto Position"};
|
||||||
case 0:
|
case 0:
|
||||||
default:
|
default:
|
||||||
return {"Normal"};
|
return {"Normal"};
|
||||||
@@ -797,6 +1057,9 @@ interval:
|
|||||||
const double SLOW_STEP_INTERVAL_MS =
|
const double SLOW_STEP_INTERVAL_MS =
|
||||||
(${manual_slow_rotation_seconds} * 1000.0) / ${steps_per_rotation};
|
(${manual_slow_rotation_seconds} * 1000.0) / ${steps_per_rotation};
|
||||||
|
|
||||||
|
const double AUTO_POSITION_STEP_INTERVAL_MS =
|
||||||
|
(${auto_position_rotation_seconds} * 1000.0) / ${steps_per_rotation};
|
||||||
|
|
||||||
const uint32_t COIL_RELEASE_MS = ${coil_release_ms};
|
const uint32_t COIL_RELEASE_MS = ${coil_release_ms};
|
||||||
const uint32_t STEP_LED_FLASH_MS = ${step_led_flash_ms};
|
const uint32_t STEP_LED_FLASH_MS = ${step_led_flash_ms};
|
||||||
|
|
||||||
@@ -883,6 +1146,18 @@ interval:
|
|||||||
const bool slow_reverse_active =
|
const bool slow_reverse_active =
|
||||||
id(physical_slow_reverse_active) || id(web_slow_reverse_active);
|
id(physical_slow_reverse_active) || id(web_slow_reverse_active);
|
||||||
|
|
||||||
|
const bool any_manual_control_active =
|
||||||
|
fast_forward_active ||
|
||||||
|
slow_forward_active ||
|
||||||
|
fast_reverse_active ||
|
||||||
|
slow_reverse_active;
|
||||||
|
|
||||||
|
if (any_manual_control_active && id(auto_position_active)) {
|
||||||
|
id(auto_position_active) = false;
|
||||||
|
id(auto_position_steps_remaining) = 0;
|
||||||
|
ESP_LOGW("auto_position", "Auto positioning cancelled by manual control.");
|
||||||
|
}
|
||||||
|
|
||||||
int selected_mode = 0;
|
int selected_mode = 0;
|
||||||
int selected_direction = NORMAL_DIRECTION_MULTIPLIER;
|
int selected_direction = NORMAL_DIRECTION_MULTIPLIER;
|
||||||
double selected_step_interval_ms = NORMAL_STEP_INTERVAL_MS;
|
double selected_step_interval_ms = NORMAL_STEP_INTERVAL_MS;
|
||||||
@@ -903,6 +1178,10 @@ interval:
|
|||||||
selected_mode = 4;
|
selected_mode = 4;
|
||||||
selected_direction = -NORMAL_DIRECTION_MULTIPLIER;
|
selected_direction = -NORMAL_DIRECTION_MULTIPLIER;
|
||||||
selected_step_interval_ms = SLOW_STEP_INTERVAL_MS;
|
selected_step_interval_ms = SLOW_STEP_INTERVAL_MS;
|
||||||
|
} else if (id(auto_position_active)) {
|
||||||
|
selected_mode = 5;
|
||||||
|
selected_direction = NORMAL_DIRECTION_MULTIPLIER;
|
||||||
|
selected_step_interval_ms = AUTO_POSITION_STEP_INTERVAL_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t now_ms = millis();
|
const uint32_t now_ms = millis();
|
||||||
@@ -926,6 +1205,23 @@ interval:
|
|||||||
|
|
||||||
if (id(step_accumulator_ms) >= selected_step_interval_ms) {
|
if (id(step_accumulator_ms) >= selected_step_interval_ms) {
|
||||||
do_one_step(selected_direction, now_ms);
|
do_one_step(selected_direction, now_ms);
|
||||||
|
|
||||||
|
if (selected_mode == 5 && id(auto_position_active)) {
|
||||||
|
id(auto_position_steps_remaining)--;
|
||||||
|
|
||||||
|
if (id(auto_position_steps_remaining) <= 0) {
|
||||||
|
id(auto_position_steps_remaining) = 0;
|
||||||
|
id(auto_position_active) = false;
|
||||||
|
id(current_motion_mode) = 0;
|
||||||
|
|
||||||
|
ESP_LOGI(
|
||||||
|
"auto_position",
|
||||||
|
"Auto positioning complete. Current step: %d.",
|
||||||
|
id(current_position_step)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id(step_accumulator_ms) -= selected_step_interval_ms;
|
id(step_accumulator_ms) -= selected_step_interval_ms;
|
||||||
|
|
||||||
// If the loop was badly delayed, avoid trying to catch up with a burst
|
// If the loop was badly delayed, avoid trying to catch up with a burst
|
||||||
@@ -1076,4 +1372,52 @@ interval:
|
|||||||
|
|
||||||
id(onboard_step_led).turn_on();
|
id(onboard_step_led).turn_on();
|
||||||
id(ip_flash_led_is_on) = true;
|
id(ip_flash_led_is_on) = true;
|
||||||
id(ip_flash_next_action_ms) = now_ms + IP_FLASH_ON_MS;
|
id(ip_flash_next_action_ms) = now_ms + IP_FLASH_ON_MS;
|
||||||
|
|
||||||
|
|
||||||
|
#:########################################################################################:#
|
||||||
|
# MQTT:
|
||||||
|
# Device-specific MQTT command triggers, in addition to common MQTT config
|
||||||
|
# https://esphome.io/components/mqtt.html
|
||||||
|
#:########################################################################################:#
|
||||||
|
#mqtt:
|
||||||
|
# on_message:
|
||||||
|
# - topic: "${mqtt_command_topic}/fast_forward/set"
|
||||||
|
# payload: "ON"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_on: web_fast_forward_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/fast_forward/set"
|
||||||
|
# payload: "OFF"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_off: web_fast_forward_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/slow_forward/set"
|
||||||
|
# payload: "ON"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_on: web_slow_forward_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/slow_forward/set"
|
||||||
|
# payload: "OFF"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_off: web_slow_forward_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/fast_reverse/set"
|
||||||
|
# payload: "ON"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_on: web_fast_reverse_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/fast_reverse/set"
|
||||||
|
# payload: "OFF"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_off: web_fast_reverse_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/slow_reverse/set"
|
||||||
|
# payload: "ON"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_on: web_slow_reverse_switch
|
||||||
|
#
|
||||||
|
# - topic: "${mqtt_command_topic}/slow_reverse/set"
|
||||||
|
# payload: "OFF"
|
||||||
|
# then:
|
||||||
|
# - switch.turn_off: web_slow_reverse_switch
|
||||||
Reference in New Issue
Block a user