mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	[qmc5883l] Added drdy_pin option to allow it to run max rate (#10901)
Co-authored-by: Lamer Mortification <lamer_mortification@yahoo.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
This commit is contained in:
		| @@ -8,6 +8,7 @@ namespace esphome { | |||||||
| namespace qmc5883l { | namespace qmc5883l { | ||||||
|  |  | ||||||
| static const char *const TAG = "qmc5883l"; | static const char *const TAG = "qmc5883l"; | ||||||
|  |  | ||||||
| static const uint8_t QMC5883L_ADDRESS = 0x0D; | static const uint8_t QMC5883L_ADDRESS = 0x0D; | ||||||
|  |  | ||||||
| static const uint8_t QMC5883L_REGISTER_DATA_X_LSB = 0x00; | static const uint8_t QMC5883L_REGISTER_DATA_X_LSB = 0x00; | ||||||
| @@ -32,6 +33,10 @@ void QMC5883LComponent::setup() { | |||||||
|   } |   } | ||||||
|   delay(10); |   delay(10); | ||||||
|  |  | ||||||
|  |   if (this->drdy_pin_) { | ||||||
|  |     this->drdy_pin_->setup(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   uint8_t control_1 = 0; |   uint8_t control_1 = 0; | ||||||
|   control_1 |= 0b01 << 0;  // MODE (Mode) -> 0b00=standby, 0b01=continuous |   control_1 |= 0b01 << 0;  // MODE (Mode) -> 0b00=standby, 0b01=continuous | ||||||
|   control_1 |= this->datarate_ << 2; |   control_1 |= this->datarate_ << 2; | ||||||
| @@ -64,6 +69,7 @@ void QMC5883LComponent::setup() { | |||||||
|     high_freq_.start(); |     high_freq_.start(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void QMC5883LComponent::dump_config() { | void QMC5883LComponent::dump_config() { | ||||||
|   ESP_LOGCONFIG(TAG, "QMC5883L:"); |   ESP_LOGCONFIG(TAG, "QMC5883L:"); | ||||||
|   LOG_I2C_DEVICE(this); |   LOG_I2C_DEVICE(this); | ||||||
| @@ -77,11 +83,20 @@ void QMC5883LComponent::dump_config() { | |||||||
|   LOG_SENSOR("  ", "Z Axis", this->z_sensor_); |   LOG_SENSOR("  ", "Z Axis", this->z_sensor_); | ||||||
|   LOG_SENSOR("  ", "Heading", this->heading_sensor_); |   LOG_SENSOR("  ", "Heading", this->heading_sensor_); | ||||||
|   LOG_SENSOR("  ", "Temperature", this->temperature_sensor_); |   LOG_SENSOR("  ", "Temperature", this->temperature_sensor_); | ||||||
|  |   LOG_PIN("  DRDY Pin: ", this->drdy_pin_); | ||||||
| } | } | ||||||
|  |  | ||||||
| float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } | float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } | ||||||
|  |  | ||||||
| void QMC5883LComponent::update() { | void QMC5883LComponent::update() { | ||||||
|   i2c::ErrorCode err; |   i2c::ErrorCode err; | ||||||
|   uint8_t status = false; |   uint8_t status = false; | ||||||
|  |  | ||||||
|  |   // If DRDY pin is configured and the data is not ready return. | ||||||
|  |   if (this->drdy_pin_ && !this->drdy_pin_->digital_read()) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Status byte gets cleared when data is read, so we have to read this first. |   // Status byte gets cleared when data is read, so we have to read this first. | ||||||
|   // If status and two axes are desired, it's possible to save one byte of traffic by enabling |   // If status and two axes are desired, it's possible to save one byte of traffic by enabling | ||||||
|   // ROL_PNT in setup and reading 7 bytes starting at the status register. |   // ROL_PNT in setup and reading 7 bytes starting at the status register. | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| #include "esphome/core/component.h" | #include "esphome/core/component.h" | ||||||
| #include "esphome/components/sensor/sensor.h" | #include "esphome/components/sensor/sensor.h" | ||||||
| #include "esphome/components/i2c/i2c.h" | #include "esphome/components/i2c/i2c.h" | ||||||
|  | #include "esphome/core/hal.h" | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace qmc5883l { | namespace qmc5883l { | ||||||
| @@ -33,6 +34,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { | |||||||
|   float get_setup_priority() const override; |   float get_setup_priority() const override; | ||||||
|   void update() override; |   void update() override; | ||||||
|  |  | ||||||
|  |   void set_drdy_pin(GPIOPin *pin) { drdy_pin_ = pin; } | ||||||
|   void set_datarate(QMC5883LDatarate datarate) { datarate_ = datarate; } |   void set_datarate(QMC5883LDatarate datarate) { datarate_ = datarate; } | ||||||
|   void set_range(QMC5883LRange range) { range_ = range; } |   void set_range(QMC5883LRange range) { range_ = range; } | ||||||
|   void set_oversampling(QMC5883LOversampling oversampling) { oversampling_ = oversampling; } |   void set_oversampling(QMC5883LOversampling oversampling) { oversampling_ = oversampling; } | ||||||
| @@ -51,6 +53,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { | |||||||
|   sensor::Sensor *z_sensor_{nullptr}; |   sensor::Sensor *z_sensor_{nullptr}; | ||||||
|   sensor::Sensor *heading_sensor_{nullptr}; |   sensor::Sensor *heading_sensor_{nullptr}; | ||||||
|   sensor::Sensor *temperature_sensor_{nullptr}; |   sensor::Sensor *temperature_sensor_{nullptr}; | ||||||
|  |   GPIOPin *drdy_pin_{nullptr}; | ||||||
|   enum ErrorCode { |   enum ErrorCode { | ||||||
|     NONE = 0, |     NONE = 0, | ||||||
|     COMMUNICATION_FAILED, |     COMMUNICATION_FAILED, | ||||||
|   | |||||||
| @@ -1,8 +1,12 @@ | |||||||
|  | import logging | ||||||
|  |  | ||||||
|  | from esphome import pins | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components import i2c, sensor | from esphome.components import i2c, sensor | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_ADDRESS, |     CONF_ADDRESS, | ||||||
|  |     CONF_DATA_RATE, | ||||||
|     CONF_FIELD_STRENGTH_X, |     CONF_FIELD_STRENGTH_X, | ||||||
|     CONF_FIELD_STRENGTH_Y, |     CONF_FIELD_STRENGTH_Y, | ||||||
|     CONF_FIELD_STRENGTH_Z, |     CONF_FIELD_STRENGTH_Z, | ||||||
| @@ -21,6 +25,10 @@ from esphome.const import ( | |||||||
|     UNIT_MICROTESLA, |     UNIT_MICROTESLA, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
|  | CONF_DRDY_PIN = "drdy_pin" | ||||||
|  |  | ||||||
| DEPENDENCIES = ["i2c"] | DEPENDENCIES = ["i2c"] | ||||||
|  |  | ||||||
| qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") | qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") | ||||||
| @@ -52,6 +60,18 @@ QMC5883LOversamplings = { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def validate_config(config): | ||||||
|  |     if ( | ||||||
|  |         config[CONF_UPDATE_INTERVAL].total_milliseconds < 15 | ||||||
|  |         and CONF_DRDY_PIN not in config | ||||||
|  |     ): | ||||||
|  |         _LOGGER.warning( | ||||||
|  |             "[qmc5883l] 'update_interval' is less than 15ms and 'drdy_pin' is " | ||||||
|  |             "not configured, this may result in I2C errors" | ||||||
|  |         ) | ||||||
|  |     return config | ||||||
|  |  | ||||||
|  |  | ||||||
| def validate_enum(enum_values, units=None, int=True): | def validate_enum(enum_values, units=None, int=True): | ||||||
|     _units = [] |     _units = [] | ||||||
|     if units is not None: |     if units is not None: | ||||||
| @@ -88,7 +108,7 @@ temperature_schema = sensor.sensor_schema( | |||||||
|     state_class=STATE_CLASS_MEASUREMENT, |     state_class=STATE_CLASS_MEASUREMENT, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = ( | CONFIG_SCHEMA = cv.All( | ||||||
|     cv.Schema( |     cv.Schema( | ||||||
|         { |         { | ||||||
|             cv.GenerateID(): cv.declare_id(QMC5883LComponent), |             cv.GenerateID(): cv.declare_id(QMC5883LComponent), | ||||||
| @@ -104,29 +124,25 @@ CONFIG_SCHEMA = ( | |||||||
|             cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, |             cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, | ||||||
|             cv.Optional(CONF_HEADING): heading_schema, |             cv.Optional(CONF_HEADING): heading_schema, | ||||||
|             cv.Optional(CONF_TEMPERATURE): temperature_schema, |             cv.Optional(CONF_TEMPERATURE): temperature_schema, | ||||||
|  |             cv.Optional(CONF_DRDY_PIN): pins.gpio_input_pin_schema, | ||||||
|  |             cv.Optional(CONF_DATA_RATE, default="200hz"): validate_enum( | ||||||
|  |                 QMC5883LDatarates, units=["hz", "Hz"] | ||||||
|  |             ), | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     .extend(cv.polling_component_schema("60s")) |     .extend(cv.polling_component_schema("60s")) | ||||||
|     .extend(i2c.i2c_device_schema(0x0D)) |     .extend(i2c.i2c_device_schema(0x0D)), | ||||||
|  |     validate_config, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def auto_data_rate(config): |  | ||||||
|     interval_sec = config[CONF_UPDATE_INTERVAL].total_milliseconds / 1000 |  | ||||||
|     interval_hz = 1.0 / interval_sec |  | ||||||
|     for datarate in sorted(QMC5883LDatarates.keys()): |  | ||||||
|         if float(datarate) >= interval_hz: |  | ||||||
|             return QMC5883LDatarates[datarate] |  | ||||||
|     return QMC5883LDatarates[200] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| async def to_code(config): | async def to_code(config): | ||||||
|     var = cg.new_Pvariable(config[CONF_ID]) |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|     await cg.register_component(var, config) |     await cg.register_component(var, config) | ||||||
|     await i2c.register_i2c_device(var, config) |     await i2c.register_i2c_device(var, config) | ||||||
|  |  | ||||||
|     cg.add(var.set_oversampling(config[CONF_OVERSAMPLING])) |     cg.add(var.set_oversampling(config[CONF_OVERSAMPLING])) | ||||||
|     cg.add(var.set_datarate(auto_data_rate(config))) |     cg.add(var.set_datarate(config[CONF_DATA_RATE])) | ||||||
|     cg.add(var.set_range(config[CONF_RANGE])) |     cg.add(var.set_range(config[CONF_RANGE])) | ||||||
|     if CONF_FIELD_STRENGTH_X in config: |     if CONF_FIELD_STRENGTH_X in config: | ||||||
|         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X]) |         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X]) | ||||||
| @@ -143,3 +159,6 @@ 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)) | ||||||
|  |     if CONF_DRDY_PIN in config: | ||||||
|  |         pin = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) | ||||||
|  |         cg.add(var.set_drdy_pin(pin)) | ||||||
|   | |||||||
| @@ -17,5 +17,7 @@ sensor: | |||||||
|     temperature: |     temperature: | ||||||
|       name: QMC5883L Temperature |       name: QMC5883L Temperature | ||||||
|     range: 800uT |     range: 800uT | ||||||
|  |     data_rate: 200Hz | ||||||
|     oversampling: 256x |     oversampling: 256x | ||||||
|     update_interval: 15s |     update_interval: 15s | ||||||
|  |     drdy_pin: ${drdy_pin} | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO16 |   scl_pin: GPIO16 | ||||||
|   sda_pin: GPIO17 |   sda_pin: GPIO17 | ||||||
|  |   drdy_pin: GPIO18 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO5 |   scl_pin: GPIO5 | ||||||
|   sda_pin: GPIO4 |   sda_pin: GPIO4 | ||||||
|  |   drdy_pin: GPIO6 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO5 |   scl_pin: GPIO5 | ||||||
|   sda_pin: GPIO4 |   sda_pin: GPIO4 | ||||||
|  |   drdy_pin: GPIO6 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO16 |   scl_pin: GPIO16 | ||||||
|   sda_pin: GPIO17 |   sda_pin: GPIO17 | ||||||
|  |   drdy_pin: GPIO18 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO5 |   scl_pin: GPIO5 | ||||||
|   sda_pin: GPIO4 |   sda_pin: GPIO4 | ||||||
|  |   drdy_pin: GPIO2 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| substitutions: | substitutions: | ||||||
|   scl_pin: GPIO5 |   scl_pin: GPIO5 | ||||||
|   sda_pin: GPIO4 |   sda_pin: GPIO4 | ||||||
|  |   drdy_pin: GPIO2 | ||||||
|  |  | ||||||
| <<: !include common.yaml | <<: !include common.yaml | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user