mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 01:07:45 +01:00
CAP1188 Capacitive Touch Sensor Support (#2653)
This commit is contained in:
parent
662773b075
commit
710866ff4e
6 changed files with 233 additions and 0 deletions
|
@ -31,6 +31,7 @@ esphome/components/binary_sensor/* @esphome/core
|
|||
esphome/components/ble_client/* @buxtronix
|
||||
esphome/components/bme680_bsec/* @trvrnrth
|
||||
esphome/components/canbus/* @danielschramm @mvturnho
|
||||
esphome/components/cap1188/* @MrEditor97
|
||||
esphome/components/captive_portal/* @OttoWinter
|
||||
esphome/components/ccs811/* @habbie
|
||||
esphome/components/climate/* @esphome/core
|
||||
|
|
45
esphome/components/cap1188/__init__.py
Normal file
45
esphome/components/cap1188/__init__.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID, CONF_RESET_PIN
|
||||
from esphome import pins
|
||||
|
||||
CONF_TOUCH_THRESHOLD = "touch_threshold"
|
||||
CONF_ALLOW_MULTIPLE_TOUCHES = "allow_multiple_touches"
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
AUTO_LOAD = ["binary_sensor", "output"]
|
||||
CODEOWNERS = ["@MrEditor97"]
|
||||
|
||||
cap1188_ns = cg.esphome_ns.namespace("cap1188")
|
||||
CONF_CAP1188_ID = "cap1188_id"
|
||||
CAP1188Component = cap1188_ns.class_("CAP1188Component", cg.Component, i2c.I2CDevice)
|
||||
|
||||
MULTI_CONF = True
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CAP1188Component),
|
||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_TOUCH_THRESHOLD, default=0x20): cv.int_range(
|
||||
min=0x01, max=0x80
|
||||
),
|
||||
cv.Optional(CONF_ALLOW_MULTIPLE_TOUCHES, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x29))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
cg.add(var.set_touch_threshold(config[CONF_TOUCH_THRESHOLD]))
|
||||
cg.add(var.set_allow_multiple_touches(config[CONF_ALLOW_MULTIPLE_TOUCHES]))
|
||||
|
||||
if CONF_RESET_PIN in config:
|
||||
pin = await cg.gpio_pin_expression(config[CONF_RESET_PIN])
|
||||
cg.add(var.set_reset_pin(pin))
|
||||
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
25
esphome/components/cap1188/binary_sensor.py
Normal file
25
esphome/components/cap1188/binary_sensor.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_CHANNEL, CONF_ID
|
||||
from . import cap1188_ns, CAP1188Component, CONF_CAP1188_ID
|
||||
|
||||
DEPENDENCIES = ["cap1188"]
|
||||
CAP1188Channel = cap1188_ns.class_("CAP1188Channel", binary_sensor.BinarySensor)
|
||||
|
||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(CAP1188Channel),
|
||||
cv.GenerateID(CONF_CAP1188_ID): cv.use_id(CAP1188Component),
|
||||
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await binary_sensor.register_binary_sensor(var, config)
|
||||
hub = await cg.get_variable(config[CONF_CAP1188_ID])
|
||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||
|
||||
cg.add(hub.register_channel(var))
|
88
esphome/components/cap1188/cap1188.cpp
Normal file
88
esphome/components/cap1188/cap1188.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "cap1188.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace cap1188 {
|
||||
|
||||
static const char *const TAG = "cap1188";
|
||||
|
||||
void CAP1188Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up CAP1188...");
|
||||
|
||||
// Reset device using the reset pin
|
||||
if (this->reset_pin_ != nullptr) {
|
||||
this->reset_pin_->setup();
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(100); // NOLINT
|
||||
this->reset_pin_->digital_write(true);
|
||||
delay(100); // NOLINT
|
||||
this->reset_pin_->digital_write(false);
|
||||
delay(100); // NOLINT
|
||||
}
|
||||
|
||||
// Check if CAP1188 is actually connected
|
||||
this->read_byte(CAP1188_PRODUCT_ID, &this->cap1188_product_id_);
|
||||
this->read_byte(CAP1188_MANUFACTURE_ID, &this->cap1188_manufacture_id_);
|
||||
this->read_byte(CAP1188_REVISION, &this->cap1188_revision_);
|
||||
|
||||
if ((this->cap1188_product_id_ != 0x50) || (this->cap1188_manufacture_id_ != 0x5D)) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set sensitivity
|
||||
uint8_t sensitivity = 0;
|
||||
this->read_byte(CAP1188_SENSITVITY, &sensitivity);
|
||||
sensitivity = sensitivity & 0x0f;
|
||||
this->write_byte(CAP1188_SENSITVITY, sensitivity | this->touch_threshold_);
|
||||
|
||||
// Allow multiple touches
|
||||
this->write_byte(CAP1188_MULTI_TOUCH, this->allow_multiple_touches_);
|
||||
|
||||
// Have LEDs follow touches
|
||||
this->write_byte(CAP1188_LED_LINK, 0xFF);
|
||||
|
||||
// Speed up a bit
|
||||
this->write_byte(CAP1188_STAND_BY_CONFIGURATION, 0x30);
|
||||
}
|
||||
|
||||
void CAP1188Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "CAP1188:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Product ID: 0x%x", this->cap1188_product_id_);
|
||||
ESP_LOGCONFIG(TAG, " Manufacture ID: 0x%x", this->cap1188_manufacture_id_);
|
||||
ESP_LOGCONFIG(TAG, " Revision ID: 0x%x", this->cap1188_revision_);
|
||||
|
||||
switch (this->error_code_) {
|
||||
case COMMUNICATION_FAILED:
|
||||
ESP_LOGE(TAG, "Product ID or Manufacture ID of the connected device does not match a known CAP1188.");
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CAP1188Component::loop() {
|
||||
uint8_t touched = 0;
|
||||
|
||||
this->read_register(CAP1188_SENSOR_INPUT_STATUS, &touched, 1);
|
||||
|
||||
if (touched) {
|
||||
uint8_t data = 0;
|
||||
this->read_register(CAP1188_MAIN, &data, 1);
|
||||
data = data & ~CAP1188_MAIN_INT;
|
||||
|
||||
this->write_register(CAP1188_MAIN, &data, 2);
|
||||
}
|
||||
|
||||
for (auto *channel : this->channels_) {
|
||||
channel->process(touched);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cap1188
|
||||
} // namespace esphome
|
68
esphome/components/cap1188/cap1188.h
Normal file
68
esphome/components/cap1188/cap1188.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/output/binary_output.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace cap1188 {
|
||||
|
||||
enum {
|
||||
CAP1188_I2CADDR = 0x29,
|
||||
CAP1188_SENSOR_INPUT_STATUS = 0x3,
|
||||
CAP1188_MULTI_TOUCH = 0x2A,
|
||||
CAP1188_LED_LINK = 0x72,
|
||||
CAP1188_PRODUCT_ID = 0xFD,
|
||||
CAP1188_MANUFACTURE_ID = 0xFE,
|
||||
CAP1188_STAND_BY_CONFIGURATION = 0x41,
|
||||
CAP1188_REVISION = 0xFF,
|
||||
CAP1188_MAIN = 0x00,
|
||||
CAP1188_MAIN_INT = 0x01,
|
||||
CAP1188_LEDPOL = 0x73,
|
||||
CAP1188_INTERUPT_REPEAT = 0x28,
|
||||
CAP1188_SENSITVITY = 0x1f,
|
||||
};
|
||||
|
||||
class CAP1188Channel : public binary_sensor::BinarySensor {
|
||||
public:
|
||||
void set_channel(uint8_t channel) { channel_ = channel; }
|
||||
void process(uint8_t data) { this->publish_state(static_cast<bool>(data & (1 << this->channel_))); }
|
||||
|
||||
protected:
|
||||
uint8_t channel_{0};
|
||||
};
|
||||
|
||||
class CAP1188Component : public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
void register_channel(CAP1188Channel *channel) { this->channels_.push_back(channel); }
|
||||
void set_touch_threshold(uint8_t touch_threshold) { this->touch_threshold_ = touch_threshold; };
|
||||
void set_allow_multiple_touches(bool allow_multiple_touches) {
|
||||
this->allow_multiple_touches_ = allow_multiple_touches ? 0x41 : 0x80;
|
||||
};
|
||||
void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
void loop() override;
|
||||
|
||||
protected:
|
||||
std::vector<CAP1188Channel *> channels_{};
|
||||
uint8_t touch_threshold_{0x20};
|
||||
uint8_t allow_multiple_touches_{0x80};
|
||||
|
||||
GPIOPin *reset_pin_{nullptr};
|
||||
|
||||
uint8_t cap1188_product_id_{0};
|
||||
uint8_t cap1188_manufacture_id_{0};
|
||||
uint8_t cap1188_revision_{0};
|
||||
|
||||
enum ErrorCode {
|
||||
NONE = 0,
|
||||
COMMUNICATION_FAILED,
|
||||
} error_code_{NONE};
|
||||
};
|
||||
|
||||
} // namespace cap1188
|
||||
} // namespace esphome
|
|
@ -504,3 +504,9 @@ interval:
|
|||
|
||||
display:
|
||||
|
||||
cap1188:
|
||||
id: cap1188_component
|
||||
address: 0x29
|
||||
touch_threshold: 0x20
|
||||
allow_multiple_touches: true
|
||||
reset_pin: 14
|
||||
|
|
Loading…
Reference in a new issue