mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	SCD30 Added support for manual calibration (#4362)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
							
								
								
									
										23
									
								
								esphome/components/scd30/automation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/scd30/automation.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/automation.h" | ||||||
|  | #include "scd30.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace scd30 { | ||||||
|  |  | ||||||
|  | template<typename... Ts> class ForceRecalibrationWithReference : public Action<Ts...>, public Parented<SCD30Component> { | ||||||
|  |  public: | ||||||
|  |   void play(Ts... x) override { | ||||||
|  |     if (this->value_.has_value()) { | ||||||
|  |       this->parent_->force_recalibration_with_reference(this->value_.value(x...)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   TEMPLATABLE_VALUE(uint16_t, value) | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace scd30 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -202,5 +202,27 @@ bool SCD30Component::is_data_ready_() { | |||||||
|   return is_data_ready == 1; |   return is_data_ready == 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool SCD30Component::force_recalibration_with_reference(uint16_t co2_reference) { | ||||||
|  |   ESP_LOGD(TAG, "Performing CO2 force recalibration with reference %dppm.", co2_reference); | ||||||
|  |   if (this->write_command(SCD30_CMD_FORCED_CALIBRATION, co2_reference)) { | ||||||
|  |     ESP_LOGD(TAG, "Force recalibration complete."); | ||||||
|  |     return true; | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGE(TAG, "Failed to force recalibration with reference."); | ||||||
|  |     this->error_code_ = FORCE_RECALIBRATION_FAILED; | ||||||
|  |     this->status_set_warning(); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint16_t SCD30Component::get_forced_calibration_reference() { | ||||||
|  |   uint16_t forced_calibration_reference; | ||||||
|  |   // Get current CO2 calibration | ||||||
|  |   if (!this->get_register(SCD30_CMD_FORCED_CALIBRATION, forced_calibration_reference)) { | ||||||
|  |     ESP_LOGE(TAG, "Unable to read forced calibration reference."); | ||||||
|  |   } | ||||||
|  |   return forced_calibration_reference; | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace scd30 | }  // namespace scd30 | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -20,6 +20,8 @@ class SCD30Component : public Component, public sensirion_common::SensirionI2CDe | |||||||
|   } |   } | ||||||
|   void set_temperature_offset(float offset) { temperature_offset_ = offset; } |   void set_temperature_offset(float offset) { temperature_offset_ = offset; } | ||||||
|   void set_update_interval(uint16_t interval) { update_interval_ = interval; } |   void set_update_interval(uint16_t interval) { update_interval_ = interval; } | ||||||
|  |   bool force_recalibration_with_reference(uint16_t co2_reference); | ||||||
|  |   uint16_t get_forced_calibration_reference(); | ||||||
|  |  | ||||||
|   void setup() override; |   void setup() override; | ||||||
|   void update(); |   void update(); | ||||||
| @@ -33,6 +35,7 @@ class SCD30Component : public Component, public sensirion_common::SensirionI2CDe | |||||||
|     COMMUNICATION_FAILED, |     COMMUNICATION_FAILED, | ||||||
|     FIRMWARE_IDENTIFICATION_FAILED, |     FIRMWARE_IDENTIFICATION_FAILED, | ||||||
|     MEASUREMENT_INIT_FAILED, |     MEASUREMENT_INIT_FAILED, | ||||||
|  |     FORCE_RECALIBRATION_FAILED, | ||||||
|     UNKNOWN |     UNKNOWN | ||||||
|   } error_code_{UNKNOWN}; |   } error_code_{UNKNOWN}; | ||||||
|   bool enable_asc_{true}; |   bool enable_asc_{true}; | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| from esphome import core | from esphome import automation, core | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.components import i2c, sensor | from esphome.components import i2c, sensor | ||||||
| @@ -9,6 +9,7 @@ from esphome.const import ( | |||||||
|     CONF_TEMPERATURE, |     CONF_TEMPERATURE, | ||||||
|     CONF_CO2, |     CONF_CO2, | ||||||
|     CONF_UPDATE_INTERVAL, |     CONF_UPDATE_INTERVAL, | ||||||
|  |     CONF_VALUE, | ||||||
|     DEVICE_CLASS_HUMIDITY, |     DEVICE_CLASS_HUMIDITY, | ||||||
|     DEVICE_CLASS_TEMPERATURE, |     DEVICE_CLASS_TEMPERATURE, | ||||||
|     STATE_CLASS_MEASUREMENT, |     STATE_CLASS_MEASUREMENT, | ||||||
| @@ -26,6 +27,11 @@ SCD30Component = scd30_ns.class_( | |||||||
|     "SCD30Component", cg.Component, sensirion_common.SensirionI2CDevice |     "SCD30Component", cg.Component, sensirion_common.SensirionI2CDevice | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | # Actions | ||||||
|  | ForceRecalibrationWithReference = scd30_ns.class_( | ||||||
|  |     "ForceRecalibrationWithReference", automation.Action | ||||||
|  | ) | ||||||
|  |  | ||||||
| CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" | CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" | ||||||
| CONF_ALTITUDE_COMPENSATION = "altitude_compensation" | CONF_ALTITUDE_COMPENSATION = "altitude_compensation" | ||||||
| CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" | CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" | ||||||
| @@ -106,3 +112,26 @@ async def to_code(config): | |||||||
|     if CONF_TEMPERATURE in config: |     if CONF_TEMPERATURE in config: | ||||||
|         sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) |         sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) | ||||||
|         cg.add(var.set_temperature_sensor(sens)) |         cg.add(var.set_temperature_sensor(sens)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @automation.register_action( | ||||||
|  |     "scd30.force_recalibration_with_reference", | ||||||
|  |     ForceRecalibrationWithReference, | ||||||
|  |     cv.maybe_simple_value( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.use_id(SCD30Component), | ||||||
|  |             cv.Required(CONF_VALUE): cv.templatable( | ||||||
|  |                 cv.int_range(min=400, max=2000, max_included=True) | ||||||
|  |             ), | ||||||
|  |         }, | ||||||
|  |         key=CONF_VALUE, | ||||||
|  |     ), | ||||||
|  | ) | ||||||
|  | async def scd30_force_recalibration_with_reference_to_code( | ||||||
|  |     config, action_id, template_arg, args | ||||||
|  | ): | ||||||
|  |     var = cg.new_Pvariable(action_id, template_arg) | ||||||
|  |     await cg.register_parented(var, config[CONF_ID]) | ||||||
|  |     template_ = await cg.templatable(config[CONF_VALUE], args, cg.uint16) | ||||||
|  |     cg.add(var.set_value(template_)) | ||||||
|  |     return var | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user