mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add restore_mode to rotary_encoder (#2643)
This commit is contained in:
		| @@ -125,6 +125,22 @@ void IRAM_ATTR HOT RotaryEncoderSensorStore::gpio_intr(RotaryEncoderSensorStore | ||||
|  | ||||
| void RotaryEncoderSensor::setup() { | ||||
|   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->store_.pin_a = this->pin_a_->to_isr(); | ||||
|   this->pin_b_->setup(); | ||||
| @@ -142,6 +158,18 @@ void RotaryEncoderSensor::dump_config() { | ||||
|   LOG_PIN("  Pin A: ", this->pin_a_); | ||||
|   LOG_PIN("  Pin B: ", this->pin_b_); | ||||
|   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) { | ||||
|     case ROTARY_ENCODER_1_PULSE_PER_CYCLE: | ||||
|       ESP_LOGCONFIG(TAG, "  Resolution: 1 Pulse Per Cycle"); | ||||
| @@ -190,6 +218,9 @@ void RotaryEncoderSensor::loop() { | ||||
|   } | ||||
|   int counter = this->store_.counter; | ||||
|   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->publish_state(counter); | ||||
|     this->publish_initial_value_ = false; | ||||
| @@ -197,6 +228,9 @@ void RotaryEncoderSensor::loop() { | ||||
| } | ||||
|  | ||||
| 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_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; } | ||||
|   | ||||
| @@ -10,6 +10,12 @@ | ||||
| namespace esphome { | ||||
| 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 | ||||
| enum RotaryEncoderResolution { | ||||
|   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_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. | ||||
|    * | ||||
|    * 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_; | ||||
|   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_; | ||||
|   ESPPreferenceObject rtc_; | ||||
|   RotaryEncoderRestoreMode restore_mode_{ROTARY_ENCODER_RESTORE_DEFAULT_ZERO}; | ||||
|  | ||||
|   RotaryEncoderSensorStore store_{}; | ||||
|  | ||||
|   | ||||
| @@ -14,9 +14,17 @@ from esphome.const import ( | ||||
|     CONF_PIN_A, | ||||
|     CONF_PIN_B, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_RESTORE_MODE, | ||||
| ) | ||||
|  | ||||
| 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") | ||||
| RESOLUTIONS = { | ||||
|     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_MAX_VALUE): cv.int_, | ||||
|             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.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]) | ||||
|     cg.add(var.set_pin_b(pin_b)) | ||||
|     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: | ||||
|         pin_i = await cg.gpio_pin_expression(config[CONF_PIN_RESET]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user