mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +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/md5/* @esphome/core | ||||||
| esphome/components/mdns/* @esphome/core | esphome/components/mdns/* @esphome/core | ||||||
| esphome/components/media_player/* @jesserockz | esphome/components/media_player/* @jesserockz | ||||||
|  | esphome/components/mics_4514/* @jesserockz | ||||||
| esphome/components/midea/* @dudanov | esphome/components/midea/* @dudanov | ||||||
| esphome/components/midea_ir/* @dudanov | esphome/components/midea_ir/* @dudanov | ||||||
| esphome/components/mitsubishi/* @RubyBailey | 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 |     temperature_sensor: ha_hello_world_temperature | ||||||
|     ph: |     ph: | ||||||
|       name: Ufire 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: | time: | ||||||
|   - platform: homeassistant |   - platform: homeassistant | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user