mirror of
https://github.com/esphome/esphome.git
synced 2024-11-28 12:46:22 +01:00
Add new sensor sen0501
This commit is contained in:
parent
d64e0ae704
commit
5a9763d20f
0
esphome/components/sen0501/__init__.py
Normal file
0
esphome/components/sen0501/__init__.py
Normal file
165
esphome/components/sen0501/sen0501.cpp
Normal file
165
esphome/components/sen0501/sen0501.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
#include "sen0501.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace sen0501 {
|
||||||
|
|
||||||
|
static const char *const TAG = "sen0501";
|
||||||
|
|
||||||
|
// Device Address
|
||||||
|
static const uint8_t SEN050X_DEFAULT_DEVICE_ADDRESS = 0x22;
|
||||||
|
// Board identification
|
||||||
|
static const uint16_t DEVICE_PID_GRAVITY = 0x01F5;
|
||||||
|
static const uint16_t DEVICE_PID_BREAKOUT = 0x01F4;
|
||||||
|
static const uint16_t DEVICE_VID = 0x3343;
|
||||||
|
// Device registers
|
||||||
|
static const uint16_t REG_PID = 0x0000;
|
||||||
|
static const uint16_t REG_VID = 0x0002;
|
||||||
|
static const uint16_t REG_DEVICE_ADDR = 0x0004;
|
||||||
|
static const uint16_t REG_UART_CTRL0 = 0x0006;
|
||||||
|
static const uint16_t EG_UART_CTRL1 = 0x0008;
|
||||||
|
static const uint16_t REG_VERSION = 0x000A;
|
||||||
|
// Data registers
|
||||||
|
static const uint16_t REG_ULTRAVIOLET_INTENSITY = 0x0010;
|
||||||
|
static const uint16_t REG_LUMINOUS_INTENSITY = 0x0012;
|
||||||
|
static const uint16_t REG_TEMP = 0x0014;
|
||||||
|
static const uint16_t REG_HUMIDITY = 0x0016;
|
||||||
|
static const uint16_t REG_ATMOSPHERIC_PRESSURE = 0x0018;
|
||||||
|
|
||||||
|
// PUBLIC
|
||||||
|
|
||||||
|
void sen0501Component::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up sen0501...");
|
||||||
|
uint8_t product_id_first_byte;
|
||||||
|
if (!this->read_byte(REG_PID, &product_id_first_byte)) {
|
||||||
|
this->error_code_ = COMMUNICATION_FAILED;
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
uint8_t buf[2];
|
||||||
|
this->read_bytes(REG_PID, buf, 2);
|
||||||
|
uint16_t product_id = buf[0] << 8 | buf[1];
|
||||||
|
if ((product_id != DEVICE_PID_GRAVITY) && (product_id != DEVICE_PID_BREAKOUT)) {
|
||||||
|
this->error_code_ = WRONG_DEVICE_ID;
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->read_bytes(REG_VID, buf, 2);
|
||||||
|
uint16_t vendor_id = buf[0] << 8 | buf[1];
|
||||||
|
if (vendor_id != DEVICE_VID) {
|
||||||
|
this->error_code_ = WRONG_VENDOR_ID;
|
||||||
|
this->mark_failed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::update() {
|
||||||
|
this->read_temperature_();
|
||||||
|
this->read_humidity_();
|
||||||
|
this->read_uv_intensity_();
|
||||||
|
this->read_luminous_intensity_();
|
||||||
|
this->read_atmospheric_pressure_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "DFRobot Environmental Sensor - sen0501:");
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
switch (this->error_code_) {
|
||||||
|
case COMMUNICATION_FAILED:
|
||||||
|
ESP_LOGE(TAG, "Communication with sen0501 failed!");
|
||||||
|
break;
|
||||||
|
case WRONG_DEVICE_ID:
|
||||||
|
ESP_LOGE(TAG, "Wrong device ID! Is it a sen0501?");
|
||||||
|
break;
|
||||||
|
case WRONG_VENDOR_ID:
|
||||||
|
ESP_LOGE(TAG, "Wrong vendor ID! Is it made by DFRobot(Zhiwei Robotics Corp)?");
|
||||||
|
break;
|
||||||
|
case NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
LOG_SENSOR(" ", "Temperature", this->temperature_);
|
||||||
|
LOG_SENSOR(" ", "Humidity", this->humidity_);
|
||||||
|
LOG_SENSOR(" ", "UV Intensity", this->uv_intensity_);
|
||||||
|
LOG_SENSOR(" ", "Luminous Intensity", this->luminous_intensity_);
|
||||||
|
LOG_SENSOR(" ", "Atmospheric Pressure", this->atmospheric_pressure_);
|
||||||
|
LOG_SENSOR(" ", "Elevation", this->elevation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sen0501Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
// PROTECTED
|
||||||
|
|
||||||
|
float sen0501Component::mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::read_temperature_() {
|
||||||
|
uint8_t buffer[2];
|
||||||
|
uint16_t data;
|
||||||
|
float temp;
|
||||||
|
read_bytes(REG_TEMP, buffer, 2);
|
||||||
|
data = buffer[0] << 8 | buffer[1];
|
||||||
|
temp = 175.0f * float(data) / 65536.0f - 45.0f;
|
||||||
|
this->temperature_->publish_state(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::read_humidity_() {
|
||||||
|
uint8_t buffer[2];
|
||||||
|
uint16_t data;
|
||||||
|
float humidity;
|
||||||
|
read_bytes(REG_HUMIDITY, buffer, 2);
|
||||||
|
data = buffer[0] << 8 | buffer[1];
|
||||||
|
humidity = (float) data * 100 / 65536;
|
||||||
|
this->humidity_->publish_state(humidity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::read_uv_intensity_() {
|
||||||
|
uint8_t buffer[2];
|
||||||
|
uint16_t uvLevel;
|
||||||
|
uint16_t version = 0;
|
||||||
|
float ultraviolet;
|
||||||
|
read_bytes(REG_VERSION, buffer, 2);
|
||||||
|
version = buffer[0] << 8 | buffer[1];
|
||||||
|
if (version == 0x1001) {
|
||||||
|
read_bytes(REG_ULTRAVIOLET_INTENSITY, buffer, 2);
|
||||||
|
uvLevel = buffer[0] << 8 | buffer[1];
|
||||||
|
ultraviolet = (float) uvLevel / 1800.0;
|
||||||
|
} else {
|
||||||
|
read_bytes(REG_ULTRAVIOLET_INTENSITY, buffer, 2);
|
||||||
|
uvLevel = buffer[0] << 8 | buffer[1];
|
||||||
|
float outputVoltage = 3.0 * uvLevel / 1024;
|
||||||
|
if (outputVoltage <= 0.99)
|
||||||
|
outputVoltage = 0.99;
|
||||||
|
else if (outputVoltage >= 2.99)
|
||||||
|
outputVoltage = 2.99;
|
||||||
|
ultraviolet = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0);
|
||||||
|
}
|
||||||
|
this->uv_intensity_->publish_state(ultraviolet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::read_luminous_intensity_() {
|
||||||
|
uint8_t buffer[2];
|
||||||
|
uint16_t data;
|
||||||
|
read_bytes(REG_LUMINOUS_INTENSITY, buffer, 2);
|
||||||
|
data = buffer[0] << 8 | buffer[1];
|
||||||
|
float luminous = data;
|
||||||
|
luminous = luminous * (1.0023f + luminous * (8.1488e-5f + luminous * (-9.3924e-9f + luminous * 6.0135e-13f)));
|
||||||
|
this->luminous_intensity_->publish_state(luminous);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sen0501Component::read_atmospheric_pressure_() {
|
||||||
|
uint8_t buffer[2];
|
||||||
|
uint16_t atmosphere;
|
||||||
|
read_bytes(REG_ATMOSPHERIC_PRESSURE, buffer, 2);
|
||||||
|
atmosphere = buffer[0] << 8 | buffer[1];
|
||||||
|
float elevation = 44330 * (1.0 - pow(atmosphere / 1015.0f, 0.1903));
|
||||||
|
this->atmospheric_pressure_->publish_state(atmosphere);
|
||||||
|
this->elevation_->publish_state(elevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sen0501
|
||||||
|
} // namespace esphome
|
52
esphome/components/sen0501/sen0501.h
Normal file
52
esphome/components/sen0501/sen0501.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/i2c/i2c.h"
|
||||||
|
|
||||||
|
// ref:
|
||||||
|
// https://github.com/DFRobot/DFRobot_EnvironmentalSensor
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace sen0501 {
|
||||||
|
|
||||||
|
class sen0501Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
|
public:
|
||||||
|
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; }
|
||||||
|
void set_humidity(sensor::Sensor *humidity) { humidity_ = humidity; }
|
||||||
|
void set_uv_intensity(sensor::Sensor *uv_intensity) { uv_intensity_ = uv_intensity; }
|
||||||
|
void set_luminous_intensity(sensor::Sensor *luminous_intensity) { luminous_intensity_ = luminous_intensity; }
|
||||||
|
void set_atmospheric_pressure(sensor::Sensor *atmospheric_pressure) { atmospheric_pressure_ = atmospheric_pressure; }
|
||||||
|
void set_elevation(sensor::Sensor *elevation) { elevation_ = elevation; }
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max);
|
||||||
|
|
||||||
|
void read_temperature_();
|
||||||
|
void read_humidity_();
|
||||||
|
void read_uv_intensity_();
|
||||||
|
void read_luminous_intensity_();
|
||||||
|
void read_atmospheric_pressure_();
|
||||||
|
|
||||||
|
sensor::Sensor *temperature_{nullptr};
|
||||||
|
sensor::Sensor *humidity_{nullptr};
|
||||||
|
sensor::Sensor *uv_intensity_{nullptr};
|
||||||
|
sensor::Sensor *luminous_intensity_{nullptr};
|
||||||
|
sensor::Sensor *atmospheric_pressure_{nullptr};
|
||||||
|
sensor::Sensor *elevation_{nullptr};
|
||||||
|
|
||||||
|
enum ErrorCode {
|
||||||
|
NONE = 0,
|
||||||
|
COMMUNICATION_FAILED,
|
||||||
|
WRONG_DEVICE_ID,
|
||||||
|
WRONG_VENDOR_ID,
|
||||||
|
} error_code_{NONE};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sen0501
|
||||||
|
} // namespace esphome
|
122
esphome/components/sen0501/sensor.py
Normal file
122
esphome/components/sen0501/sensor.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import i2c, sensor
|
||||||
|
from esphome.const import (
|
||||||
|
ICON_BRIGHTNESS_5,
|
||||||
|
ICON_ELEVATION,
|
||||||
|
ICON_GAUGE,
|
||||||
|
ICON_THERMOMETER,
|
||||||
|
ICON_UV_RADIATION,
|
||||||
|
ICON_WATER_PERCENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
UNIT_HECTOPASCAL,
|
||||||
|
UNIT_IRRADIANCE,
|
||||||
|
UNIT_LUX,
|
||||||
|
UNIT_METER,
|
||||||
|
UNIT_PERCENT,
|
||||||
|
DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||||
|
DEVICE_CLASS_DISTANCE,
|
||||||
|
DEVICE_CLASS_HUMIDITY,
|
||||||
|
DEVICE_CLASS_ILLUMINANCE,
|
||||||
|
DEVICE_CLASS_IRRADIANCE,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
CONF_ELEVATION,
|
||||||
|
CONF_HUMIDITY,
|
||||||
|
CONF_ID,
|
||||||
|
CONF_ILLUMINANCE,
|
||||||
|
CONF_TEMPERATURE,
|
||||||
|
CONF_PRESSURE,
|
||||||
|
CONF_UV_IRRADIANCE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@thetestspecimen"]
|
||||||
|
DEPENDENCIES = ["i2c"]
|
||||||
|
|
||||||
|
sen0501_ns = cg.esphome_ns.namespace("sen0501")
|
||||||
|
sen0501Component = sen0501_ns.class_(
|
||||||
|
"sen0501Component", cg.PollingComponent, i2c.I2CDevice
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(sen0501Component),
|
||||||
|
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
icon=ICON_THERMOMETER,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_PERCENT,
|
||||||
|
icon=ICON_WATER_PERCENT,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_UV_IRRADIANCE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_IRRADIANCE,
|
||||||
|
icon=ICON_UV_RADIATION,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_IRRADIANCE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_LUX,
|
||||||
|
icon=ICON_BRIGHTNESS_5,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_ILLUMINANCE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||||
|
icon=ICON_GAUGE,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ELEVATION): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_METER,
|
||||||
|
icon=ICON_ELEVATION,
|
||||||
|
accuracy_decimals=1,
|
||||||
|
device_class=DEVICE_CLASS_DISTANCE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(i2c.i2c_device_schema(0x22))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
if temperature_config := config.get(CONF_TEMPERATURE):
|
||||||
|
sens = await sensor.new_sensor(temperature_config)
|
||||||
|
cg.add(var.set_temperature(sens))
|
||||||
|
|
||||||
|
if humidity_config := config.get(CONF_HUMIDITY):
|
||||||
|
sens = await sensor.new_sensor(humidity_config)
|
||||||
|
cg.add(var.set_humidity(sens))
|
||||||
|
|
||||||
|
if uv_irradiance_config := config.get(CONF_UV_IRRADIANCE):
|
||||||
|
sens = await sensor.new_sensor(uv_irradiance_config)
|
||||||
|
cg.add(var.set_uv_intensity(sens))
|
||||||
|
|
||||||
|
if brightness_config := config.get(CONF_ILLUMINANCE):
|
||||||
|
sens = await sensor.new_sensor(brightness_config)
|
||||||
|
cg.add(var.set_luminous_intensity(sens))
|
||||||
|
|
||||||
|
if pressure_config := config.get(CONF_PRESSURE):
|
||||||
|
sens = await sensor.new_sensor(pressure_config)
|
||||||
|
cg.add(var.set_atmospheric_pressure(sens))
|
||||||
|
|
||||||
|
if elevation_config := config.get(CONF_ELEVATION):
|
||||||
|
sens = await sensor.new_sensor(elevation_config)
|
||||||
|
cg.add(var.set_elevation(sens))
|
Loading…
Reference in New Issue
Block a user