mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Add MICS-4514 gas sensor (#4316)
This commit is contained in:
		| @@ -145,6 +145,7 @@ esphome/components/mcp9808/* @k7hpn | ||||
| esphome/components/md5/* @esphome/core | ||||
| esphome/components/mdns/* @esphome/core | ||||
| esphome/components/media_player/* @jesserockz | ||||
| esphome/components/mics_4514/* @jesserockz | ||||
| esphome/components/midea/* @dudanov | ||||
| esphome/components/midea_ir/* @dudanov | ||||
| esphome/components/mitsubishi/* @RubyBailey | ||||
|   | ||||
							
								
								
									
										0
									
								
								esphome/components/mics_4514/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								esphome/components/mics_4514/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										145
									
								
								esphome/components/mics_4514/mics_4514.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								esphome/components/mics_4514/mics_4514.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| #include "mics_4514.h" | ||||
|  | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace mics_4514 { | ||||
|  | ||||
| static const char *const TAG = "mics_4514"; | ||||
|  | ||||
| static const uint8_t SENSOR_REGISTER = 0x04; | ||||
| static const uint8_t POWER_MODE_REGISTER = 0x0a; | ||||
|  | ||||
| void MICS4514Component::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up MICS 4514..."); | ||||
|   uint8_t power_mode; | ||||
|   this->read_register(POWER_MODE_REGISTER, &power_mode, 1); | ||||
|   if (power_mode == 0x00) { | ||||
|     ESP_LOGCONFIG(TAG, "Waking up MICS 4514"); | ||||
|     power_mode = 0x01; | ||||
|     this->write_register(POWER_MODE_REGISTER, &power_mode, 1); | ||||
|     delay(100);  // NOLINT | ||||
|     this->set_timeout("warmup", 3 * 60 * 1000, [this]() { | ||||
|       this->warmed_up_ = true; | ||||
|       ESP_LOGCONFIG(TAG, "MICS 4514 setup complete."); | ||||
|     }); | ||||
|     this->status_set_warning(); | ||||
|     return; | ||||
|   } | ||||
|   ESP_LOGCONFIG(TAG, "Device already awake."); | ||||
|   this->warmed_up_ = true; | ||||
|   ESP_LOGCONFIG(TAG, "MICS 4514 setup complete."); | ||||
| } | ||||
| void MICS4514Component::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "MICS 4514:"); | ||||
|   LOG_I2C_DEVICE(this); | ||||
|   LOG_UPDATE_INTERVAL(this); | ||||
|   LOG_SENSOR("  ", "Nitrogen Dioxide", this->nitrogen_dioxide_sensor_); | ||||
|   LOG_SENSOR("  ", "Carbon Monoxide", this->carbon_monoxide_sensor_); | ||||
|   LOG_SENSOR("  ", "Methane", this->methane_sensor_); | ||||
|   LOG_SENSOR("  ", "Ethanol", this->ethanol_sensor_); | ||||
|   LOG_SENSOR("  ", "Hydrogen", this->hydrogen_sensor_); | ||||
|   LOG_SENSOR("  ", "Ammonia", this->ammonia_sensor_); | ||||
| } | ||||
| float MICS4514Component::get_setup_priority() const { return setup_priority::DATA; } | ||||
| void MICS4514Component::update() { | ||||
|   if (!this->warmed_up_) { | ||||
|     return; | ||||
|   } | ||||
|   uint8_t data[6]; | ||||
|   if (this->read_register(SENSOR_REGISTER, data, 6) != i2c::ERROR_OK) { | ||||
|     this->status_set_warning(); | ||||
|     return; | ||||
|   } | ||||
|   this->status_clear_warning(); | ||||
|   ESP_LOGV(TAG, "Got data: %02X %02X %02X %02X %02X %02X", data[0], data[1], data[2], data[3], data[4], data[5]); | ||||
|   uint16_t ox = encode_uint16(data[0], data[1]); | ||||
|   uint16_t red = encode_uint16(data[2], data[3]); | ||||
|   uint16_t power = encode_uint16(data[4], data[5]); | ||||
|  | ||||
|   if (this->initial_) { | ||||
|     this->initial_ = false; | ||||
|     this->ox_calibration_ = (float) (power - ox); | ||||
|     this->red_calibration_ = (float) (power - red); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   float red_f = (float) (power - red) / this->red_calibration_; | ||||
|   float ox_f = (float) (power - ox) / this->ox_calibration_; | ||||
|  | ||||
|   if (this->carbon_monoxide_sensor_ != nullptr) { | ||||
|     float co = 0.0f; | ||||
|     if (red_f <= 0.425f) { | ||||
|       co = (0.425f - red_f) / 0.000405f; | ||||
|       if (co < 1.0f) | ||||
|         co = 0.0f; | ||||
|       if (co > 1000.0f) | ||||
|         co = 1000.0f; | ||||
|     } | ||||
|     this->carbon_monoxide_sensor_->publish_state(co); | ||||
|   } | ||||
|  | ||||
|   if (this->nitrogen_dioxide_sensor_ != nullptr) { | ||||
|     float nitrogendioxide = 0.0f; | ||||
|     if (ox_f >= 1.1f) { | ||||
|       nitrogendioxide = (ox_f - 0.045f) / 6.13f; | ||||
|       if (nitrogendioxide < 0.1f) | ||||
|         nitrogendioxide = 0.0f; | ||||
|       if (nitrogendioxide > 10.0f) | ||||
|         nitrogendioxide = 10.0f; | ||||
|     } | ||||
|     this->nitrogen_dioxide_sensor_->publish_state(nitrogendioxide); | ||||
|   } | ||||
|  | ||||
|   if (this->methane_sensor_ != nullptr) { | ||||
|     float methane = 0.0f; | ||||
|     if (red_f <= 0.786f) { | ||||
|       methane = (0.786f - red_f) / 0.000023f; | ||||
|       if (methane < 1000.0f) | ||||
|         methane = 0.0f; | ||||
|       if (methane > 25000.0f) | ||||
|         methane = 25000.0f; | ||||
|     } | ||||
|     this->methane_sensor_->publish_state(methane); | ||||
|   } | ||||
|  | ||||
|   if (this->ethanol_sensor_ != nullptr) { | ||||
|     float ethanol = 0.0f; | ||||
|     if (red_f <= 0.306f) { | ||||
|       ethanol = (0.306f - red_f) / 0.00057f; | ||||
|       if (ethanol < 10.0f) | ||||
|         ethanol = 0.0f; | ||||
|       if (ethanol > 500.0f) | ||||
|         ethanol = 500.0f; | ||||
|     } | ||||
|     this->ethanol_sensor_->publish_state(ethanol); | ||||
|   } | ||||
|  | ||||
|   if (this->hydrogen_sensor_ != nullptr) { | ||||
|     float hydrogen = 0.0f; | ||||
|     if (red_f <= 0.279f) { | ||||
|       hydrogen = (0.279f - red_f) / 0.00026f; | ||||
|       if (hydrogen < 1.0f) | ||||
|         hydrogen = 0.0f; | ||||
|       if (hydrogen > 1000.0f) | ||||
|         hydrogen = 1000.0f; | ||||
|     } | ||||
|     this->hydrogen_sensor_->publish_state(hydrogen); | ||||
|   } | ||||
|  | ||||
|   if (this->ammonia_sensor_ != nullptr) { | ||||
|     float ammonia = 0.0f; | ||||
|     if (red_f <= 0.8f) { | ||||
|       ammonia = (0.8f - red_f) / 0.0015f; | ||||
|       if (ammonia < 1.0f) | ||||
|         ammonia = 0.0f; | ||||
|       if (ammonia > 500.0f) | ||||
|         ammonia = 500.0f; | ||||
|     } | ||||
|     this->ammonia_sensor_->publish_state(ammonia); | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace mics_4514 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										34
									
								
								esphome/components/mics_4514/mics_4514.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								esphome/components/mics_4514/mics_4514.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "esphome/components/i2c/i2c.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/hal.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace mics_4514 { | ||||
|  | ||||
| class MICS4514Component : public PollingComponent, public i2c::I2CDevice { | ||||
|   SUB_SENSOR(carbon_monoxide) | ||||
|   SUB_SENSOR(nitrogen_dioxide) | ||||
|   SUB_SENSOR(methane) | ||||
|   SUB_SENSOR(ethanol) | ||||
|   SUB_SENSOR(hydrogen) | ||||
|   SUB_SENSOR(ammonia) | ||||
|  | ||||
|  public: | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override; | ||||
|   void update() override; | ||||
|  | ||||
|  protected: | ||||
|   bool warmed_up_{false}; | ||||
|   bool initial_{true}; | ||||
|  | ||||
|   float ox_calibration_{0}; | ||||
|   float red_calibration_{0}; | ||||
| }; | ||||
|  | ||||
| }  // namespace mics_4514 | ||||
| }  // namespace esphome | ||||
							
								
								
									
										71
									
								
								esphome/components/mics_4514/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								esphome/components/mics_4514/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
|  | ||||
| from esphome.components import sensor, i2c | ||||
|  | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     STATE_CLASS_MEASUREMENT, | ||||
|     UNIT_PARTS_PER_MILLION, | ||||
| ) | ||||
|  | ||||
| CODEOWNERS = ["@jesserockz"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| CONF_CARBON_MONOXIDE = "carbon_monoxide" | ||||
| CONF_NITROGEN_DIOXIDE = "nitrogen_dioxide" | ||||
| CONF_METHANE = "methane" | ||||
| CONF_ETHANOL = "ethanol" | ||||
| CONF_HYDROGEN = "hydrogen" | ||||
| CONF_AMMONIA = "ammonia" | ||||
|  | ||||
|  | ||||
| mics_4514_ns = cg.esphome_ns.namespace("mics_4514") | ||||
| MICS4514Component = mics_4514_ns.class_( | ||||
|     "MICS4514Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| SENSORS = [ | ||||
|     CONF_CARBON_MONOXIDE, | ||||
|     CONF_METHANE, | ||||
|     CONF_ETHANOL, | ||||
|     CONF_HYDROGEN, | ||||
|     CONF_AMMONIA, | ||||
| ] | ||||
|  | ||||
| common_sensor_schema = sensor.sensor_schema( | ||||
|     unit_of_measurement=UNIT_PARTS_PER_MILLION, | ||||
|     state_class=STATE_CLASS_MEASUREMENT, | ||||
|     accuracy_decimals=2, | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(MICS4514Component), | ||||
|             cv.Optional(CONF_NITROGEN_DIOXIDE): sensor.sensor_schema( | ||||
|                 unit_of_measurement=UNIT_PARTS_PER_MILLION, | ||||
|                 state_class=STATE_CLASS_MEASUREMENT, | ||||
|                 accuracy_decimals=2, | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend({cv.Optional(sensor_type): common_sensor_schema for sensor_type in SENSORS}) | ||||
|     .extend(i2c.i2c_device_schema(0x75)) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| 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) | ||||
|  | ||||
|     for sensor_type in SENSORS: | ||||
|         if sensor_type in config: | ||||
|             sens = await sensor.new_sensor(config[sensor_type]) | ||||
|             cg.add(getattr(var, f"set_{sensor_type}_sensor")(sens)) | ||||
|  | ||||
|     if CONF_NITROGEN_DIOXIDE in config: | ||||
|         sens = await sensor.new_sensor(config[CONF_NITROGEN_DIOXIDE]) | ||||
|         cg.add(var.set_nitrogen_dioxide_sensor(sens)) | ||||
| @@ -381,6 +381,20 @@ sensor: | ||||
|     temperature_sensor: ha_hello_world_temperature | ||||
|     ph: | ||||
|       name: Ufire pH | ||||
|   - platform: mics_4514 | ||||
|     update_interval: 60s | ||||
|     nitrogen_dioxide: | ||||
|       name: MICS-4514 NO2 | ||||
|     carbon_monoxide: | ||||
|       name: MICS-4514 CO | ||||
|     methane: | ||||
|       name: MICS-4514 CH4 | ||||
|     hydrogen: | ||||
|       name: MICS-4514 H2 | ||||
|     ethanol: | ||||
|       name: MICS-4514 C2H5OH | ||||
|     ammonia: | ||||
|       name: MICS-4514 NH3 | ||||
|  | ||||
| time: | ||||
|   - platform: homeassistant | ||||
|   | ||||
		Reference in New Issue
	
	Block a user