mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add sensor support: MAX44009 (#3125)
Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
		| @@ -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" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user