mirror of
https://github.com/esphome/esphome.git
synced 2025-01-22 12:26:01 +01:00
Merge branch 'esphome:dev' into dev
This commit is contained in:
commit
489d5952ef
19 changed files with 304 additions and 93 deletions
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -65,7 +65,7 @@ jobs:
|
|||
pip3 install build
|
||||
python3 -m build
|
||||
- name: Publish
|
||||
uses: pypa/gh-action-pypi-publish@v1.10.1
|
||||
uses: pypa/gh-action-pypi-publish@v1.10.2
|
||||
|
||||
deploy-docker:
|
||||
name: Build ESPHome ${{ matrix.platform }}
|
||||
|
|
|
@ -152,6 +152,7 @@ esphome/components/ft63x6/* @gpambrozio
|
|||
esphome/components/gcja5/* @gcormier
|
||||
esphome/components/gdk101/* @Szewcson
|
||||
esphome/components/globals/* @esphome/core
|
||||
esphome/components/gp2y1010au0f/* @zry98
|
||||
esphome/components/gp8403/* @jesserockz
|
||||
esphome/components/gpio/* @esphome/core
|
||||
esphome/components/gpio/one_wire/* @ssieb
|
||||
|
|
|
@ -7,3 +7,5 @@
|
|||
For issues, please go to [the issue tracker](https://github.com/esphome/issues/issues).
|
||||
|
||||
For feature requests, please see [feature requests](https://github.com/esphome/feature-requests/issues).
|
||||
|
||||
[![ESPHome - A project from the Open Home Foundation](https://www.openhomefoundation.org/badges/esphome.png)](https://www.openhomefoundation.org/)
|
||||
|
|
|
@ -26,7 +26,6 @@ from esphome.cpp_generator import MockObjClass
|
|||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@rfdarter", "@jesserockz"]
|
||||
DEPENDENCIES = ["time"]
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
|
@ -62,20 +61,28 @@ DATETIME_MODES = [
|
|||
]
|
||||
|
||||
|
||||
_DATETIME_SCHEMA = (
|
||||
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
||||
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
||||
.extend(
|
||||
def _validate_time_present(config):
|
||||
config = config.copy()
|
||||
if CONF_ON_TIME in config and CONF_TIME_ID not in config:
|
||||
time_id = cv.use_id(time.RealTimeClock)(None)
|
||||
config[CONF_TIME_ID] = time_id
|
||||
return config
|
||||
|
||||
|
||||
_DATETIME_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
web_server.WEBSERVER_SORTING_SCHEMA,
|
||||
cv.MQTT_COMMAND_COMPONENT_SCHEMA,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_ON_VALUE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DateTimeStateTrigger),
|
||||
}
|
||||
),
|
||||
cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
|
||||
cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
|
||||
}
|
||||
)
|
||||
)
|
||||
),
|
||||
).add_extra(_validate_time_present)
|
||||
|
||||
|
||||
def date_schema(class_: MockObjClass) -> cv.Schema:
|
||||
|
@ -138,8 +145,9 @@ async def setup_datetime_core_(var, config):
|
|||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [(cg.ESPTime, "x")], conf)
|
||||
|
||||
rtc = await cg.get_variable(config[CONF_TIME_ID])
|
||||
cg.add(var.set_rtc(rtc))
|
||||
if CONF_TIME_ID in config:
|
||||
rtc = await cg.get_variable(config[CONF_TIME_ID])
|
||||
cg.add(var.set_rtc(rtc))
|
||||
|
||||
for conf in config.get(CONF_ON_TIME, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/time.h"
|
||||
|
||||
#ifdef USE_TIME
|
||||
#include "esphome/components/time/real_time_clock.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace datetime {
|
||||
|
@ -19,23 +20,29 @@ class DateTimeBase : public EntityBase {
|
|||
|
||||
void add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); }
|
||||
|
||||
#ifdef USE_TIME
|
||||
void set_rtc(time::RealTimeClock *rtc) { this->rtc_ = rtc; }
|
||||
time::RealTimeClock *get_rtc() const { return this->rtc_; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
CallbackManager<void()> state_callback_;
|
||||
|
||||
#ifdef USE_TIME
|
||||
time::RealTimeClock *rtc_;
|
||||
#endif
|
||||
|
||||
bool has_state_{false};
|
||||
};
|
||||
|
||||
#ifdef USE_TIME
|
||||
class DateTimeStateTrigger : public Trigger<ESPTime> {
|
||||
public:
|
||||
explicit DateTimeStateTrigger(DateTimeBase *parent) {
|
||||
parent->add_on_state_callback([this, parent]() { this->trigger(parent->state_as_esptime()); });
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace datetime
|
||||
} // namespace esphome
|
||||
|
|
|
@ -192,6 +192,7 @@ void DateTimeEntityRestoreState::apply(DateTimeEntity *time) {
|
|||
time->publish_state();
|
||||
}
|
||||
|
||||
#ifdef USE_TIME
|
||||
static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider
|
||||
// there has been a drastic time synchronization
|
||||
|
||||
|
@ -245,6 +246,7 @@ bool OnDateTimeTrigger::matches_(const ESPTime &time) const {
|
|||
time.day_of_month == this->parent_->day && time.hour == this->parent_->hour &&
|
||||
time.minute == this->parent_->minute && time.second == this->parent_->second;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace datetime
|
||||
} // namespace esphome
|
||||
|
|
|
@ -134,6 +134,7 @@ template<typename... Ts> class DateTimeSetAction : public Action<Ts...>, public
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef USE_TIME
|
||||
class OnDateTimeTrigger : public Trigger<>, public Component, public Parented<DateTimeEntity> {
|
||||
public:
|
||||
void loop() override;
|
||||
|
@ -143,6 +144,7 @@ class OnDateTimeTrigger : public Trigger<>, public Component, public Parented<Da
|
|||
|
||||
optional<ESPTime> last_check_;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace datetime
|
||||
} // namespace esphome
|
||||
|
|
|
@ -94,6 +94,7 @@ void TimeEntityRestoreState::apply(TimeEntity *time) {
|
|||
time->publish_state();
|
||||
}
|
||||
|
||||
#ifdef USE_TIME
|
||||
static const int MAX_TIMESTAMP_DRIFT = 900; // how far can the clock drift before we consider
|
||||
// there has been a drastic time synchronization
|
||||
|
||||
|
@ -145,6 +146,7 @@ bool OnTimeTrigger::matches_(const ESPTime &time) const {
|
|||
return time.is_valid() && time.hour == this->parent_->hour && time.minute == this->parent_->minute &&
|
||||
time.second == this->parent_->second;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace datetime
|
||||
} // namespace esphome
|
||||
|
|
|
@ -113,6 +113,7 @@ template<typename... Ts> class TimeSetAction : public Action<Ts...>, public Pare
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef USE_TIME
|
||||
class OnTimeTrigger : public Trigger<>, public Component, public Parented<TimeEntity> {
|
||||
public:
|
||||
void loop() override;
|
||||
|
@ -122,6 +123,7 @@ class OnTimeTrigger : public Trigger<>, public Component, public Parented<TimeEn
|
|||
|
||||
optional<ESPTime> last_check_;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace datetime
|
||||
} // namespace esphome
|
||||
|
|
0
esphome/components/gp2y1010au0f/__init__.py
Normal file
0
esphome/components/gp2y1010au0f/__init__.py
Normal file
67
esphome/components/gp2y1010au0f/gp2y1010au0f.cpp
Normal file
67
esphome/components/gp2y1010au0f/gp2y1010au0f.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "gp2y1010au0f.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace gp2y1010au0f {
|
||||
|
||||
static const char *const TAG = "gp2y1010au0f";
|
||||
static const float MIN_VOLTAGE = 0.0f;
|
||||
static const float MAX_VOLTAGE = 4.0f;
|
||||
|
||||
void GP2Y1010AU0FSensor::dump_config() {
|
||||
LOG_SENSOR("", "Sharp GP2Y1010AU0F PM2.5 Sensor", this);
|
||||
ESP_LOGCONFIG(TAG, " Sampling duration: %" PRId32 " ms", this->sample_duration_);
|
||||
ESP_LOGCONFIG(TAG, " ADC voltage multiplier: %.3f", this->voltage_multiplier_);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void GP2Y1010AU0FSensor::update() {
|
||||
is_sampling_ = true;
|
||||
|
||||
this->set_timeout("read", this->sample_duration_, [this]() {
|
||||
this->is_sampling_ = false;
|
||||
if (this->num_samples_ == 0)
|
||||
return;
|
||||
|
||||
float mean = this->sample_sum_ / float(this->num_samples_);
|
||||
ESP_LOGD(TAG, "ADC read voltage: %.3f V (mean from %" PRId32 " samples)", mean, this->num_samples_);
|
||||
|
||||
// PM2.5 calculation
|
||||
// ref: https://www.howmuchsnow.com/arduino/airquality/
|
||||
int16_t pm_2_5_value = 170 * mean;
|
||||
this->publish_state(pm_2_5_value);
|
||||
});
|
||||
|
||||
// reset readings
|
||||
this->num_samples_ = 0;
|
||||
this->sample_sum_ = 0.0f;
|
||||
}
|
||||
|
||||
void GP2Y1010AU0FSensor::loop() {
|
||||
if (!this->is_sampling_)
|
||||
return;
|
||||
|
||||
// enable the internal IR LED
|
||||
this->led_output_->turn_on();
|
||||
// wait for the sensor to stabilize
|
||||
delayMicroseconds(this->sample_wait_before_);
|
||||
// perform a single sample
|
||||
float read_voltage = this->source_->sample();
|
||||
// disable the internal IR LED
|
||||
this->led_output_->turn_off();
|
||||
|
||||
if (std::isnan(read_voltage))
|
||||
return;
|
||||
read_voltage = read_voltage * this->voltage_multiplier_ - this->voltage_offset_;
|
||||
if (read_voltage < MIN_VOLTAGE || read_voltage > MAX_VOLTAGE)
|
||||
return;
|
||||
|
||||
this->num_samples_++;
|
||||
this->sample_sum_ += read_voltage;
|
||||
}
|
||||
|
||||
} // namespace gp2y1010au0f
|
||||
} // namespace esphome
|
52
esphome/components/gp2y1010au0f/gp2y1010au0f.h
Normal file
52
esphome/components/gp2y1010au0f/gp2y1010au0f.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||
#include "esphome/components/output/binary_output.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace gp2y1010au0f {
|
||||
|
||||
class GP2Y1010AU0FSensor : public sensor::Sensor, public PollingComponent {
|
||||
public:
|
||||
void update() override;
|
||||
void loop() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override {
|
||||
// after the base sensor has been initialized
|
||||
return setup_priority::DATA - 1.0f;
|
||||
}
|
||||
|
||||
void set_adc_source(voltage_sampler::VoltageSampler *source) { source_ = source; }
|
||||
void set_voltage_refs(float offset, float multiplier) {
|
||||
this->voltage_offset_ = offset;
|
||||
this->voltage_multiplier_ = multiplier;
|
||||
}
|
||||
void set_led_output(output::BinaryOutput *output) { led_output_ = output; }
|
||||
|
||||
protected:
|
||||
// duration in ms of the sampling phase
|
||||
uint32_t sample_duration_ = 100;
|
||||
// duration in us of the wait before sampling
|
||||
// ref: https://global.sharp/products/device/lineup/data/pdf/datasheet/gp2y1010au_appl_e.pdf
|
||||
uint32_t sample_wait_before_ = 280;
|
||||
// duration in us of the wait after sampling
|
||||
// it seems no need to delay on purpose since one ADC sampling takes longer than that (300-400 us on ESP8266)
|
||||
// uint32_t sample_wait_after_ = 40;
|
||||
// the sampling source to read voltage from
|
||||
voltage_sampler::VoltageSampler *source_;
|
||||
// ADC voltage reading offset
|
||||
float voltage_offset_ = 0.0f;
|
||||
// ADC voltage reading multiplier
|
||||
float voltage_multiplier_ = 1.0f;
|
||||
// the binary output to control the sampling LED
|
||||
output::BinaryOutput *led_output_;
|
||||
|
||||
float sample_sum_ = 0.0f;
|
||||
uint32_t num_samples_ = 0;
|
||||
bool is_sampling_ = false;
|
||||
};
|
||||
|
||||
} // namespace gp2y1010au0f
|
||||
} // namespace esphome
|
61
esphome/components/gp2y1010au0f/sensor.py
Normal file
61
esphome/components/gp2y1010au0f/sensor.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, voltage_sampler, output
|
||||
from esphome.const import (
|
||||
CONF_SENSOR,
|
||||
CONF_OUTPUT,
|
||||
DEVICE_CLASS_PM25,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_MICROGRAMS_PER_CUBIC_METER,
|
||||
ICON_CHEMICAL_WEAPON,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["output"]
|
||||
AUTO_LOAD = ["voltage_sampler"]
|
||||
CODEOWNERS = ["@zry98"]
|
||||
|
||||
CONF_ADC_VOLTAGE_OFFSET = "adc_voltage_offset"
|
||||
CONF_ADC_VOLTAGE_MULTIPLIER = "adc_voltage_multiplier"
|
||||
|
||||
gp2y1010au0f_ns = cg.esphome_ns.namespace("gp2y1010au0f")
|
||||
GP2Y1010AU0FSensor = gp2y1010au0f_ns.class_(
|
||||
"GP2Y1010AU0FSensor", sensor.Sensor, cg.PollingComponent
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(
|
||||
GP2Y1010AU0FSensor,
|
||||
unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER,
|
||||
accuracy_decimals=0,
|
||||
device_class=DEVICE_CLASS_PM25,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
icon=ICON_CHEMICAL_WEAPON,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler),
|
||||
cv.Optional(CONF_ADC_VOLTAGE_OFFSET, default=0.0): cv.float_,
|
||||
cv.Optional(CONF_ADC_VOLTAGE_MULTIPLIER, default=1.0): cv.float_,
|
||||
cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await sensor.new_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
|
||||
# the ADC sensor to read voltage from
|
||||
adc_sensor = await cg.get_variable(config[CONF_SENSOR])
|
||||
cg.add(var.set_adc_source(adc_sensor))
|
||||
cg.add(
|
||||
var.set_voltage_refs(
|
||||
config[CONF_ADC_VOLTAGE_OFFSET], config[CONF_ADC_VOLTAGE_MULTIPLIER]
|
||||
)
|
||||
)
|
||||
|
||||
# the binary output to control the module's internal IR LED
|
||||
led_output = await cg.get_variable(config[CONF_OUTPUT])
|
||||
cg.add(var.set_led_output(led_output))
|
|
@ -71,6 +71,14 @@ def _format_framework_arduino_version(ver: cv.Version) -> str:
|
|||
# return f"~1.{ver.major}{ver.minor:02d}{ver.patch:02d}.0"
|
||||
|
||||
|
||||
def _parse_platform_version(value):
|
||||
value = cv.string(value)
|
||||
if value.startswith("http"):
|
||||
return value
|
||||
|
||||
return f"https://github.com/maxgerhardt/platform-raspberrypi.git#{value}"
|
||||
|
||||
|
||||
# NOTE: Keep this in mind when updating the recommended version:
|
||||
# * The new version needs to be thoroughly validated before changing the
|
||||
# recommended version as otherwise a bunch of devices could be bricked
|
||||
|
@ -82,10 +90,9 @@ def _format_framework_arduino_version(ver: cv.Version) -> str:
|
|||
# - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico
|
||||
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 9, 4)
|
||||
|
||||
# The platformio/raspberrypi version to use for arduino frameworks
|
||||
# - https://github.com/platformio/platform-raspberrypi/releases
|
||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/raspberrypi
|
||||
ARDUINO_PLATFORM_VERSION = cv.Version(1, 13, 0)
|
||||
# The raspberrypi platform version to use for arduino frameworks
|
||||
# - https://github.com/maxgerhardt/platform-raspberrypi/tags
|
||||
RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.2.0-gcc12"
|
||||
|
||||
|
||||
def _arduino_check_versions(value):
|
||||
|
@ -111,7 +118,8 @@ def _arduino_check_versions(value):
|
|||
value[CONF_SOURCE] = source or _format_framework_arduino_version(version)
|
||||
|
||||
value[CONF_PLATFORM_VERSION] = value.get(
|
||||
CONF_PLATFORM_VERSION, _parse_platform_version(str(ARDUINO_PLATFORM_VERSION))
|
||||
CONF_PLATFORM_VERSION,
|
||||
_parse_platform_version(RECOMMENDED_ARDUINO_PLATFORM_VERSION),
|
||||
)
|
||||
|
||||
if version != RECOMMENDED_ARDUINO_FRAMEWORK_VERSION:
|
||||
|
@ -122,15 +130,6 @@ def _arduino_check_versions(value):
|
|||
return value
|
||||
|
||||
|
||||
def _parse_platform_version(value):
|
||||
try:
|
||||
# if platform version is a valid version constraint, prefix the default package
|
||||
cv.platformio_version_constraint(value)
|
||||
return f"platformio/raspberrypi@{value}"
|
||||
except cv.Invalid:
|
||||
return value
|
||||
|
||||
|
||||
ARDUINO_FRAMEWORK_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include <algorithm>
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace tcs34725 {
|
||||
|
@ -14,10 +15,7 @@ static const uint8_t TCS34725_REGISTER_ID = TCS34725_COMMAND_BIT | 0x12;
|
|||
static const uint8_t TCS34725_REGISTER_ATIME = TCS34725_COMMAND_BIT | 0x01;
|
||||
static const uint8_t TCS34725_REGISTER_CONTROL = TCS34725_COMMAND_BIT | 0x0F;
|
||||
static const uint8_t TCS34725_REGISTER_ENABLE = TCS34725_COMMAND_BIT | 0x00;
|
||||
static const uint8_t TCS34725_REGISTER_CDATAL = TCS34725_COMMAND_BIT | 0x14;
|
||||
static const uint8_t TCS34725_REGISTER_RDATAL = TCS34725_COMMAND_BIT | 0x16;
|
||||
static const uint8_t TCS34725_REGISTER_GDATAL = TCS34725_COMMAND_BIT | 0x18;
|
||||
static const uint8_t TCS34725_REGISTER_BDATAL = TCS34725_COMMAND_BIT | 0x1A;
|
||||
static const uint8_t TCS34725_REGISTER_CRGBDATAL = TCS34725_COMMAND_BIT | 0x14;
|
||||
|
||||
void TCS34725Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up TCS34725...");
|
||||
|
@ -75,20 +73,21 @@ float TCS34725Component::get_setup_priority() const { return setup_priority::DAT
|
|||
* @return Color temperature in degrees Kelvin
|
||||
*/
|
||||
void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, uint16_t b, uint16_t c) {
|
||||
float r2, g2, b2; /* RGB values minus IR component */
|
||||
float sat; /* Digital saturation level */
|
||||
float ir; /* Inferred IR content */
|
||||
float sat; /* Digital saturation level */
|
||||
|
||||
this->illuminance_ = 0; // Assign 0 value before calculation
|
||||
this->color_temperature_ = 0;
|
||||
this->illuminance_ = NAN;
|
||||
this->color_temperature_ = NAN;
|
||||
|
||||
const float ga = this->glass_attenuation_; // Glass Attenuation Factor
|
||||
static const float DF = 310.f; // Device Factor
|
||||
static const float R_COEF = 0.136f; //
|
||||
static const float G_COEF = 1.f; // used in lux computation
|
||||
static const float B_COEF = -0.444f; //
|
||||
static const float CT_COEF = 3810.f; // Color Temperature Coefficient
|
||||
static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset
|
||||
const float ga = this->glass_attenuation_; // Glass Attenuation Factor
|
||||
static const float DF = 310.f; // Device Factor
|
||||
static const float R_COEF = 0.136f; //
|
||||
static const float G_COEF = 1.f; // used in lux computation
|
||||
static const float B_COEF = -0.444f; //
|
||||
static const float CT_COEF = 3810.f; // Color Temperature Coefficient
|
||||
static const float CT_OFFSET = 1391.f; // Color Temperatuer Offset
|
||||
static const float MAX_ILLUMINANCE = 100000.0f; // Cap illuminance at 100,000 lux
|
||||
static const float MAX_COLOR_TEMPERATURE = 15000.0f; // Maximum expected color temperature in Kelvin
|
||||
static const float MIN_COLOR_TEMPERATURE = 1000.0f; // Maximum reasonable color temperature in Kelvin
|
||||
|
||||
if (c == 0) {
|
||||
return;
|
||||
|
@ -139,69 +138,66 @@ void TCS34725Component::calculate_temperature_and_lux_(uint16_t r, uint16_t g, u
|
|||
if (c >= sat) {
|
||||
if (this->integration_time_auto_) {
|
||||
ESP_LOGI(TAG, "Saturation too high, sample discarded, autogain ongoing");
|
||||
return;
|
||||
} else {
|
||||
ESP_LOGW(
|
||||
TAG,
|
||||
"Saturation too high, sample with saturation %.1f and clear %d treat values carefully or use grey filter",
|
||||
sat, c);
|
||||
}
|
||||
}
|
||||
|
||||
/* AMS RGB sensors have no IR channel, so the IR content must be */
|
||||
/* calculated indirectly. */
|
||||
ir = ((r + g + b) > c) ? (r + g + b - c) / 2 : 0;
|
||||
|
||||
/* Remove the IR component from the raw RGB values */
|
||||
r2 = r - ir;
|
||||
g2 = g - ir;
|
||||
b2 = b - ir;
|
||||
|
||||
// discarding super low values? not recemmonded, and avoided by using auto gain.
|
||||
if (r2 == 0) {
|
||||
// legacy code
|
||||
if (!this->integration_time_auto_) {
|
||||
ESP_LOGW(TAG,
|
||||
"No light detected on red channel, switch to auto gain or adjust timing, values will be unreliable");
|
||||
"Saturation too high, sample with saturation %.1f and clear %d lux/color temperature cannot reliably "
|
||||
"calculated, reduce integration/gain or use a grey filter.",
|
||||
sat, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Lux Calculation (DN40 3.2)
|
||||
|
||||
float g1 = R_COEF * r2 + G_COEF * g2 + B_COEF * b2;
|
||||
float g1 = R_COEF * (float) r + G_COEF * (float) g + B_COEF * (float) b;
|
||||
float cpl = (this->integration_time_ * this->gain_) / (ga * DF);
|
||||
this->illuminance_ = g1 / cpl;
|
||||
|
||||
this->illuminance_ = std::max(g1 / cpl, 0.0f);
|
||||
|
||||
if (this->illuminance_ > MAX_ILLUMINANCE) {
|
||||
ESP_LOGW(TAG, "Calculated illuminance greater than limit (%f), setting to NAN", this->illuminance_);
|
||||
this->illuminance_ = NAN;
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
ESP_LOGW(TAG, "Red channel is zero, cannot compute color temperature");
|
||||
return;
|
||||
}
|
||||
|
||||
// Color Temperature Calculation (DN40)
|
||||
/* A simple method of measuring color temp is to use the ratio of blue */
|
||||
/* to red light, taking IR cancellation into account. */
|
||||
this->color_temperature_ = (CT_COEF * b2) / /** Color temp coefficient. */
|
||||
r2 +
|
||||
CT_OFFSET; /** Color temp offset. */
|
||||
/* to red light. */
|
||||
|
||||
this->color_temperature_ = (CT_COEF * (float) b) / (float) r + CT_OFFSET;
|
||||
|
||||
// Ensure the color temperature stays within reasonable bounds
|
||||
if (this->color_temperature_ < MIN_COLOR_TEMPERATURE) {
|
||||
ESP_LOGW(TAG, "Calculated color temperature value too low (%f), setting to NAN", this->color_temperature_);
|
||||
this->color_temperature_ = NAN;
|
||||
} else if (this->color_temperature_ > MAX_COLOR_TEMPERATURE) {
|
||||
ESP_LOGW(TAG, "Calculated color temperature value too high (%f), setting to NAN", this->color_temperature_);
|
||||
this->color_temperature_ = NAN;
|
||||
}
|
||||
}
|
||||
|
||||
void TCS34725Component::update() {
|
||||
uint16_t raw_c;
|
||||
uint16_t raw_r;
|
||||
uint16_t raw_g;
|
||||
uint16_t raw_b;
|
||||
uint8_t data[8]; // Buffer to hold the 8 bytes (2 bytes for each of the 4 channels)
|
||||
|
||||
if (this->read_data_register_(TCS34725_REGISTER_CDATAL, raw_c) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
if (this->read_data_register_(TCS34725_REGISTER_RDATAL, raw_r) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
if (this->read_data_register_(TCS34725_REGISTER_GDATAL, raw_g) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
if (this->read_data_register_(TCS34725_REGISTER_BDATAL, raw_b) != i2c::ERROR_OK) {
|
||||
// Perform burst
|
||||
if (this->read_register(TCS34725_REGISTER_CRGBDATAL, data, 8) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
ESP_LOGW(TAG, "Error reading TCS34725 sensor data");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract the data
|
||||
uint16_t raw_c = encode_uint16(data[1], data[0]); // Clear channel
|
||||
uint16_t raw_r = encode_uint16(data[3], data[2]); // Red channel
|
||||
uint16_t raw_g = encode_uint16(data[5], data[4]); // Green channel
|
||||
uint16_t raw_b = encode_uint16(data[7], data[6]); // Blue channel
|
||||
|
||||
ESP_LOGV(TAG, "Raw values clear=%d red=%d green=%d blue=%d", raw_c, raw_r, raw_g, raw_b);
|
||||
|
||||
float channel_c;
|
||||
|
|
|
@ -90,9 +90,6 @@ esp32:
|
|||
RP2040_CONFIG = """
|
||||
rp2040:
|
||||
board: {board}
|
||||
framework:
|
||||
# Required until https://github.com/platformio/platform-raspberrypi/pull/36 is merged
|
||||
platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
"""
|
||||
|
||||
BK72XX_CONFIG = """
|
||||
|
|
|
@ -165,7 +165,7 @@ platform_packages =
|
|||
extends = common:arduino
|
||||
board_build.filesystem_size = 0.5m
|
||||
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12
|
||||
platform_packages =
|
||||
; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted
|
||||
earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip
|
||||
|
|
16
tests/components/gp2y1010au0f/test.esp32-idf.yaml
Normal file
16
tests/components/gp2y1010au0f/test.esp32-idf.yaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
sensor:
|
||||
- platform: adc
|
||||
pin: GPIO36
|
||||
id: adc_sensor
|
||||
|
||||
- platform: gp2y1010au0f
|
||||
sensor: adc_sensor
|
||||
name: Dust Sensor
|
||||
adc_voltage_offset: 0.2
|
||||
adc_voltage_multiplier: 3.3
|
||||
output: dust_sensor_led
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
id: dust_sensor_led
|
||||
pin: GPIO32
|
|
@ -4,9 +4,6 @@ esphome:
|
|||
|
||||
rp2040:
|
||||
board: rpipicow
|
||||
framework:
|
||||
# Waiting for https://github.com/platformio/platform-raspberrypi/pull/36
|
||||
platform_version: https://github.com/maxgerhardt/platform-raspberrypi.git
|
||||
|
||||
logger:
|
||||
level: VERY_VERBOSE
|
||||
|
|
Loading…
Reference in a new issue