Add restore_mode to rotary_encoder (#2643)

This commit is contained in:
niklasweber 2021-11-02 19:32:24 +01:00 committed by GitHub
parent 5ea77894b7
commit 379c3e98f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 0 deletions

View file

@ -125,6 +125,22 @@ void IRAM_ATTR HOT RotaryEncoderSensorStore::gpio_intr(RotaryEncoderSensorStore
void RotaryEncoderSensor::setup() { void RotaryEncoderSensor::setup() {
ESP_LOGCONFIG(TAG, "Setting up Rotary Encoder '%s'...", this->name_.c_str()); ESP_LOGCONFIG(TAG, "Setting up Rotary Encoder '%s'...", this->name_.c_str());
int32_t initial_value = 0;
switch (this->restore_mode_) {
case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO:
this->rtc_ = global_preferences->make_preference<int32_t>(this->get_object_id_hash());
if (!this->rtc_.load(&initial_value)) {
initial_value = 0;
}
break;
case ROTARY_ENCODER_ALWAYS_ZERO:
initial_value = 0;
break;
}
this->store_.counter = initial_value;
this->store_.last_read = initial_value;
this->pin_a_->setup(); this->pin_a_->setup();
this->store_.pin_a = this->pin_a_->to_isr(); this->store_.pin_a = this->pin_a_->to_isr();
this->pin_b_->setup(); this->pin_b_->setup();
@ -142,6 +158,18 @@ void RotaryEncoderSensor::dump_config() {
LOG_PIN(" Pin A: ", this->pin_a_); LOG_PIN(" Pin A: ", this->pin_a_);
LOG_PIN(" Pin B: ", this->pin_b_); LOG_PIN(" Pin B: ", this->pin_b_);
LOG_PIN(" Pin I: ", this->pin_i_); LOG_PIN(" Pin I: ", this->pin_i_);
const LogString *restore_mode = LOG_STR("");
switch (this->restore_mode_) {
case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO:
restore_mode = LOG_STR("Restore (Defaults to zero)");
break;
case ROTARY_ENCODER_ALWAYS_ZERO:
restore_mode = LOG_STR("Always zero");
break;
}
ESP_LOGCONFIG(TAG, " Restore Mode: %s", LOG_STR_ARG(restore_mode));
switch (this->store_.resolution) { switch (this->store_.resolution) {
case ROTARY_ENCODER_1_PULSE_PER_CYCLE: case ROTARY_ENCODER_1_PULSE_PER_CYCLE:
ESP_LOGCONFIG(TAG, " Resolution: 1 Pulse Per Cycle"); ESP_LOGCONFIG(TAG, " Resolution: 1 Pulse Per Cycle");
@ -190,6 +218,9 @@ void RotaryEncoderSensor::loop() {
} }
int counter = this->store_.counter; int counter = this->store_.counter;
if (this->store_.last_read != counter || this->publish_initial_value_) { if (this->store_.last_read != counter || this->publish_initial_value_) {
if (this->restore_mode_ == ROTARY_ENCODER_RESTORE_DEFAULT_ZERO) {
this->rtc_.save(&counter);
}
this->store_.last_read = counter; this->store_.last_read = counter;
this->publish_state(counter); this->publish_state(counter);
this->publish_initial_value_ = false; this->publish_initial_value_ = false;
@ -197,6 +228,9 @@ void RotaryEncoderSensor::loop() {
} }
float RotaryEncoderSensor::get_setup_priority() const { return setup_priority::DATA; } float RotaryEncoderSensor::get_setup_priority() const { return setup_priority::DATA; }
void RotaryEncoderSensor::set_restore_mode(RotaryEncoderRestoreMode restore_mode) {
this->restore_mode_ = restore_mode;
}
void RotaryEncoderSensor::set_resolution(RotaryEncoderResolution mode) { this->store_.resolution = mode; } void RotaryEncoderSensor::set_resolution(RotaryEncoderResolution mode) { this->store_.resolution = mode; }
void RotaryEncoderSensor::set_min_value(int32_t min_value) { this->store_.min_value = min_value; } void RotaryEncoderSensor::set_min_value(int32_t min_value) { this->store_.min_value = min_value; }
void RotaryEncoderSensor::set_max_value(int32_t max_value) { this->store_.max_value = max_value; } void RotaryEncoderSensor::set_max_value(int32_t max_value) { this->store_.max_value = max_value; }

View file

@ -10,6 +10,12 @@
namespace esphome { namespace esphome {
namespace rotary_encoder { namespace rotary_encoder {
/// All possible restore modes for the rotary encoder
enum RotaryEncoderRestoreMode {
ROTARY_ENCODER_RESTORE_DEFAULT_ZERO, /// try to restore counter, otherwise set to zero
ROTARY_ENCODER_ALWAYS_ZERO, /// do not restore counter, always set to zero
};
/// All possible resolutions for the rotary encoder /// All possible resolutions for the rotary encoder
enum RotaryEncoderResolution { enum RotaryEncoderResolution {
ROTARY_ENCODER_1_PULSE_PER_CYCLE = ROTARY_ENCODER_1_PULSE_PER_CYCLE =
@ -40,6 +46,15 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component {
void set_pin_a(InternalGPIOPin *pin_a) { pin_a_ = pin_a; } void set_pin_a(InternalGPIOPin *pin_a) { pin_a_ = pin_a; }
void set_pin_b(InternalGPIOPin *pin_b) { pin_b_ = pin_b; } void set_pin_b(InternalGPIOPin *pin_b) { pin_b_ = pin_b; }
/** Set the restore mode of the rotary encoder.
*
* By default (if possible) the last known counter state is restored. Otherwise the value 0 is used.
* Restoring the state can also be turned off.
*
* @param restore_mode The restore mode to use.
*/
void set_restore_mode(RotaryEncoderRestoreMode restore_mode);
/** Set the resolution of the rotary encoder. /** Set the resolution of the rotary encoder.
* *
* By default, this component will increment the counter by 1 with every A-B input cycle. * By default, this component will increment the counter by 1 with every A-B input cycle.
@ -81,6 +96,8 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component {
InternalGPIOPin *pin_b_; InternalGPIOPin *pin_b_;
GPIOPin *pin_i_{nullptr}; /// Index pin, if this is not nullptr, the counter will reset to 0 once this pin is HIGH. GPIOPin *pin_i_{nullptr}; /// Index pin, if this is not nullptr, the counter will reset to 0 once this pin is HIGH.
bool publish_initial_value_; bool publish_initial_value_;
ESPPreferenceObject rtc_;
RotaryEncoderRestoreMode restore_mode_{ROTARY_ENCODER_RESTORE_DEFAULT_ZERO};
RotaryEncoderSensorStore store_{}; RotaryEncoderSensorStore store_{};

View file

@ -14,9 +14,17 @@ from esphome.const import (
CONF_PIN_A, CONF_PIN_A,
CONF_PIN_B, CONF_PIN_B,
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
CONF_RESTORE_MODE,
) )
rotary_encoder_ns = cg.esphome_ns.namespace("rotary_encoder") rotary_encoder_ns = cg.esphome_ns.namespace("rotary_encoder")
RotaryEncoderRestoreMode = rotary_encoder_ns.enum("RotaryEncoderRestoreMode")
RESTORE_MODES = {
"RESTORE_DEFAULT_ZERO": RotaryEncoderRestoreMode.ROTARY_ENCODER_RESTORE_DEFAULT_ZERO,
"ALWAYS_ZERO": RotaryEncoderRestoreMode.ROTARY_ENCODER_ALWAYS_ZERO,
}
RotaryEncoderResolution = rotary_encoder_ns.enum("RotaryEncoderResolution") RotaryEncoderResolution = rotary_encoder_ns.enum("RotaryEncoderResolution")
RESOLUTIONS = { RESOLUTIONS = {
1: RotaryEncoderResolution.ROTARY_ENCODER_1_PULSE_PER_CYCLE, 1: RotaryEncoderResolution.ROTARY_ENCODER_1_PULSE_PER_CYCLE,
@ -72,6 +80,9 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_MIN_VALUE): cv.int_, cv.Optional(CONF_MIN_VALUE): cv.int_,
cv.Optional(CONF_MAX_VALUE): cv.int_, cv.Optional(CONF_MAX_VALUE): cv.int_,
cv.Optional(CONF_PUBLISH_INITIAL_VALUE, default=False): cv.boolean, cv.Optional(CONF_PUBLISH_INITIAL_VALUE, default=False): cv.boolean,
cv.Optional(CONF_RESTORE_MODE, default="RESTORE_DEFAULT_ZERO"): cv.enum(
RESTORE_MODES, upper=True, space="_"
),
cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation( cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation(
{ {
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
@ -102,6 +113,7 @@ async def to_code(config):
pin_b = await cg.gpio_pin_expression(config[CONF_PIN_B]) pin_b = await cg.gpio_pin_expression(config[CONF_PIN_B])
cg.add(var.set_pin_b(pin_b)) cg.add(var.set_pin_b(pin_b))
cg.add(var.set_publish_initial_value(config[CONF_PUBLISH_INITIAL_VALUE])) cg.add(var.set_publish_initial_value(config[CONF_PUBLISH_INITIAL_VALUE]))
cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE]))
if CONF_PIN_RESET in config: if CONF_PIN_RESET in config:
pin_i = await cg.gpio_pin_expression(config[CONF_PIN_RESET]) pin_i = await cg.gpio_pin_expression(config[CONF_PIN_RESET])