mirror of
https://github.com/esphome/esphome.git
synced 2024-11-30 10:44:13 +01:00
88fbb0ffbb
Co-authored-by: Otto Winter <otto@otto-winter.com>
144 lines
4.1 KiB
C++
144 lines
4.1 KiB
C++
#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
|