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 { | ||||
|  | ||||
| static const char *const TAG = "qmc5883l"; | ||||
|  | ||||
| static const uint8_t QMC5883L_ADDRESS = 0x0D; | ||||
|  | ||||
| static const uint8_t QMC5883L_REGISTER_DATA_X_LSB = 0x00; | ||||
| @@ -32,6 +33,10 @@ void QMC5883LComponent::setup() { | ||||
|   } | ||||
|   delay(10); | ||||
|  | ||||
|   if (this->drdy_pin_) { | ||||
|     this->drdy_pin_->setup(); | ||||
|   } | ||||
|  | ||||
|   uint8_t control_1 = 0; | ||||
|   control_1 |= 0b01 << 0;  // MODE (Mode) -> 0b00=standby, 0b01=continuous | ||||
|   control_1 |= this->datarate_ << 2; | ||||
| @@ -64,6 +69,7 @@ void QMC5883LComponent::setup() { | ||||
|     high_freq_.start(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void QMC5883LComponent::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "QMC5883L:"); | ||||
|   LOG_I2C_DEVICE(this); | ||||
| @@ -77,11 +83,20 @@ void QMC5883LComponent::dump_config() { | ||||
|   LOG_SENSOR("  ", "Z Axis", this->z_sensor_); | ||||
|   LOG_SENSOR("  ", "Heading", this->heading_sensor_); | ||||
|   LOG_SENSOR("  ", "Temperature", this->temperature_sensor_); | ||||
|   LOG_PIN("  DRDY Pin: ", this->drdy_pin_); | ||||
| } | ||||
|  | ||||
| float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } | ||||
|  | ||||
| void QMC5883LComponent::update() { | ||||
|   i2c::ErrorCode err; | ||||
|   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. | ||||
|   // 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. | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/components/sensor/sensor.h" | ||||
| #include "esphome/components/i2c/i2c.h" | ||||
| #include "esphome/core/hal.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace qmc5883l { | ||||
| @@ -33,6 +34,7 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { | ||||
|   float get_setup_priority() const override; | ||||
|   void update() override; | ||||
|  | ||||
|   void set_drdy_pin(GPIOPin *pin) { drdy_pin_ = pin; } | ||||
|   void set_datarate(QMC5883LDatarate datarate) { datarate_ = datarate; } | ||||
|   void set_range(QMC5883LRange range) { range_ = range; } | ||||
|   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 *heading_sensor_{nullptr}; | ||||
|   sensor::Sensor *temperature_sensor_{nullptr}; | ||||
|   GPIOPin *drdy_pin_{nullptr}; | ||||
|   enum ErrorCode { | ||||
|     NONE = 0, | ||||
|     COMMUNICATION_FAILED, | ||||
|   | ||||
| @@ -1,8 +1,12 @@ | ||||
| import logging | ||||
|  | ||||
| from esphome import pins | ||||
| import esphome.codegen as cg | ||||
| from esphome.components import i2c, sensor | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|     CONF_ADDRESS, | ||||
|     CONF_DATA_RATE, | ||||
|     CONF_FIELD_STRENGTH_X, | ||||
|     CONF_FIELD_STRENGTH_Y, | ||||
|     CONF_FIELD_STRENGTH_Z, | ||||
| @@ -21,6 +25,10 @@ from esphome.const import ( | ||||
|     UNIT_MICROTESLA, | ||||
| ) | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| CONF_DRDY_PIN = "drdy_pin" | ||||
|  | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| 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): | ||||
|     _units = [] | ||||
|     if units is not None: | ||||
| @@ -88,7 +108,7 @@ temperature_schema = sensor.sensor_schema( | ||||
|     state_class=STATE_CLASS_MEASUREMENT, | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = ( | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(QMC5883LComponent), | ||||
| @@ -104,29 +124,25 @@ CONFIG_SCHEMA = ( | ||||
|             cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, | ||||
|             cv.Optional(CONF_HEADING): heading_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(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): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     await cg.register_component(var, config) | ||||
|     await i2c.register_i2c_device(var, config) | ||||
|  | ||||
|     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])) | ||||
|     if CONF_FIELD_STRENGTH_X in config: | ||||
|         sens = await sensor.new_sensor(config[CONF_FIELD_STRENGTH_X]) | ||||
| @@ -143,3 +159,6 @@ async def to_code(config): | ||||
|     if CONF_TEMPERATURE in config: | ||||
|         sens = await sensor.new_sensor(config[CONF_TEMPERATURE]) | ||||
|         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: | ||||
|       name: QMC5883L Temperature | ||||
|     range: 800uT | ||||
|     data_rate: 200Hz | ||||
|     oversampling: 256x | ||||
|     update_interval: 15s | ||||
|     drdy_pin: ${drdy_pin} | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO16 | ||||
|   sda_pin: GPIO17 | ||||
|   drdy_pin: GPIO18 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|   drdy_pin: GPIO6 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|   drdy_pin: GPIO6 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO16 | ||||
|   sda_pin: GPIO17 | ||||
|   drdy_pin: GPIO18 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|   drdy_pin: GPIO2 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| substitutions: | ||||
|   scl_pin: GPIO5 | ||||
|   sda_pin: GPIO4 | ||||
|   drdy_pin: GPIO2 | ||||
|  | ||||
| <<: !include common.yaml | ||||
|   | ||||
		Reference in New Issue
	
	Block a user