diff --git a/esphome/components/mcp3008/__init__.py b/esphome/components/mcp3008/__init__.py new file mode 100644 index 0000000000..2196b96a92 --- /dev/null +++ b/esphome/components/mcp3008/__init__.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import spi +from esphome.const import CONF_ID + +DEPENDENCIES = ['spi'] +AUTO_LOAD = ['sensor'] +MULTI_CONF = True + +CONF_MCP3008 = 'mcp3008' + +mcp3008_ns = cg.esphome_ns.namespace('mcp3008') +MCP3008 = mcp3008_ns.class_('MCP3008', cg.Component, spi.SPIDevice) + +CONFIG_SCHEMA = cv.Schema({ + cv.GenerateID(): cv.declare_id(MCP3008), +}).extend(spi.spi_device_schema(CS_PIN_required=True)) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield spi.register_spi_device(var, config) diff --git a/esphome/components/mcp3008/mcp3008.cpp b/esphome/components/mcp3008/mcp3008.cpp new file mode 100644 index 0000000000..70484e8818 --- /dev/null +++ b/esphome/components/mcp3008/mcp3008.cpp @@ -0,0 +1,52 @@ +#include "mcp3008.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace mcp3008 { + +static const char *TAG = "mcp3008"; + +float MCP3008::get_setup_priority() const { return setup_priority::HARDWARE; } + +void MCP3008::setup() { + ESP_LOGCONFIG(TAG, "Setting up mcp3008"); + this->spi_setup(); +} + +void MCP3008::dump_config() { + ESP_LOGCONFIG(TAG, "MCP3008:"); + LOG_PIN(" CS Pin: ", this->cs_); +} + +float MCP3008::read_data_(uint8_t pin) { + byte data_msb = 0; + byte data_lsb = 0; + + byte command = ((0x01 << 7) | // start bit + ((pin & 0x07) << 4)); // channel number + + this->enable(); + + this->transfer_byte(0x01); + data_msb = this->transfer_byte(command) & 0x03; + data_lsb = this->transfer_byte(0x00); + + this->disable(); + + int data = data_msb << 8 | data_lsb; + + return data / 1024.0f; +} + +MCP3008Sensor::MCP3008Sensor(MCP3008 *parent, std::string name, uint8_t pin) + : PollingComponent(1000), parent_(parent), pin_(pin) { + this->set_name(name); +} +void MCP3008Sensor::setup() { LOG_SENSOR("", "Setting up MCP3008 Sensor '%s'...", this); } +void MCP3008Sensor::update() { + float value_v = this->parent_->read_data_(pin_); + this->publish_state(value_v); +} + +} // namespace mcp3008 +} // namespace esphome diff --git a/esphome/components/mcp3008/mcp3008.h b/esphome/components/mcp3008/mcp3008.h new file mode 100644 index 0000000000..594bdc4204 --- /dev/null +++ b/esphome/components/mcp3008/mcp3008.h @@ -0,0 +1,42 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/esphal.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/spi/spi.h" + +namespace esphome { +namespace mcp3008 { + +class MCP3008Sensor; + +class MCP3008 : public Component, + public spi::SPIDevice { // At 3.3V 2MHz is too fast 1.35MHz is about right + public: + MCP3008() = default; + + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + + protected: + float read_data_(uint8_t pin); + + friend class MCP3008Sensor; +}; + +class MCP3008Sensor : public PollingComponent, public sensor::Sensor { + public: + MCP3008Sensor(MCP3008 *parent, std::string name, uint8_t pin); + + void setup() override; + void update() override; + + protected: + MCP3008 *parent_; + uint8_t pin_; +}; + +} // namespace mcp3008 +} // namespace esphome diff --git a/esphome/components/mcp3008/sensor.py b/esphome/components/mcp3008/sensor.py new file mode 100644 index 0000000000..ec7df0429a --- /dev/null +++ b/esphome/components/mcp3008/sensor.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import sensor +from esphome.const import CONF_ID, CONF_NUMBER, CONF_NAME +from . import mcp3008_ns, MCP3008 + +DEPENDENCIES = ['mcp3008'] + +MCP3008Sensor = mcp3008_ns.class_('MCP3008Sensor', sensor.Sensor, cg.PollingComponent) + +CONF_MCP3008_ID = 'mcp3008_id' + +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ + cv.GenerateID(): cv.declare_id(MCP3008Sensor), + cv.GenerateID(CONF_MCP3008_ID): cv.use_id(MCP3008), + cv.Required(CONF_NUMBER): cv.int_, +}).extend(cv.polling_component_schema('1s')) + + +def to_code(config): + parent = yield cg.get_variable(config[CONF_MCP3008_ID]) + var = cg.new_Pvariable(config[CONF_ID], parent, config[CONF_NAME], config[CONF_NUMBER]) + yield cg.register_component(var, config)