mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 16:38:16 +01:00
Fix AHT10 / AHT20 communication (#5198)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
259a6d52e1
commit
03baaa94a8
3 changed files with 51 additions and 21 deletions
|
@ -21,37 +21,50 @@ namespace esphome {
|
||||||
namespace aht10 {
|
namespace aht10 {
|
||||||
|
|
||||||
static const char *const TAG = "aht10";
|
static const char *const TAG = "aht10";
|
||||||
static const uint8_t AHT10_CALIBRATE_CMD[] = {0xE1};
|
static const size_t SIZE_CALIBRATE_CMD = 3;
|
||||||
|
static const uint8_t AHT10_CALIBRATE_CMD[] = {0xE1, 0x08, 0x00};
|
||||||
|
static const uint8_t AHT20_CALIBRATE_CMD[] = {0xBE, 0x08, 0x00};
|
||||||
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
|
static const uint8_t AHT10_MEASURE_CMD[] = {0xAC, 0x33, 0x00};
|
||||||
static const uint8_t AHT10_DEFAULT_DELAY = 5; // ms, for calibration and temperature measurement
|
static const uint8_t AHT10_DEFAULT_DELAY = 5; // ms, for calibration and temperature measurement
|
||||||
static const uint8_t AHT10_HUMIDITY_DELAY = 30; // ms
|
static const uint8_t AHT10_HUMIDITY_DELAY = 30; // ms
|
||||||
static const uint8_t AHT10_ATTEMPTS = 3; // safety margin, normally 3 attempts are enough: 3*30=90ms
|
static const uint8_t AHT10_ATTEMPTS = 3; // safety margin, normally 3 attempts are enough: 3*30=90ms
|
||||||
|
static const uint8_t AHT10_CAL_ATTEMPTS = 10;
|
||||||
|
static const uint8_t AHT10_STATUS_BUSY = 0x80;
|
||||||
|
|
||||||
void AHT10Component::setup() {
|
void AHT10Component::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up AHT10...");
|
const uint8_t *calibrate_cmd;
|
||||||
|
switch (this->variant_) {
|
||||||
|
case AHT10Variant::AHT20:
|
||||||
|
calibrate_cmd = AHT20_CALIBRATE_CMD;
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up AHT20");
|
||||||
|
break;
|
||||||
|
case AHT10Variant::AHT10:
|
||||||
|
default:
|
||||||
|
calibrate_cmd = AHT10_CALIBRATE_CMD;
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up AHT10");
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->write_bytes(0, AHT10_CALIBRATE_CMD, sizeof(AHT10_CALIBRATE_CMD))) {
|
if (this->write(calibrate_cmd, SIZE_CALIBRATE_CMD) != i2c::ERROR_OK) {
|
||||||
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t data = 0;
|
uint8_t data = AHT10_STATUS_BUSY;
|
||||||
if (this->write(&data, 1) != i2c::ERROR_OK) {
|
int cal_attempts = 0;
|
||||||
ESP_LOGD(TAG, "Communication with AHT10 failed!");
|
while (data & AHT10_STATUS_BUSY) {
|
||||||
this->mark_failed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
delay(AHT10_DEFAULT_DELAY);
|
delay(AHT10_DEFAULT_DELAY);
|
||||||
if (this->read(&data, 1) != i2c::ERROR_OK) {
|
if (this->read(&data, 1) != i2c::ERROR_OK) {
|
||||||
ESP_LOGD(TAG, "Communication with AHT10 failed!");
|
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->read(&data, 1) != i2c::ERROR_OK) {
|
++cal_attempts;
|
||||||
ESP_LOGD(TAG, "Communication with AHT10 failed!");
|
if (cal_attempts > AHT10_CAL_ATTEMPTS) {
|
||||||
|
ESP_LOGE(TAG, "AHT10 calibration timed out!");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ((data & 0x68) != 0x08) { // Bit[6:5] = 0b00, NORMAL mode and Bit[3] = 0b1, CALIBRATED
|
if ((data & 0x68) != 0x08) { // Bit[6:5] = 0b00, NORMAL mode and Bit[3] = 0b1, CALIBRATED
|
||||||
ESP_LOGE(TAG, "AHT10 calibration failed!");
|
ESP_LOGE(TAG, "AHT10 calibration failed!");
|
||||||
this->mark_failed();
|
this->mark_failed();
|
||||||
|
@ -62,7 +75,7 @@ void AHT10Component::setup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AHT10Component::update() {
|
void AHT10Component::update() {
|
||||||
if (!this->write_bytes(0, AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD))) {
|
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
|
||||||
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return;
|
||||||
|
@ -89,7 +102,7 @@ void AHT10Component::update() {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying...");
|
ESP_LOGD(TAG, "ATH10 Unrealistic humidity (0x0), retrying...");
|
||||||
if (!this->write_bytes(0, AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD))) {
|
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
|
||||||
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
ESP_LOGE(TAG, "Communication with AHT10 failed!");
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#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"
|
||||||
|
@ -7,12 +9,15 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace aht10 {
|
namespace aht10 {
|
||||||
|
|
||||||
|
enum AHT10Variant { AHT10, AHT20 };
|
||||||
|
|
||||||
class AHT10Component : public PollingComponent, public i2c::I2CDevice {
|
class AHT10Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
|
void set_variant(AHT10Variant variant) { this->variant_ = variant; }
|
||||||
|
|
||||||
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||||
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
|
void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
|
||||||
|
@ -20,6 +25,7 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
protected:
|
protected:
|
||||||
sensor::Sensor *temperature_sensor_{nullptr};
|
sensor::Sensor *temperature_sensor_{nullptr};
|
||||||
sensor::Sensor *humidity_sensor_{nullptr};
|
sensor::Sensor *humidity_sensor_{nullptr};
|
||||||
|
AHT10Variant variant_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aht10
|
} // namespace aht10
|
||||||
|
|
|
@ -10,6 +10,7 @@ from esphome.const import (
|
||||||
STATE_CLASS_MEASUREMENT,
|
STATE_CLASS_MEASUREMENT,
|
||||||
UNIT_CELSIUS,
|
UNIT_CELSIUS,
|
||||||
UNIT_PERCENT,
|
UNIT_PERCENT,
|
||||||
|
CONF_VARIANT,
|
||||||
)
|
)
|
||||||
|
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
@ -17,6 +18,12 @@ DEPENDENCIES = ["i2c"]
|
||||||
aht10_ns = cg.esphome_ns.namespace("aht10")
|
aht10_ns = cg.esphome_ns.namespace("aht10")
|
||||||
AHT10Component = aht10_ns.class_("AHT10Component", cg.PollingComponent, i2c.I2CDevice)
|
AHT10Component = aht10_ns.class_("AHT10Component", cg.PollingComponent, i2c.I2CDevice)
|
||||||
|
|
||||||
|
AHT10Variant = aht10_ns.enum("AHT10Variant")
|
||||||
|
AHT10_VARIANTS = {
|
||||||
|
"AHT10": AHT10Variant.AHT10,
|
||||||
|
"AHT20": AHT10Variant.AHT20,
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
CONFIG_SCHEMA = (
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
|
@ -33,6 +40,9 @@ CONFIG_SCHEMA = (
|
||||||
device_class=DEVICE_CLASS_HUMIDITY,
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_VARIANT, default="AHT10"): cv.enum(
|
||||||
|
AHT10_VARIANTS, upper=True
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("60s"))
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
@ -44,6 +54,7 @@ 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_variant(config[CONF_VARIANT]))
|
||||||
|
|
||||||
if temperature := config.get(CONF_TEMPERATURE):
|
if temperature := config.get(CONF_TEMPERATURE):
|
||||||
sens = await sensor.new_sensor(temperature)
|
sens = await sensor.new_sensor(temperature)
|
||||||
|
|
Loading…
Reference in a new issue