mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Vl53l0x change address (#1126)
* Added vl53l0x change address and timeout * Added vl53l0x change address and timeout * vl53l0x code cleanup and update test * remove executable bit * lint code cleanup * code review fixes including timeout default to 10ms * Code review cleanup and change a WARN log level message to DEBUG * Fix issue where warn should be temporary * Added name of sensor to warning message * Fix blacklist lint issue * Remove unused import
This commit is contained in:
		| @@ -1,7 +1,9 @@ | |||||||
| 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 | ||||||
| from esphome.const import CONF_ID, UNIT_METER, ICON_ARROW_EXPAND_VERTICAL | from esphome.const import (CONF_ID, UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, CONF_ADDRESS, | ||||||
|  |                            CONF_TIMEOUT, CONF_ENABLE_PIN) | ||||||
|  | from esphome import pins | ||||||
|  |  | ||||||
| DEPENDENCIES = ['i2c'] | DEPENDENCIES = ['i2c'] | ||||||
|  |  | ||||||
| @@ -12,12 +14,31 @@ VL53L0XSensor = vl53l0x_ns.class_('VL53L0XSensor', sensor.Sensor, cg.PollingComp | |||||||
| CONF_SIGNAL_RATE_LIMIT = 'signal_rate_limit' | CONF_SIGNAL_RATE_LIMIT = 'signal_rate_limit' | ||||||
| CONF_LONG_RANGE = 'long_range' | CONF_LONG_RANGE = 'long_range' | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2).extend({ |  | ||||||
|  | def check_keys(obj): | ||||||
|  |     if obj[CONF_ADDRESS] != 0x29 and CONF_ENABLE_PIN not in obj: | ||||||
|  |         msg = "Address other then 0x29 requires enable_pin definition to allow sensor\r" | ||||||
|  |         msg += "re-addressing. Also if you have more then one VL53 device on the same\r" | ||||||
|  |         msg += "i2c bus, then all VL53 devices must have enable_pin defined." | ||||||
|  |         raise cv.Invalid(msg) | ||||||
|  |     return obj | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def check_timeout(value): | ||||||
|  |     value = cv.positive_time_period_microseconds(value) | ||||||
|  |     if value.total_seconds > 60: | ||||||
|  |         raise cv.Invalid("Maximum timeout can not be greater then 60 seconds") | ||||||
|  |     return value | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = cv.All(sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2).extend({ | ||||||
|         cv.GenerateID(): cv.declare_id(VL53L0XSensor), |         cv.GenerateID(): cv.declare_id(VL53L0XSensor), | ||||||
|         cv.Optional(CONF_SIGNAL_RATE_LIMIT, default=0.25): cv.float_range( |         cv.Optional(CONF_SIGNAL_RATE_LIMIT, default=0.25): cv.float_range( | ||||||
|             min=0.0, max=512.0, min_included=False, max_included=False), |             min=0.0, max=512.0, min_included=False, max_included=False), | ||||||
|         cv.Optional(CONF_LONG_RANGE, default=False): cv.boolean, |         cv.Optional(CONF_LONG_RANGE, default=False): cv.boolean, | ||||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x29)) |         cv.Optional(CONF_TIMEOUT, default='10ms'): check_timeout, | ||||||
|  |         cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, | ||||||
|  |     }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x29)), check_keys) | ||||||
|  |  | ||||||
|  |  | ||||||
| def to_code(config): | def to_code(config): | ||||||
| @@ -25,5 +46,11 @@ def to_code(config): | |||||||
|     yield cg.register_component(var, config) |     yield cg.register_component(var, config) | ||||||
|     cg.add(var.set_signal_rate_limit(config[CONF_SIGNAL_RATE_LIMIT])) |     cg.add(var.set_signal_rate_limit(config[CONF_SIGNAL_RATE_LIMIT])) | ||||||
|     cg.add(var.set_long_range(config[CONF_LONG_RANGE])) |     cg.add(var.set_long_range(config[CONF_LONG_RANGE])) | ||||||
|  |     cg.add(var.set_timeout_us(config[CONF_TIMEOUT])) | ||||||
|  |  | ||||||
|  |     if CONF_ENABLE_PIN in config: | ||||||
|  |         enable = yield cg.gpio_pin_expression(config[CONF_ENABLE_PIN]) | ||||||
|  |         cg.add(var.set_enable_pin(enable)) | ||||||
|  |  | ||||||
|     yield sensor.register_sensor(var, config) |     yield sensor.register_sensor(var, config) | ||||||
|     yield i2c.register_i2c_device(var, config) |     yield i2c.register_i2c_device(var, config) | ||||||
|   | |||||||
| @@ -14,20 +14,55 @@ namespace esphome { | |||||||
| namespace vl53l0x { | namespace vl53l0x { | ||||||
|  |  | ||||||
| static const char *TAG = "vl53l0x"; | static const char *TAG = "vl53l0x"; | ||||||
|  | std::list<VL53L0XSensor *> VL53L0XSensor::vl53_sensors; | ||||||
|  | bool VL53L0XSensor::enable_pin_setup_complete = false; | ||||||
|  |  | ||||||
|  | VL53L0XSensor::VL53L0XSensor() { VL53L0XSensor::vl53_sensors.push_back(this); } | ||||||
|  |  | ||||||
| void VL53L0XSensor::dump_config() { | void VL53L0XSensor::dump_config() { | ||||||
|   LOG_SENSOR("", "VL53L0X", this); |   LOG_SENSOR("", "VL53L0X", this); | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
|   LOG_I2C_DEVICE(this); |   LOG_I2C_DEVICE(this); | ||||||
|  |   if (this->enable_pin_ != nullptr) { | ||||||
|  |     LOG_PIN("  Enable Pin: ", this->enable_pin_); | ||||||
|  |   } | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Timeout: %u%s", this->timeout_us_, this->timeout_us_ > 0 ? "us" : " (no timeout)"); | ||||||
| } | } | ||||||
|  |  | ||||||
| void VL53L0XSensor::setup() { | void VL53L0XSensor::setup() { | ||||||
|  |   ESP_LOGD(TAG, "'%s' - setup BEGIN", this->name_.c_str()); | ||||||
|  |  | ||||||
|  |   if (!esphome::vl53l0x::VL53L0XSensor::enable_pin_setup_complete) { | ||||||
|  |     for (auto &vl53_sensor : vl53_sensors) { | ||||||
|  |       if (vl53_sensor->enable_pin_ != nullptr) { | ||||||
|  |         // Disable the enable pin to force vl53 to HW Standby mode | ||||||
|  |         ESP_LOGD(TAG, "i2c vl53l0x disable enable pins: GPIO%u", (vl53_sensor->enable_pin_)->get_pin()); | ||||||
|  |         // Set enable pin as OUTPUT and disable the enable pin to force vl53 to HW Standby mode | ||||||
|  |         vl53_sensor->enable_pin_->setup(); | ||||||
|  |         vl53_sensor->enable_pin_->digital_write(false); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     esphome::vl53l0x::VL53L0XSensor::enable_pin_setup_complete = true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (this->enable_pin_ != nullptr) { | ||||||
|  |     // Enable the enable pin to cause FW boot (to get back to 0x29 default address) | ||||||
|  |     this->enable_pin_->digital_write(true); | ||||||
|  |     delayMicroseconds(100); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Save the i2c address we want and force it to use the default 0x29 | ||||||
|  |   // until we finish setup, then re-address to final desired address. | ||||||
|  |   uint8_t final_address = address_; | ||||||
|  |   this->set_i2c_address(0x29); | ||||||
|  |  | ||||||
|   reg(0x89) |= 0x01; |   reg(0x89) |= 0x01; | ||||||
|   reg(0x88) = 0x00; |   reg(0x88) = 0x00; | ||||||
|  |  | ||||||
|   reg(0x80) = 0x01; |   reg(0x80) = 0x01; | ||||||
|   reg(0xFF) = 0x01; |   reg(0xFF) = 0x01; | ||||||
|   reg(0x00) = 0x00; |   reg(0x00) = 0x00; | ||||||
|   stop_variable_ = reg(0x91).get(); |   this->stop_variable_ = reg(0x91).get(); | ||||||
|  |  | ||||||
|   reg(0x00) = 0x01; |   reg(0x00) = 0x01; | ||||||
|   reg(0xFF) = 0x00; |   reg(0xFF) = 0x00; | ||||||
| @@ -52,8 +87,15 @@ void VL53L0XSensor::setup() { | |||||||
|   reg(0x94) = 0x6B; |   reg(0x94) = 0x6B; | ||||||
|   reg(0x83) = 0x00; |   reg(0x83) = 0x00; | ||||||
|  |  | ||||||
|   while (reg(0x83).get() == 0x00) |   this->timeout_start_us_ = micros(); | ||||||
|  |   while (reg(0x83).get() == 0x00) { | ||||||
|  |     if (this->timeout_us_ > 0 && ((uint16_t)(micros() - this->timeout_start_us_) > this->timeout_us_)) { | ||||||
|  |       ESP_LOGE(TAG, "'%s' - setup timeout", this->name_.c_str()); | ||||||
|  |       this->mark_failed(); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|     yield(); |     yield(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   reg(0x83) = 0x01; |   reg(0x83) = 0x01; | ||||||
|   uint8_t tmp = reg(0x92).get(); |   uint8_t tmp = reg(0x92).get(); | ||||||
| @@ -205,11 +247,22 @@ void VL53L0XSensor::setup() { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   reg(0x01) = 0xE8; |   reg(0x01) = 0xE8; | ||||||
|  |  | ||||||
|  |   // Set the sensor to the desired final address | ||||||
|  |   // The following is different for VL53L0X vs VL53L1X | ||||||
|  |   // I2C_SXXXX_DEVICE_ADDRESS = 0x8A for VL53L0X | ||||||
|  |   // I2C_SXXXX__DEVICE_ADDRESS = 0x0001 for VL53L1X | ||||||
|  |   reg(0x8A) = final_address & 0x7F; | ||||||
|  |   this->set_i2c_address(final_address); | ||||||
|  |  | ||||||
|  |   ESP_LOGD(TAG, "'%s' - setup END", this->name_.c_str()); | ||||||
| } | } | ||||||
| void VL53L0XSensor::update() { | void VL53L0XSensor::update() { | ||||||
|   if (this->initiated_read_ || this->waiting_for_interrupt_) { |   if (this->initiated_read_ || this->waiting_for_interrupt_) { | ||||||
|     this->publish_state(NAN); |     this->publish_state(NAN); | ||||||
|     this->status_set_warning(); |     this->status_momentary_warning("update", 5000); | ||||||
|  |     ESP_LOGW(TAG, "%s - update called before prior reading complete - initiated:%d waiting_for_interrupt:%d", | ||||||
|  |              this->name_.c_str(), this->initiated_read_, this->waiting_for_interrupt_); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // initiate single shot measurement |   // initiate single shot measurement | ||||||
| @@ -217,7 +270,7 @@ void VL53L0XSensor::update() { | |||||||
|   reg(0xFF) = 0x01; |   reg(0xFF) = 0x01; | ||||||
|  |  | ||||||
|   reg(0x00) = 0x00; |   reg(0x00) = 0x00; | ||||||
|   reg(0x91) = stop_variable_; |   reg(0x91) = this->stop_variable_; | ||||||
|   reg(0x00) = 0x01; |   reg(0x00) = 0x01; | ||||||
|   reg(0xFF) = 0x00; |   reg(0xFF) = 0x00; | ||||||
|   reg(0x80) = 0x00; |   reg(0x80) = 0x00; | ||||||
| @@ -246,7 +299,7 @@ void VL53L0XSensor::loop() { | |||||||
|       this->waiting_for_interrupt_ = false; |       this->waiting_for_interrupt_ = false; | ||||||
|  |  | ||||||
|       if (range_mm >= 8190) { |       if (range_mm >= 8190) { | ||||||
|         ESP_LOGW(TAG, "'%s' - Distance is out of range, please move the target closer", this->name_.c_str()); |         ESP_LOGD(TAG, "'%s' - Distance is out of range, please move the target closer", this->name_.c_str()); | ||||||
|         this->publish_state(NAN); |         this->publish_state(NAN); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <list> | ||||||
|  |  | ||||||
| #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" | ||||||
| @@ -20,6 +22,8 @@ struct SequenceStepTimeouts { | |||||||
|  |  | ||||||
| class VL53L0XSensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { | class VL53L0XSensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { | ||||||
|  public: |  public: | ||||||
|  |   VL53L0XSensor(); | ||||||
|  |  | ||||||
|   void setup() override; |   void setup() override; | ||||||
|  |  | ||||||
|   void dump_config() override; |   void dump_config() override; | ||||||
| @@ -30,6 +34,8 @@ class VL53L0XSensor : public sensor::Sensor, public PollingComponent, public i2c | |||||||
|  |  | ||||||
|   void set_signal_rate_limit(float signal_rate_limit) { signal_rate_limit_ = signal_rate_limit; } |   void set_signal_rate_limit(float signal_rate_limit) { signal_rate_limit_ = signal_rate_limit; } | ||||||
|   void set_long_range(bool long_range) { long_range_ = long_range; } |   void set_long_range(bool long_range) { long_range_ = long_range; } | ||||||
|  |   void set_timeout_us(uint32_t timeout_us) { this->timeout_us_ = timeout_us; } | ||||||
|  |   void set_enable_pin(GPIOPin *enable) { this->enable_pin_ = enable; } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   uint32_t get_measurement_timing_budget_() { |   uint32_t get_measurement_timing_budget_() { | ||||||
| @@ -249,10 +255,17 @@ class VL53L0XSensor : public sensor::Sensor, public PollingComponent, public i2c | |||||||
|  |  | ||||||
|   float signal_rate_limit_; |   float signal_rate_limit_; | ||||||
|   bool long_range_; |   bool long_range_; | ||||||
|  |   GPIOPin *enable_pin_{nullptr}; | ||||||
|   uint32_t measurement_timing_budget_us_; |   uint32_t measurement_timing_budget_us_; | ||||||
|   bool initiated_read_{false}; |   bool initiated_read_{false}; | ||||||
|   bool waiting_for_interrupt_{false}; |   bool waiting_for_interrupt_{false}; | ||||||
|   uint8_t stop_variable_; |   uint8_t stop_variable_; | ||||||
|  |  | ||||||
|  |   uint16_t timeout_start_us_; | ||||||
|  |   uint16_t timeout_us_{}; | ||||||
|  |  | ||||||
|  |   static std::list<VL53L0XSensor *> vl53_sensors; | ||||||
|  |   static bool enable_pin_setup_complete; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace vl53l0x | }  // namespace vl53l0x | ||||||
|   | |||||||
| @@ -229,6 +229,8 @@ sensor: | |||||||
|     name: 'VL53L0x Distance' |     name: 'VL53L0x Distance' | ||||||
|     address: 0x29 |     address: 0x29 | ||||||
|     update_interval: 60s |     update_interval: 60s | ||||||
|  |     enable_pin: GPIO13 | ||||||
|  |     timeout: 200us | ||||||
|   - platform: apds9960 |   - platform: apds9960 | ||||||
|     type: clear |     type: clear | ||||||
|     name: APDS9960 Clear |     name: APDS9960 Clear | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user