Hi All,
I’m trying to work out how to detect when a rotary encoder is stationary, so i can set the cover operation to idle. I’ve tried a few things but i just can’t seem to get it to work in a stable way.
Project: Super Smart Garage Door with Dumb Controller
Summary: I have an old merlin garage door opener that simply has some contact to trigger. Depending on the weather i like to leave the door open 25% to allow air flow.
- Ultrasonic Sensor is used to measure the distance and effectively simulate limit switches
- Rotary Encoder is resting against the drive chain to get the actual door position.
My current problem is how do i set the “Current Operation” of the Cover. I can easily get the Opening, Closing, but how do i set Idle? When the rotary encoder is not moving. Here is some of my code:
The Cover:
cover:
- platform: template
device_class: garage
name: "${friendly_name} Control"
has_position: true
optimistic: false
assumed_state: false
### This Lambda is to ensure that the door has an open and closed value based on the Ultrasonic even if the door hasnt been calibrated. If the Globals have been set to True then it will calculate the Exact position.
lambda: !lambda |-
if (id(closed_value_set) && id(open_value_set) ) {
return ( (id(encoder_last_value)) / (id(encoder_open_steps) ) );
} else {
if (id(door_state_closed_by_ultrasonic).state) {
return 0.0;
} else {
return 1.0;
}
}
id: ${devicename}_control
open_action:
- script.stop: door_position_command
- lambda: id(position_request) = 1;
- script.execute: door_position_command
stop_action:
- script.stop: door_position_command
- script.execute: stop_door
close_action:
- script.stop: door_position_command
- lambda: id(position_request) = 0;
- text_sensor.template.publish:
id: door_messages
state: "Requesting Door Fully Close"
- script.execute: door_position_command
- wait_until:
binary_sensor.is_on: door_state_closed_by_ultrasonic
- text_sensor.template.publish:
id: door_messages
state: "Door is now fully closed - Resetting Encoder to Zero"
- script.execute: reset_encoder_on_close
# - logger.log: "Running Encoder Reset on Close"
position_action:
- script.stop: door_position_command
# - lambda: id(${devicename}_position).state;
- lambda: id(position_request) = pos;
- lambda: ESP_LOGD("main", "Roller 1 setting position to %f", pos);
- script.execute: door_position_command
The Sensors:
sensor:
- platform: template
name: "direction"
id: direction
update_interval: 0.5s
internal: true
lambda: !lambda |-
return id(direction_encoder);
filters:
- lambda: |-
if (id(movement).state) {
return (x);
} else {
return 0.0;
}
- throttle: 1s
on_value_range:
- above: 0.9
then:
- cover.template.publish:
id: ${devicename}_control
current_operation: OPENING
- below: -0.9
then:
- cover.template.publish:
id: ${devicename}_control
current_operation: CLOSING
on_value:
then:
- if:
condition:
lambda: 'return id(direction).state == 0.0;'
then:
- cover.template.publish:
id: ${devicename}_control
current_operation: IDLE
- platform: rotary_encoder #this is the rotary encoder connected to the drive chain of the door
name: "Rotary Encoder"
id: door_rotary_encoder
min_value: 0
pin_a:
number: D1
mode: INPUT
pin_b:
number: D7
mode: INPUT
on_clockwise:
- delay: 0.25s
- globals.set:
id: direction_encoder
value: '1.0'
on_anticlockwise:
- delay: 0.25s
- globals.set:
id: direction_encoder
value: '-1.0'
on_value:
then:
# - globals.set:
# id: direction_encoder
# value: '0.0'
- globals.set:
id: rotation_detect
value: 'true'
- globals.set:
id: encoder_last_value
value: !lambda "return (x);"
- delay: 0.75s
- globals.set:
id: rotation_detect
value: 'false'
- platform: ultrasonic ### This is the US-100 Ultrasonic Sensor that measures the distance from the motor to the door attachment on the slider that the chain moves.
name: "${friendly_name} Distance"
id: ${devicename}_distance
trigger_pin: GPIO12 #D6
echo_pin: GPIO14 #D5
update_interval: 1s
unit_of_measurement: "cm"
accuracy_decimals: 0
pulse_time: 10us
timeout: 20m
internal: false
filters:
- filter_out: nan # filter timeouts
- multiply: 100
- median:
window_size: 15
send_every: 5
send_first_at: 3
- lambda: |-
if ((x) >= (${distance_closed}) ) {
return (${distance_closed});
} else if ((x) <= (${distance_open}) ) {
return (${distance_open});
} else {
return x;
}
- platform: template # This displays the value of the variable Open Value when it is set
name: "Global Steps Open as set"
lambda: 'return (id(encoder_open_steps));'
accuracy_decimals: 0
update_interval: 5s
- platform: template #calculate the actual position of the door in % using the last known step count for door open
name: "Door Postion"
id: ${devicename}_position
unit_of_measurement: "pos"
icon: "mdi:door"
update_interval: 1s
accuracy_decimals: 2
lambda: return id(${devicename}_control).position;
- platform: template
name: "Position Request Value"
lambda: 'return id(position_request);'
update_interval: 2s
- platform: template
name: "Last known Value of Encoder"
lambda: 'return id(encoder_last_value);'
update_interval: 2s
Any ideas or suggestions?