mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	mpr121: Add GPIO support (#6776)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -1,19 +1,32 @@ | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
|  | import esphome.final_validate as fv | ||||||
|  | from esphome import pins | ||||||
| from esphome.components import i2c | from esphome.components import i2c | ||||||
| from esphome.const import CONF_ID | from esphome.const import ( | ||||||
|  |     CONF_BINARY_SENSOR, | ||||||
|  |     CONF_CHANNEL, | ||||||
|  |     CONF_ID, | ||||||
|  |     CONF_INPUT, | ||||||
|  |     CONF_INVERTED, | ||||||
|  |     CONF_MODE, | ||||||
|  |     CONF_NUMBER, | ||||||
|  |     CONF_OUTPUT, | ||||||
|  | ) | ||||||
|  |  | ||||||
| CONF_TOUCH_THRESHOLD = "touch_threshold" | CONF_TOUCH_THRESHOLD = "touch_threshold" | ||||||
| CONF_RELEASE_THRESHOLD = "release_threshold" | CONF_RELEASE_THRESHOLD = "release_threshold" | ||||||
| CONF_TOUCH_DEBOUNCE = "touch_debounce" | CONF_TOUCH_DEBOUNCE = "touch_debounce" | ||||||
| CONF_RELEASE_DEBOUNCE = "release_debounce" | CONF_RELEASE_DEBOUNCE = "release_debounce" | ||||||
|  | CONF_MAX_TOUCH_CHANNEL = "max_touch_channel" | ||||||
|  | CONF_MPR121 = "mpr121" | ||||||
|  | CONF_MPR121_ID = "mpr121_id" | ||||||
|  |  | ||||||
| DEPENDENCIES = ["i2c"] | DEPENDENCIES = ["i2c"] | ||||||
| AUTO_LOAD = ["binary_sensor"] |  | ||||||
|  |  | ||||||
| mpr121_ns = cg.esphome_ns.namespace("mpr121") | mpr121_ns = cg.esphome_ns.namespace("mpr121") | ||||||
| CONF_MPR121_ID = "mpr121_id" |  | ||||||
| MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice) | MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice) | ||||||
|  | MPR121GPIOPin = mpr121_ns.class_("MPR121GPIOPin", cg.GPIOPin) | ||||||
|  |  | ||||||
| MULTI_CONF = True | MULTI_CONF = True | ||||||
| CONFIG_SCHEMA = ( | CONFIG_SCHEMA = ( | ||||||
| @@ -28,6 +41,7 @@ CONFIG_SCHEMA = ( | |||||||
|             cv.Optional(CONF_RELEASE_THRESHOLD, default=0x06): cv.int_range( |             cv.Optional(CONF_RELEASE_THRESHOLD, default=0x06): cv.int_range( | ||||||
|                 min=0x05, max=0x30 |                 min=0x05, max=0x30 | ||||||
|             ), |             ), | ||||||
|  |             cv.Optional(CONF_MAX_TOUCH_CHANNEL): cv.int_range(min=3, max=11), | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     .extend(cv.COMPONENT_SCHEMA) |     .extend(cv.COMPONENT_SCHEMA) | ||||||
| @@ -35,11 +49,79 @@ CONFIG_SCHEMA = ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _final_validate(config): | ||||||
|  |     fconf = fv.full_config.get() | ||||||
|  |     max_touch_channel = 3 | ||||||
|  |     if (binary_sensors := fconf.get(CONF_BINARY_SENSOR)) is not None: | ||||||
|  |         for binary_sensor in binary_sensors: | ||||||
|  |             if binary_sensor.get(CONF_MPR121_ID) == config[CONF_ID]: | ||||||
|  |                 max_touch_channel = max(max_touch_channel, binary_sensor[CONF_CHANNEL]) | ||||||
|  |     if max_touch_channel_in_config := config.get(CONF_MAX_TOUCH_CHANNEL): | ||||||
|  |         if max_touch_channel != max_touch_channel_in_config: | ||||||
|  |             raise cv.Invalid( | ||||||
|  |                 "Max touch channel must equal the highest binary sensor channel or be removed for auto calculation", | ||||||
|  |                 path=[CONF_MAX_TOUCH_CHANNEL], | ||||||
|  |             ) | ||||||
|  |     path = fconf.get_path_for_id(config[CONF_ID])[:-1] | ||||||
|  |     this_config = fconf.get_config_for_path(path) | ||||||
|  |     this_config[CONF_MAX_TOUCH_CHANNEL] = max_touch_channel | ||||||
|  |  | ||||||
|  |  | ||||||
|  | FINAL_VALIDATE_SCHEMA = _final_validate | ||||||
|  |  | ||||||
|  |  | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     cg.add(var.set_touch_debounce(config[CONF_TOUCH_DEBOUNCE])) |     cg.add(var.set_touch_debounce(config[CONF_TOUCH_DEBOUNCE])) | ||||||
|     cg.add(var.set_release_debounce(config[CONF_RELEASE_DEBOUNCE])) |     cg.add(var.set_release_debounce(config[CONF_RELEASE_DEBOUNCE])) | ||||||
|     cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) |     cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) | ||||||
|     cg.add(var.set_release_threshold(config[CONF_RELEASE_THRESHOLD])) |     cg.add(var.set_release_threshold(config[CONF_RELEASE_THRESHOLD])) | ||||||
|  |     cg.add(var.set_max_touch_channel(config[CONF_MAX_TOUCH_CHANNEL])) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|     await i2c.register_i2c_device(var, config) |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_mode(value): | ||||||
|  |     if bool(value[CONF_INPUT]) == bool(value[CONF_OUTPUT]): | ||||||
|  |         raise cv.Invalid("Mode must be either input or output") | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # https://www.nxp.com/docs/en/data-sheet/MPR121.pdf, page 4 | ||||||
|  | # | ||||||
|  | # Among the 12 electrode inputs, 8 inputs are designed as multifunctional pins. When these pins are | ||||||
|  | # not configured as electrodes, they may be used to drive LEDs or used for general purpose input or | ||||||
|  | # output. | ||||||
|  | MPR121_GPIO_PIN_SCHEMA = pins.gpio_base_schema( | ||||||
|  |     MPR121GPIOPin, | ||||||
|  |     cv.int_range(min=4, max=11), | ||||||
|  |     modes=[CONF_INPUT, CONF_OUTPUT], | ||||||
|  |     mode_validator=validate_mode, | ||||||
|  | ).extend( | ||||||
|  |     { | ||||||
|  |         cv.Required(CONF_MPR121): cv.use_id(MPR121Component), | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def mpr121_pin_final_validate(pin_config, parent_config): | ||||||
|  |     if pin_config[CONF_NUMBER] <= parent_config[CONF_MAX_TOUCH_CHANNEL]: | ||||||
|  |         raise cv.Invalid( | ||||||
|  |             "Pin number must be higher than the max touch channel of the MPR121 component", | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pins.PIN_SCHEMA_REGISTRY.register( | ||||||
|  |     CONF_MPR121, MPR121_GPIO_PIN_SCHEMA, mpr121_pin_final_validate | ||||||
|  | ) | ||||||
|  | async def mpr121_gpio_pin_to_code(config): | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     parent = await cg.get_variable(config[CONF_MPR121]) | ||||||
|  |  | ||||||
|  |     cg.add(var.set_parent(parent)) | ||||||
|  |  | ||||||
|  |     num = config[CONF_NUMBER] | ||||||
|  |     cg.add(var.set_pin(num)) | ||||||
|  |     cg.add(var.set_inverted(config[CONF_INVERTED])) | ||||||
|  |     cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE]))) | ||||||
|  |     return var | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | |||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import binary_sensor | from esphome.components import binary_sensor | ||||||
| from esphome.const import CONF_CHANNEL | from esphome.const import CONF_CHANNEL | ||||||
| from . import ( | from .. import ( | ||||||
|     mpr121_ns, |     mpr121_ns, | ||||||
|     MPR121Component, |     MPR121Component, | ||||||
|     CONF_MPR121_ID, |     CONF_MPR121_ID, | ||||||
| @@ -11,9 +11,9 @@ from . import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| DEPENDENCIES = ["mpr121"] | DEPENDENCIES = ["mpr121"] | ||||||
| MPR121Channel = mpr121_ns.class_("MPR121Channel", binary_sensor.BinarySensor) | MPR121BinarySensor = mpr121_ns.class_("MPR121BinarySensor", binary_sensor.BinarySensor) | ||||||
| 
 | 
 | ||||||
| CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(MPR121Channel).extend( | CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(MPR121BinarySensor).extend( | ||||||
|     { |     { | ||||||
|         cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component), |         cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component), | ||||||
|         cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11), |         cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11), | ||||||
| @@ -27,6 +27,7 @@ async def to_code(config): | |||||||
|     var = await binary_sensor.new_binary_sensor(config) |     var = await binary_sensor.new_binary_sensor(config) | ||||||
|     hub = await cg.get_variable(config[CONF_MPR121_ID]) |     hub = await cg.get_variable(config[CONF_MPR121_ID]) | ||||||
|     cg.add(var.set_channel(config[CONF_CHANNEL])) |     cg.add(var.set_channel(config[CONF_CHANNEL])) | ||||||
|  |     cg.register_parented(var, hub) | ||||||
| 
 | 
 | ||||||
|     if CONF_TOUCH_THRESHOLD in config: |     if CONF_TOUCH_THRESHOLD in config: | ||||||
|         cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) |         cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD])) | ||||||
| @@ -0,0 +1,20 @@ | |||||||
|  | #include "mpr121_binary_sensor.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mpr121 { | ||||||
|  |  | ||||||
|  | void MPR121BinarySensor::setup() { | ||||||
|  |   uint8_t touch_threshold = this->touch_threshold_.value_or(this->parent_->get_touch_threshold()); | ||||||
|  |   this->parent_->write_byte(MPR121_TOUCHTH_0 + 2 * this->channel_, touch_threshold); | ||||||
|  |  | ||||||
|  |   uint8_t release_threshold = this->release_threshold_.value_or(this->parent_->get_release_threshold()); | ||||||
|  |   this->parent_->write_byte(MPR121_RELEASETH_0 + 2 * this->channel_, release_threshold); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MPR121BinarySensor::process(uint16_t data) { | ||||||
|  |   bool new_state = data & (1 << this->channel_); | ||||||
|  |   this->publish_state(new_state); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace mpr121 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,26 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/binary_sensor/binary_sensor.h" | ||||||
|  |  | ||||||
|  | #include "../mpr121.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mpr121 { | ||||||
|  |  | ||||||
|  | class MPR121BinarySensor : public binary_sensor::BinarySensor, public MPR121Channel, public Parented<MPR121Component> { | ||||||
|  |  public: | ||||||
|  |   void set_channel(uint8_t channel) { this->channel_ = channel; } | ||||||
|  |   void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; | ||||||
|  |   void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; | ||||||
|  |  | ||||||
|  |   void setup() override; | ||||||
|  |   void process(uint16_t data) override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   uint8_t channel_{0}; | ||||||
|  |   optional<uint8_t> touch_threshold_{}; | ||||||
|  |   optional<uint8_t> release_threshold_{}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace mpr121 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -1,6 +1,9 @@ | |||||||
| #include "mpr121.h" | #include "mpr121.h" | ||||||
| #include "esphome/core/log.h" |  | ||||||
|  | #include <cstdint> | ||||||
|  |  | ||||||
| #include "esphome/core/hal.h" | #include "esphome/core/hal.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace mpr121 { | namespace mpr121 { | ||||||
| @@ -20,10 +23,7 @@ void MPR121Component::setup() { | |||||||
|  |  | ||||||
|   // set touch sensitivity for all 12 channels |   // set touch sensitivity for all 12 channels | ||||||
|   for (auto *channel : this->channels_) { |   for (auto *channel : this->channels_) { | ||||||
|     this->write_byte(MPR121_TOUCHTH_0 + 2 * channel->channel_, |     channel->setup(); | ||||||
|                      channel->touch_threshold_.value_or(this->touch_threshold_)); |  | ||||||
|     this->write_byte(MPR121_RELEASETH_0 + 2 * channel->channel_, |  | ||||||
|                      channel->release_threshold_.value_or(this->release_threshold_)); |  | ||||||
|   } |   } | ||||||
|   this->write_byte(MPR121_MHDR, 0x01); |   this->write_byte(MPR121_MHDR, 0x01); | ||||||
|   this->write_byte(MPR121_NHDR, 0x01); |   this->write_byte(MPR121_NHDR, 0x01); | ||||||
| @@ -44,8 +44,15 @@ void MPR121Component::setup() { | |||||||
|   this->write_byte(MPR121_CONFIG1, 0x10); |   this->write_byte(MPR121_CONFIG1, 0x10); | ||||||
|   // 0.5uS encoding, 1ms period |   // 0.5uS encoding, 1ms period | ||||||
|   this->write_byte(MPR121_CONFIG2, 0x20); |   this->write_byte(MPR121_CONFIG2, 0x20); | ||||||
|   // start with first 5 bits of baseline tracking |  | ||||||
|   this->write_byte(MPR121_ECR, 0x8F); |   // Write the Electrode Configuration Register | ||||||
|  |   // * Highest 2 bits is "Calibration Lock", which we set to a value corresponding to 5 bits. | ||||||
|  |   // * The 2 bits below is "Proximity Enable" and are left at 0. | ||||||
|  |   // * The 4 least significant bits control how many electrodes are enabled. Electrodes are enabled | ||||||
|  |   //   as a range, starting at 0 up to the highest channel index used. | ||||||
|  |   this->write_byte(MPR121_ECR, 0x80 | (this->max_touch_channel_ + 1)); | ||||||
|  |  | ||||||
|  |   this->flush_gpio_(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void MPR121Component::set_touch_debounce(uint8_t debounce) { | void MPR121Component::set_touch_debounce(uint8_t debounce) { | ||||||
| @@ -86,6 +93,72 @@ void MPR121Component::loop() { | |||||||
|  |  | ||||||
|   for (auto *channel : this->channels_) |   for (auto *channel : this->channels_) | ||||||
|     channel->process(val); |     channel->process(val); | ||||||
|  |  | ||||||
|  |   this->read_byte(MPR121_GPIODATA, &this->gpio_input_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MPR121Component::digital_read(uint8_t ionum) { return (this->gpio_input_ & (1 << ionum)) != 0; } | ||||||
|  |  | ||||||
|  | void MPR121Component::digital_write(uint8_t ionum, bool value) { | ||||||
|  |   if (value) { | ||||||
|  |     this->gpio_output_ |= (1 << ionum); | ||||||
|  |   } else { | ||||||
|  |     this->gpio_output_ &= ~(1 << ionum); | ||||||
|  |   } | ||||||
|  |   this->flush_gpio_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MPR121Component::pin_mode(uint8_t ionum, gpio::Flags flags) { | ||||||
|  |   this->gpio_enable_ |= (1 << ionum); | ||||||
|  |   if (flags & gpio::FLAG_INPUT) { | ||||||
|  |     this->gpio_direction_ &= ~(1 << ionum); | ||||||
|  |   } else if (flags & gpio::FLAG_OUTPUT) { | ||||||
|  |     this->gpio_direction_ |= 1 << ionum; | ||||||
|  |   } | ||||||
|  |   this->flush_gpio_(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MPR121Component::flush_gpio_() { | ||||||
|  |   if (this->is_failed()) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // TODO: The CTL registers can configure internal pullup/pulldown resistors. | ||||||
|  |   this->write_byte(MPR121_GPIOCTL0, 0x00); | ||||||
|  |   this->write_byte(MPR121_GPIOCTL1, 0x00); | ||||||
|  |   this->write_byte(MPR121_GPIOEN, this->gpio_enable_); | ||||||
|  |   this->write_byte(MPR121_GPIODIR, this->gpio_direction_); | ||||||
|  |  | ||||||
|  |   if (!this->write_byte(MPR121_GPIODATA, this->gpio_output_)) { | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   this->status_clear_warning(); | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MPR121GPIOPin::setup() { this->pin_mode(this->flags_); } | ||||||
|  |  | ||||||
|  | void MPR121GPIOPin::pin_mode(gpio::Flags flags) { | ||||||
|  |   assert(this->pin_ >= 4); | ||||||
|  |   this->parent_->pin_mode(this->pin_ - 4, flags); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool MPR121GPIOPin::digital_read() { | ||||||
|  |   assert(this->pin_ >= 4); | ||||||
|  |   return this->parent_->digital_read(this->pin_ - 4) != this->inverted_; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MPR121GPIOPin::digital_write(bool value) { | ||||||
|  |   assert(this->pin_ >= 4); | ||||||
|  |   this->parent_->digital_write(this->pin_ - 4, value != this->inverted_); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string MPR121GPIOPin::dump_summary() const { | ||||||
|  |   char buffer[32]; | ||||||
|  |   snprintf(buffer, sizeof(buffer), "ELE%u on MPR121", this->pin_); | ||||||
|  |   return buffer; | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace mpr121 | }  // namespace mpr121 | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/defines.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  |  | ||||||
| #include "esphome/components/i2c/i2c.h" | #include "esphome/components/i2c/i2c.h" | ||||||
| #include "esphome/components/binary_sensor/binary_sensor.h" |  | ||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| @@ -39,6 +41,9 @@ enum { | |||||||
|   MPR121_UPLIMIT = 0x7D, |   MPR121_UPLIMIT = 0x7D, | ||||||
|   MPR121_LOWLIMIT = 0x7E, |   MPR121_LOWLIMIT = 0x7E, | ||||||
|   MPR121_TARGETLIMIT = 0x7F, |   MPR121_TARGETLIMIT = 0x7F, | ||||||
|  |   MPR121_GPIOCTL0 = 0x73, | ||||||
|  |   MPR121_GPIOCTL1 = 0x74, | ||||||
|  |   MPR121_GPIODATA = 0x75, | ||||||
|   MPR121_GPIODIR = 0x76, |   MPR121_GPIODIR = 0x76, | ||||||
|   MPR121_GPIOEN = 0x77, |   MPR121_GPIOEN = 0x77, | ||||||
|   MPR121_GPIOSET = 0x78, |   MPR121_GPIOSET = 0x78, | ||||||
| @@ -47,19 +52,10 @@ enum { | |||||||
|   MPR121_SOFTRESET = 0x80, |   MPR121_SOFTRESET = 0x80, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class MPR121Channel : public binary_sensor::BinarySensor { | class MPR121Channel { | ||||||
|   friend class MPR121Component; |  | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   void set_channel(uint8_t channel) { channel_ = channel; } |   virtual void setup() = 0; | ||||||
|   void process(uint16_t data) { this->publish_state(static_cast<bool>(data & (1 << this->channel_))); } |   virtual void process(uint16_t data) = 0; | ||||||
|   void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; |  | ||||||
|   void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; |  | ||||||
|  |  | ||||||
|  protected: |  | ||||||
|   uint8_t channel_{0}; |  | ||||||
|   optional<uint8_t> touch_threshold_{}; |  | ||||||
|   optional<uint8_t> release_threshold_{}; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| class MPR121Component : public Component, public i2c::I2CDevice { | class MPR121Component : public Component, public i2c::I2CDevice { | ||||||
| @@ -69,23 +65,63 @@ class MPR121Component : public Component, public i2c::I2CDevice { | |||||||
|   void set_release_debounce(uint8_t debounce); |   void set_release_debounce(uint8_t debounce); | ||||||
|   void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; |   void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; }; | ||||||
|   void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; |   void set_release_threshold(uint8_t release_threshold) { this->release_threshold_ = release_threshold; }; | ||||||
|   uint8_t get_touch_threshold() { return this->touch_threshold_; }; |   uint8_t get_touch_threshold() const { return this->touch_threshold_; }; | ||||||
|   uint8_t get_release_threshold() { return this->release_threshold_; }; |   uint8_t get_release_threshold() const { return this->release_threshold_; }; | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
|   float get_setup_priority() const override { return setup_priority::DATA; } |   float get_setup_priority() const override { return setup_priority::IO; } | ||||||
|   void loop() override; |   void loop() override; | ||||||
|  |  | ||||||
|  |   void set_max_touch_channel(uint8_t max_touch_channel) { this->max_touch_channel_ = max_touch_channel; } | ||||||
|  |  | ||||||
|  |   // GPIO helper functions. | ||||||
|  |   bool digital_read(uint8_t ionum); | ||||||
|  |   void digital_write(uint8_t ionum, bool value); | ||||||
|  |   void pin_mode(uint8_t ionum, gpio::Flags flags); | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   std::vector<MPR121Channel *> channels_{}; |   std::vector<MPR121Channel *> channels_{}; | ||||||
|   uint8_t debounce_{0}; |   uint8_t debounce_{0}; | ||||||
|   uint8_t touch_threshold_{}; |   uint8_t touch_threshold_{}; | ||||||
|   uint8_t release_threshold_{}; |   uint8_t release_threshold_{}; | ||||||
|  |   uint8_t max_touch_channel_{3}; | ||||||
|   enum ErrorCode { |   enum ErrorCode { | ||||||
|     NONE = 0, |     NONE = 0, | ||||||
|     COMMUNICATION_FAILED, |     COMMUNICATION_FAILED, | ||||||
|     WRONG_CHIP_STATE, |     WRONG_CHIP_STATE, | ||||||
|   } error_code_{NONE}; |   } error_code_{NONE}; | ||||||
|  |  | ||||||
|  |   bool flush_gpio_(); | ||||||
|  |  | ||||||
|  |   /// The enable mask - zero means high Z, 1 means GPIO usage | ||||||
|  |   uint8_t gpio_enable_{0x00}; | ||||||
|  |   /// Mask for the pin mode - 1 means output, 0 means input | ||||||
|  |   uint8_t gpio_direction_{0x00}; | ||||||
|  |   /// The mask to write as output state - 1 means HIGH, 0 means LOW | ||||||
|  |   uint8_t gpio_output_{0x00}; | ||||||
|  |   /// The mask to read as input state - 1 means HIGH, 0 means LOW | ||||||
|  |   uint8_t gpio_input_{0x00}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Helper class to expose a MPR121 pin as an internal input GPIO pin. | ||||||
|  | class MPR121GPIOPin : public GPIOPin { | ||||||
|  |  public: | ||||||
|  |   void setup() override; | ||||||
|  |   void pin_mode(gpio::Flags flags) override; | ||||||
|  |   bool digital_read() override; | ||||||
|  |   void digital_write(bool value) override; | ||||||
|  |   std::string dump_summary() const override; | ||||||
|  |  | ||||||
|  |   void set_parent(MPR121Component *parent) { this->parent_ = parent; } | ||||||
|  |   void set_pin(uint8_t pin) { this->pin_ = pin; } | ||||||
|  |   void set_inverted(bool inverted) { this->inverted_ = inverted; } | ||||||
|  |   void set_flags(gpio::Flags flags) { this->flags_ = flags; } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   MPR121Component *parent_; | ||||||
|  |   uint8_t pin_; | ||||||
|  |   bool inverted_; | ||||||
|  |   gpio::Flags flags_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace mpr121 | }  // namespace mpr121 | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								tests/components/mpr121/common.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								tests/components/mpr121/common.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | i2c: | ||||||
|  |   - id: i2c_mpr121 | ||||||
|  |     scl: ${i2c_scl} | ||||||
|  |     sda: ${i2c_sda} | ||||||
|  |  | ||||||
|  | mpr121: | ||||||
|  |   id: mpr121_first | ||||||
|  |   address: 0x5A | ||||||
|  |  | ||||||
|  | binary_sensor: | ||||||
|  |   - platform: mpr121 | ||||||
|  |     id: touchkey0 | ||||||
|  |     name: touchkey0 | ||||||
|  |     channel: 0 | ||||||
|  |   - platform: mpr121 | ||||||
|  |     id: bin1 | ||||||
|  |     name: touchkey1 | ||||||
|  |     channel: 1 | ||||||
|  |   - platform: mpr121 | ||||||
|  |     id: bin2 | ||||||
|  |     name: touchkey2 | ||||||
|  |     channel: 2 | ||||||
|  |   - platform: mpr121 | ||||||
|  |     id: bin3 | ||||||
|  |     name: touchkey3 | ||||||
|  |     channel: 6 | ||||||
|  |  | ||||||
|  | output: | ||||||
|  |   - platform: gpio | ||||||
|  |     id: gpio1 | ||||||
|  |     pin: | ||||||
|  |       mpr121: mpr121_first | ||||||
|  |       number: 7 | ||||||
|  |       mode: OUTPUT | ||||||
|  |   - platform: gpio | ||||||
|  |     id: gpio2 | ||||||
|  |     pin: | ||||||
|  |       mpr121: mpr121_first | ||||||
|  |       number: 11 | ||||||
|  |       mode: OUTPUT | ||||||
|  |       inverted: true | ||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO5 | ||||||
|     scl: 5 |   i2c_sda: GPIO4 | ||||||
|     sda: 4 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO5 | ||||||
|     scl: 5 |   i2c_sda: GPIO4 | ||||||
|     sda: 4 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO16 | ||||||
|     scl: 16 |   i2c_sda: GPIO17 | ||||||
|     sda: 17 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO16 | ||||||
|     scl: 16 |   i2c_sda: GPIO17 | ||||||
|     sda: 17 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO5 | ||||||
|     scl: 5 |   i2c_sda: GPIO4 | ||||||
|     sda: 4 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -1,26 +1,5 @@ | |||||||
| i2c: | substitutions: | ||||||
|   - id: i2c_mpr121 |   i2c_scl: GPIO5 | ||||||
|     scl: 5 |   i2c_sda: GPIO4 | ||||||
|     sda: 4 |  | ||||||
|  |  | ||||||
| mpr121: | <<: !include common.yaml | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     name: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     channel: 1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     channel: 2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: bin3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     channel: 3 |  | ||||||
|   | |||||||
| @@ -344,10 +344,6 @@ apds9960: | |||||||
|   address: 0x20 |   address: 0x20 | ||||||
|   update_interval: 60s |   update_interval: 60s | ||||||
|  |  | ||||||
| mpr121: |  | ||||||
|   id: mpr121_first |  | ||||||
|   address: 0x5A |  | ||||||
|  |  | ||||||
| binary_sensor: | binary_sensor: | ||||||
|   - platform: apds9960 |   - platform: apds9960 | ||||||
|     direction: up |     direction: up | ||||||
| @@ -371,25 +367,6 @@ binary_sensor: | |||||||
|     direction: right |     direction: right | ||||||
|     name: APDS9960 Right |     name: APDS9960 Right | ||||||
|  |  | ||||||
|   - platform: mpr121 |  | ||||||
|     id: touchkey0 |  | ||||||
|     channel: 0 |  | ||||||
|     name: touchkey0 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     channel: 1 |  | ||||||
|     name: touchkey1 |  | ||||||
|     id: bin1 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     channel: 2 |  | ||||||
|     name: touchkey2 |  | ||||||
|     id: bin2 |  | ||||||
|   - platform: mpr121 |  | ||||||
|     channel: 3 |  | ||||||
|     name: touchkey3 |  | ||||||
|     id: bin3 |  | ||||||
|     on_press: |  | ||||||
|       then: |  | ||||||
|         - switch.toggle: mpr121_toggle |  | ||||||
|   - platform: ttp229_lsf |   - platform: ttp229_lsf | ||||||
|     channel: 1 |     channel: 1 | ||||||
|     name: TTP229 LSF Test |     name: TTP229 LSF Test | ||||||
| @@ -443,10 +420,6 @@ grove_tb6612fng: | |||||||
|   address: 0x14 |   address: 0x14 | ||||||
|  |  | ||||||
| switch: | switch: | ||||||
|   - platform: template |  | ||||||
|     name: mpr121_toggle |  | ||||||
|     id: mpr121_toggle |  | ||||||
|     optimistic: true |  | ||||||
|   - platform: gpio |   - platform: gpio | ||||||
|     id: gpio_switch1 |     id: gpio_switch1 | ||||||
|     pin: |     pin: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user