diff --git a/esphome/components/mcp9808/__init__.py b/esphome/components/mcp9808/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/mcp9808/mcp9808.cpp b/esphome/components/mcp9808/mcp9808.cpp new file mode 100644 index 0000000000..38870b3b00 --- /dev/null +++ b/esphome/components/mcp9808/mcp9808.cpp @@ -0,0 +1,81 @@ +#include "mcp9808.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace mcp9808 { + +static const uint8_t MCP9808_REG_AMBIENT_TEMP = 0x05; +static const uint8_t MCP9808_REG_MANUF_ID = 0x06; +static const uint8_t MCP9808_REG_DEVICE_ID = 0x07; + +static const uint16_t MCP9808_MANUF_ID = 0x0054; +static const uint16_t MCP9808_DEV_ID = 0x0400; + +static const uint8_t MCP9808_AMBIENT_CLEAR_FLAGS = 0x1F; +static const uint8_t MCP9808_AMBIENT_CLEAR_SIGN = 0x0F; +static const uint8_t MCP9808_AMBIENT_TEMP_NEGATIVE = 0x10; + +static const char *TAG = "mcp9808"; + +void MCP9808Sensor::setup() { + ESP_LOGCONFIG(TAG, "Setting up %s...", this->name_.c_str()); + + uint16_t manu; + if (!this->read_byte_16(MCP9808_REG_MANUF_ID, &manu, 0) || manu != MCP9808_MANUF_ID) { + this->mark_failed(); + ESP_LOGE(TAG, "%s manufacuturer id failed, device returned %X", this->name_.c_str(), manu); + return; + } + uint16_t dev_id; + if (!this->read_byte_16(MCP9808_REG_DEVICE_ID, &dev_id, 0) || dev_id != MCP9808_DEV_ID) { + this->mark_failed(); + ESP_LOGE(TAG, "%s device id failed, device returned %X", this->name_.c_str(), dev_id); + return; + } +} +void MCP9808Sensor::dump_config() { + ESP_LOGCONFIG(TAG, "%s:", this->name_.c_str()); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with %s failed!", this->name_.c_str()); + } + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Temperature", this); +} +void MCP9808Sensor::update() { + uint16_t raw_temp; + if (!this->read_byte_16(MCP9808_REG_AMBIENT_TEMP, &raw_temp)) { + this->status_set_warning(); + return; + } + if (raw_temp == 0xFFFF) { + this->status_set_warning(); + return; + } + + float temp = NAN; + uint8_t msb = (uint8_t)((raw_temp & 0xff00) >> 8); + uint8_t lsb = raw_temp & 0x00ff; + + msb = msb & MCP9808_AMBIENT_CLEAR_FLAGS; + + if ((msb & MCP9808_AMBIENT_TEMP_NEGATIVE) == MCP9808_AMBIENT_TEMP_NEGATIVE) { + msb = msb & MCP9808_AMBIENT_CLEAR_SIGN; + temp = (256 - ((uint16_t)(msb) *16 + lsb / 16.0f)) * -1; + } else { + temp = (uint16_t)(msb) *16 + lsb / 16.0f; + } + + if (isnan(temp)) { + this->status_set_warning(); + return; + } + + ESP_LOGD(TAG, "%s: Got temperature=%.4f°C", this->name_.c_str(), temp); + this->publish_state(temp); + this->status_clear_warning(); +} +float MCP9808Sensor::get_setup_priority() const { return setup_priority::DATA; } + +} // namespace mcp9808 +} // namespace esphome diff --git a/esphome/components/mcp9808/mcp9808.h b/esphome/components/mcp9808/mcp9808.h new file mode 100644 index 0000000000..19aa3117c3 --- /dev/null +++ b/esphome/components/mcp9808/mcp9808.h @@ -0,0 +1,20 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome { +namespace mcp9808 { + +class MCP9808Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + + void update() override; +}; + +} // namespace mcp9808 +} // namespace esphome diff --git a/esphome/components/mcp9808/sensor.py b/esphome/components/mcp9808/sensor.py new file mode 100644 index 0000000000..f3d5958840 --- /dev/null +++ b/esphome/components/mcp9808/sensor.py @@ -0,0 +1,21 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import CONF_ID, ICON_THERMOMETER, UNIT_CELSIUS + +DEPENDENCIES = ['i2c'] + +mcp9808_ns = cg.esphome_ns.namespace('mcp9808') +MCP9808Sensor = mcp9808_ns.class_('MCP9808Sensor', sensor.Sensor, cg.PollingComponent, + i2c.I2CDevice) + +CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ + cv.GenerateID(): cv.declare_id(MCP9808Sensor), +}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x18)) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield i2c.register_i2c_device(var, config) + yield sensor.register_sensor(var, config) diff --git a/tests/test1.yaml b/tests/test1.yaml index d53d113d01..732d532bdf 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -757,6 +757,9 @@ sensor: aqi: name: "AQI" calculation_type: "CAQI" + - platform: mcp9808 + name: "MCP9808 Temperature" + update_interval: 15s esp32_touch: setup_mode: False