mirror of
https://github.com/esphome/esphome.git
synced 2024-11-09 16:57:47 +01:00
Add sensor support: MAX44009 (#3125)
Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
parent
231908fe9f
commit
88fbb0ffbb
6 changed files with 242 additions and 0 deletions
|
@ -94,6 +94,7 @@ esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
|
|||
esphome/components/lock/* @esphome/core
|
||||
esphome/components/logger/* @esphome/core
|
||||
esphome/components/ltr390/* @sjtrny
|
||||
esphome/components/max44009/* @berfenger
|
||||
esphome/components/max7219digit/* @rspaargaren
|
||||
esphome/components/max9611/* @mckaymatthew
|
||||
esphome/components/mcp23008/* @jesserockz
|
||||
|
|
0
esphome/components/max44009/__init__.py
Normal file
0
esphome/components/max44009/__init__.py
Normal file
144
esphome/components/max44009/max44009.cpp
Normal file
144
esphome/components/max44009/max44009.cpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
#include "max44009.h"
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace max44009 {
|
||||
|
||||
static const char *const TAG = "max44009.sensor";
|
||||
|
||||
// REGISTERS
|
||||
static const uint8_t MAX44009_REGISTER_CONFIGURATION = 0x02;
|
||||
static const uint8_t MAX44009_LUX_READING_HIGH = 0x03;
|
||||
static const uint8_t MAX44009_LUX_READING_LOW = 0x04;
|
||||
// CONFIGURATION MASKS
|
||||
static const uint8_t MAX44009_CFG_CONTINUOUS = 0x80;
|
||||
// ERROR CODES
|
||||
static const uint8_t MAX44009_OK = 0;
|
||||
static const uint8_t MAX44009_ERROR_WIRE_REQUEST = -10;
|
||||
static const uint8_t MAX44009_ERROR_OVERFLOW = -20;
|
||||
static const uint8_t MAX44009_ERROR_HIGH_BYTE = -30;
|
||||
static const uint8_t MAX44009_ERROR_LOW_BYTE = -31;
|
||||
|
||||
void MAX44009Sensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up MAX44009...");
|
||||
bool state_ok = false;
|
||||
if (this->mode_ == MAX44009Mode::MAX44009_MODE_LOW_POWER) {
|
||||
state_ok = this->set_low_power_mode();
|
||||
} else if (this->mode_ == MAX44009Mode::MAX44009_MODE_CONTINUOUS) {
|
||||
state_ok = this->set_continuous_mode();
|
||||
} else {
|
||||
/*
|
||||
* Mode AUTO: Set mode depending on update interval
|
||||
* - On low power mode, the IC measures lux intensity only once every 800ms
|
||||
* regardless of integration time
|
||||
* - On continuous mode, the IC continuously measures lux intensity
|
||||
*/
|
||||
if (this->get_update_interval() < 800) {
|
||||
state_ok = this->set_continuous_mode();
|
||||
} else {
|
||||
state_ok = this->set_low_power_mode();
|
||||
}
|
||||
}
|
||||
if (!state_ok)
|
||||
this->mark_failed();
|
||||
}
|
||||
|
||||
void MAX44009Sensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "MAX44009:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Communication with MAX44009 failed!");
|
||||
}
|
||||
}
|
||||
|
||||
float MAX44009Sensor::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
void MAX44009Sensor::update() {
|
||||
// update sensor illuminance value
|
||||
float lux = this->read_illuminance_();
|
||||
if (this->error_ != MAX44009_OK) {
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
} else {
|
||||
this->status_clear_warning();
|
||||
this->publish_state(lux);
|
||||
}
|
||||
}
|
||||
|
||||
float MAX44009Sensor::read_illuminance_() {
|
||||
uint8_t datahigh = this->read_(MAX44009_LUX_READING_HIGH);
|
||||
if (error_ != MAX44009_OK) {
|
||||
this->error_ = MAX44009_ERROR_HIGH_BYTE;
|
||||
return this->error_;
|
||||
}
|
||||
uint8_t datalow = this->read_(MAX44009_LUX_READING_LOW);
|
||||
if (error_ != MAX44009_OK) {
|
||||
this->error_ = MAX44009_ERROR_LOW_BYTE;
|
||||
return this->error_;
|
||||
}
|
||||
uint8_t exponent = datahigh >> 4;
|
||||
if (exponent == 0x0F) {
|
||||
this->error_ = MAX44009_ERROR_OVERFLOW;
|
||||
return this->error_;
|
||||
}
|
||||
|
||||
return this->convert_to_lux_(datahigh, datalow);
|
||||
}
|
||||
|
||||
float MAX44009Sensor::convert_to_lux_(uint8_t data_high, uint8_t data_low) {
|
||||
uint8_t exponent = data_high >> 4;
|
||||
uint32_t mantissa = ((data_high & 0x0F) << 4) + (data_low & 0x0F);
|
||||
return ((0x0001 << exponent) * 0.045) * mantissa;
|
||||
}
|
||||
|
||||
bool MAX44009Sensor::set_continuous_mode() {
|
||||
uint8_t config = this->read_(MAX44009_REGISTER_CONFIGURATION);
|
||||
if (this->error_ == MAX44009_OK) {
|
||||
config |= MAX44009_CFG_CONTINUOUS;
|
||||
this->write_(MAX44009_REGISTER_CONFIGURATION, config);
|
||||
this->status_clear_warning();
|
||||
ESP_LOGV(TAG, "set to continuous mode");
|
||||
return true;
|
||||
} else {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MAX44009Sensor::set_low_power_mode() {
|
||||
uint8_t config = this->read_(MAX44009_REGISTER_CONFIGURATION);
|
||||
if (this->error_ == MAX44009_OK) {
|
||||
config &= ~MAX44009_CFG_CONTINUOUS;
|
||||
this->write_(MAX44009_REGISTER_CONFIGURATION, config);
|
||||
this->status_clear_warning();
|
||||
ESP_LOGV(TAG, "set to low power mode");
|
||||
return true;
|
||||
} else {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MAX44009Sensor::read_(uint8_t reg) {
|
||||
uint8_t data = 0;
|
||||
if (!this->read_byte(reg, &data)) {
|
||||
this->error_ = MAX44009_ERROR_WIRE_REQUEST;
|
||||
} else {
|
||||
this->error_ = MAX44009_OK;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void MAX44009Sensor::write_(uint8_t reg, uint8_t value) {
|
||||
if (!this->write_byte(reg, value)) {
|
||||
this->error_ = MAX44009_ERROR_WIRE_REQUEST;
|
||||
} else {
|
||||
this->error_ = MAX44009_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void MAX44009Sensor::set_mode(MAX44009Mode mode) { this->mode_ = mode; }
|
||||
|
||||
} // namespace max44009
|
||||
} // namespace esphome
|
37
esphome/components/max44009/max44009.h
Normal file
37
esphome/components/max44009/max44009.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace max44009 {
|
||||
|
||||
enum MAX44009Mode { MAX44009_MODE_AUTO, MAX44009_MODE_LOW_POWER, MAX44009_MODE_CONTINUOUS };
|
||||
|
||||
/// This class implements support for the MAX44009 Illuminance i2c sensor.
|
||||
class MAX44009Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
MAX44009Sensor() {}
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
void update() override;
|
||||
void set_mode(MAX44009Mode mode);
|
||||
bool set_continuous_mode();
|
||||
bool set_low_power_mode();
|
||||
|
||||
protected:
|
||||
/// Read the illuminance value
|
||||
float read_illuminance_();
|
||||
float convert_to_lux_(uint8_t data_high, uint8_t data_low);
|
||||
uint8_t read_(uint8_t reg);
|
||||
void write_(uint8_t reg, uint8_t value);
|
||||
|
||||
int error_;
|
||||
MAX44009Mode mode_;
|
||||
};
|
||||
|
||||
} // namespace max44009
|
||||
} // namespace esphome
|
53
esphome/components/max44009/sensor.py
Normal file
53
esphome/components/max44009/sensor.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, i2c
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_MODE,
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_LUX,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@berfenger"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
max44009_ns = cg.esphome_ns.namespace("max44009")
|
||||
MAX44009Sensor = max44009_ns.class_(
|
||||
"MAX44009Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
MAX44009Mode = max44009_ns.enum("MAX44009Mode")
|
||||
MODE_OPTIONS = {
|
||||
"auto": MAX44009Mode.MAX44009_MODE_AUTO,
|
||||
"low_power": MAX44009Mode.MAX44009_MODE_LOW_POWER,
|
||||
"continuous": MAX44009Mode.MAX44009_MODE_CONTINUOUS,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_LUX,
|
||||
accuracy_decimals=3,
|
||||
device_class=DEVICE_CLASS_ILLUMINANCE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MAX44009Sensor),
|
||||
cv.Optional(CONF_MODE, default="low_power"): cv.enum(
|
||||
MODE_OPTIONS, lower=True
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x4A))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
await sensor.register_sensor(var, config)
|
||||
|
||||
cg.add(var.set_mode(config[CONF_MODE]))
|
|
@ -463,6 +463,13 @@ sensor:
|
|||
state_topic: livingroom/custom_state_topic
|
||||
measurement_duration: 31
|
||||
i2c_id: i2c_bus
|
||||
- platform: max44009
|
||||
name: "Outside Brightness 1"
|
||||
internal: true
|
||||
address: 0x4A
|
||||
update_interval: 30s
|
||||
mode: low_power
|
||||
i2c_id: i2c_bus
|
||||
- platform: bme280
|
||||
temperature:
|
||||
name: "Outside Temperature"
|
||||
|
|
Loading…
Reference in a new issue