mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 12:55:46 +01:00
Merge branch 'dev' into optolink
This commit is contained in:
commit
f0476f1547
@ -286,6 +286,7 @@ esphome/components/tm1637/* @glmnet
|
||||
esphome/components/tm1638/* @skykingjwc
|
||||
esphome/components/tm1651/* @freekode
|
||||
esphome/components/tmp102/* @timsavage
|
||||
esphome/components/tmp1075/* @sybrenstuvel
|
||||
esphome/components/tmp117/* @Azimath
|
||||
esphome/components/tof10120/* @wstrzalka
|
||||
esphome/components/toshiba/* @kbx81
|
||||
|
@ -6,7 +6,14 @@ import esphome.components.image as espImage
|
||||
from esphome.components.image import CONF_USE_TRANSPARENCY
|
||||
import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_FILE, CONF_ID, CONF_RAW_DATA_ID, CONF_RESIZE, CONF_TYPE
|
||||
from esphome.const import (
|
||||
CONF_FILE,
|
||||
CONF_ID,
|
||||
CONF_RAW_DATA_ID,
|
||||
CONF_REPEAT,
|
||||
CONF_RESIZE,
|
||||
CONF_TYPE,
|
||||
)
|
||||
from esphome.core import CORE, HexInt
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -14,6 +21,10 @@ _LOGGER = logging.getLogger(__name__)
|
||||
DEPENDENCIES = ["display"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_LOOP = "loop"
|
||||
CONF_START_FRAME = "start_frame"
|
||||
CONF_END_FRAME = "end_frame"
|
||||
|
||||
Animation_ = display.display_ns.class_("Animation", espImage.Image_)
|
||||
|
||||
|
||||
@ -48,6 +59,13 @@ ANIMATION_SCHEMA = cv.Schema(
|
||||
# Not setting default here on purpose; the default depends on the image type,
|
||||
# and thus will be set in the "validate_cross_dependencies" validator.
|
||||
cv.Optional(CONF_USE_TRANSPARENCY): cv.boolean,
|
||||
cv.Optional(CONF_LOOP): cv.All(
|
||||
{
|
||||
cv.Optional(CONF_START_FRAME, default=0): cv.positive_int,
|
||||
cv.Optional(CONF_END_FRAME): cv.positive_int,
|
||||
cv.Optional(CONF_REPEAT): cv.positive_int,
|
||||
}
|
||||
),
|
||||
cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8),
|
||||
},
|
||||
validate_cross_dependencies,
|
||||
@ -227,3 +245,8 @@ async def to_code(config):
|
||||
espImage.IMAGE_TYPE[config[CONF_TYPE]],
|
||||
)
|
||||
cg.add(var.set_transparency(transparent))
|
||||
if CONF_LOOP in config:
|
||||
start = config[CONF_LOOP][CONF_START_FRAME]
|
||||
end = config[CONF_LOOP].get(CONF_END_FRAME, frames)
|
||||
count = config[CONF_LOOP].get(CONF_REPEAT, -1)
|
||||
cg.add(var.set_loop(start, end, count))
|
||||
|
@ -773,12 +773,31 @@ Color Animation::get_grayscale_pixel(int x, int y) const {
|
||||
return Color(gray, gray, gray, alpha);
|
||||
}
|
||||
Animation::Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, ImageType type)
|
||||
: Image(data_start, width, height, type), current_frame_(0), animation_frame_count_(animation_frame_count) {}
|
||||
int Animation::get_animation_frame_count() const { return this->animation_frame_count_; }
|
||||
: Image(data_start, width, height, type),
|
||||
current_frame_(0),
|
||||
animation_frame_count_(animation_frame_count),
|
||||
loop_start_frame_(0),
|
||||
loop_end_frame_(animation_frame_count_),
|
||||
loop_count_(0),
|
||||
loop_current_iteration_(1) {}
|
||||
void Animation::set_loop(uint32_t start_frame, uint32_t end_frame, int count) {
|
||||
loop_start_frame_ = std::min(start_frame, animation_frame_count_);
|
||||
loop_end_frame_ = std::min(end_frame, animation_frame_count_);
|
||||
loop_count_ = count;
|
||||
loop_current_iteration_ = 1;
|
||||
}
|
||||
|
||||
uint32_t Animation::get_animation_frame_count() const { return this->animation_frame_count_; }
|
||||
int Animation::get_current_frame() const { return this->current_frame_; }
|
||||
void Animation::next_frame() {
|
||||
this->current_frame_++;
|
||||
if (loop_count_ && this->current_frame_ == loop_end_frame_ &&
|
||||
(this->loop_current_iteration_ < loop_count_ || loop_count_ < 0)) {
|
||||
this->current_frame_ = loop_start_frame_;
|
||||
this->loop_current_iteration_++;
|
||||
}
|
||||
if (this->current_frame_ >= animation_frame_count_) {
|
||||
this->loop_current_iteration_ = 1;
|
||||
this->current_frame_ = 0;
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ class Animation : public Image {
|
||||
Color get_rgb565_pixel(int x, int y) const override;
|
||||
Color get_grayscale_pixel(int x, int y) const override;
|
||||
|
||||
int get_animation_frame_count() const;
|
||||
uint32_t get_animation_frame_count() const;
|
||||
int get_current_frame() const override;
|
||||
void next_frame();
|
||||
void prev_frame();
|
||||
@ -580,9 +580,15 @@ class Animation : public Image {
|
||||
*/
|
||||
void set_frame(int frame);
|
||||
|
||||
void set_loop(uint32_t start_frame, uint32_t end_frame, int count);
|
||||
|
||||
protected:
|
||||
int current_frame_;
|
||||
int animation_frame_count_;
|
||||
uint32_t animation_frame_count_;
|
||||
uint32_t loop_start_frame_;
|
||||
uint32_t loop_end_frame_;
|
||||
int loop_count_;
|
||||
int loop_current_iteration_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> {
|
||||
|
@ -20,6 +20,7 @@ DEPENDENCIES = ["i2s_audio"]
|
||||
CONF_ADC_PIN = "adc_pin"
|
||||
CONF_ADC_TYPE = "adc_type"
|
||||
CONF_PDM = "pdm"
|
||||
CONF_BITS_PER_SAMPLE = "bits_per_sample"
|
||||
|
||||
I2SAudioMicrophone = i2s_audio_ns.class_(
|
||||
"I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component
|
||||
@ -30,10 +31,17 @@ CHANNELS = {
|
||||
"left": i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
"right": i2s_channel_fmt_t.I2S_CHANNEL_FMT_ONLY_RIGHT,
|
||||
}
|
||||
i2s_bits_per_sample_t = cg.global_ns.enum("i2s_bits_per_sample_t")
|
||||
BITS_PER_SAMPLE = {
|
||||
16: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_16BIT,
|
||||
32: i2s_bits_per_sample_t.I2S_BITS_PER_SAMPLE_32BIT,
|
||||
}
|
||||
|
||||
INTERNAL_ADC_VARIANTS = [esp32.const.VARIANT_ESP32]
|
||||
PDM_VARIANTS = [esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S3]
|
||||
|
||||
_validate_bits = cv.float_with_unit("bits", "bit")
|
||||
|
||||
|
||||
def validate_esp32_variant(config):
|
||||
variant = esp32.get_esp32_variant()
|
||||
@ -54,6 +62,9 @@ BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend(
|
||||
cv.GenerateID(): cv.declare_id(I2SAudioMicrophone),
|
||||
cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent),
|
||||
cv.Optional(CONF_CHANNEL, default="right"): cv.enum(CHANNELS),
|
||||
cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All(
|
||||
_validate_bits, cv.enum(BITS_PER_SAMPLE)
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
@ -93,6 +104,7 @@ async def to_code(config):
|
||||
cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN]))
|
||||
cg.add(var.set_pdm(config[CONF_PDM]))
|
||||
|
||||
cg.add(var.set_channel(CHANNELS[config[CONF_CHANNEL]]))
|
||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||
cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE]))
|
||||
|
||||
await microphone.register_microphone(var, config)
|
||||
|
@ -16,7 +16,13 @@ static const char *const TAG = "i2s_audio.microphone";
|
||||
|
||||
void I2SAudioMicrophone::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up I2S Audio Microphone...");
|
||||
this->buffer_.resize(BUFFER_SIZE);
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
this->buffer_ = allocator.allocate(BUFFER_SIZE);
|
||||
if (this->buffer_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate buffer!");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_ADC
|
||||
if (this->adc_) {
|
||||
@ -48,7 +54,7 @@ void I2SAudioMicrophone::start_() {
|
||||
i2s_driver_config_t config = {
|
||||
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX),
|
||||
.sample_rate = 16000,
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
|
||||
.bits_per_sample = this->bits_per_sample_,
|
||||
.channel_format = this->channel_,
|
||||
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
@ -107,16 +113,35 @@ void I2SAudioMicrophone::stop_() {
|
||||
void I2SAudioMicrophone::read_() {
|
||||
size_t bytes_read = 0;
|
||||
esp_err_t err =
|
||||
i2s_read(this->parent_->get_port(), this->buffer_.data(), BUFFER_SIZE, &bytes_read, (100 / portTICK_PERIOD_MS));
|
||||
i2s_read(this->parent_->get_port(), this->buffer_, BUFFER_SIZE, &bytes_read, (100 / portTICK_PERIOD_MS));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Error reading from I2S microphone: %s", esp_err_to_name(err));
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
|
||||
this->status_clear_warning();
|
||||
|
||||
this->data_callbacks_.call(this->buffer_);
|
||||
std::vector<int16_t> samples;
|
||||
size_t samples_read = 0;
|
||||
if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
samples_read = bytes_read / sizeof(int16_t);
|
||||
} else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) {
|
||||
samples_read = bytes_read / sizeof(int32_t);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unsupported bits per sample: %d", this->bits_per_sample_);
|
||||
return;
|
||||
}
|
||||
samples.resize(samples_read);
|
||||
if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_16BIT) {
|
||||
memcpy(samples.data(), this->buffer_, bytes_read);
|
||||
} else if (this->bits_per_sample_ == I2S_BITS_PER_SAMPLE_32BIT) {
|
||||
for (size_t i = 0; i < samples_read; i++) {
|
||||
int32_t temp = reinterpret_cast<int32_t *>(this->buffer_)[i] >> 14;
|
||||
samples[i] = clamp<int16_t>(temp, INT16_MIN, INT16_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
this->data_callbacks_.call(samples);
|
||||
}
|
||||
|
||||
void I2SAudioMicrophone::loop() {
|
||||
|
@ -29,6 +29,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub
|
||||
#endif
|
||||
|
||||
void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; }
|
||||
void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; }
|
||||
|
||||
protected:
|
||||
void start_();
|
||||
@ -41,8 +42,9 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub
|
||||
bool adc_{false};
|
||||
#endif
|
||||
bool pdm_{false};
|
||||
std::vector<uint8_t> buffer_;
|
||||
uint8_t *buffer_;
|
||||
i2s_channel_fmt_t channel_;
|
||||
i2s_bits_per_sample_t bits_per_sample_;
|
||||
|
||||
HighFrequencyLoopRequester high_freq_;
|
||||
};
|
||||
|
@ -41,7 +41,7 @@ async def setup_microphone_core_(var, config):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(
|
||||
trigger,
|
||||
[(cg.std_vector.template(cg.uint8).operator("ref").operator("const"), "x")],
|
||||
[(cg.std_vector.template(cg.int16).operator("ref").operator("const"), "x")],
|
||||
conf,
|
||||
)
|
||||
|
||||
|
@ -16,10 +16,10 @@ template<typename... Ts> class StopCaptureAction : public Action<Ts...>, public
|
||||
void play(Ts... x) override { this->parent_->stop(); }
|
||||
};
|
||||
|
||||
class DataTrigger : public Trigger<const std::vector<uint8_t> &> {
|
||||
class DataTrigger : public Trigger<const std::vector<int16_t> &> {
|
||||
public:
|
||||
explicit DataTrigger(Microphone *mic) {
|
||||
mic->add_data_callback([this](const std::vector<uint8_t> &data) { this->trigger(data); });
|
||||
mic->add_data_callback([this](const std::vector<int16_t> &data) { this->trigger(data); });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ class Microphone {
|
||||
public:
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
void add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback) {
|
||||
void add_data_callback(std::function<void(const std::vector<int16_t> &)> &&data_callback) {
|
||||
this->data_callbacks_.add(std::move(data_callback));
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class Microphone {
|
||||
protected:
|
||||
State state_{STATE_STOPPED};
|
||||
|
||||
CallbackManager<void(const std::vector<uint8_t> &)> data_callbacks_{};
|
||||
CallbackManager<void(const std::vector<int16_t> &)> data_callbacks_{};
|
||||
};
|
||||
|
||||
} // namespace microphone
|
||||
|
1
esphome/components/tmp1075/__init__.py
Normal file
1
esphome/components/tmp1075/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@sybrenstuvel"]
|
92
esphome/components/tmp1075/sensor.py
Normal file
92
esphome/components/tmp1075/sensor.py
Normal file
@ -0,0 +1,92 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
ICON_THERMOMETER,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
tmp1075_ns = cg.esphome_ns.namespace("tmp1075")
|
||||
|
||||
TMP1075Sensor = tmp1075_ns.class_(
|
||||
"TMP1075Sensor", cg.PollingComponent, sensor.Sensor, i2c.I2CDevice
|
||||
)
|
||||
|
||||
EConversionRate = tmp1075_ns.enum("EConversionRate")
|
||||
CONVERSION_RATES = {
|
||||
"27.5ms": EConversionRate.CONV_RATE_27_5_MS,
|
||||
"55ms": EConversionRate.CONV_RATE_55_MS,
|
||||
"110ms": EConversionRate.CONV_RATE_110_MS,
|
||||
"220ms": EConversionRate.CONV_RATE_220_MS,
|
||||
}
|
||||
|
||||
POLARITY = {
|
||||
"ACTIVE_LOW": 0,
|
||||
"ACTIVE_HIGH": 1,
|
||||
}
|
||||
|
||||
EAlertFunction = tmp1075_ns.enum("EAlertFunction")
|
||||
ALERT_FUNCTION = {
|
||||
"COMPARATOR": EAlertFunction.ALERT_COMPARATOR,
|
||||
"INTERRUPT": EAlertFunction.ALERT_INTERRUPT,
|
||||
}
|
||||
|
||||
CONF_ALERT = "alert"
|
||||
CONF_LIMIT_LOW = "limit_low"
|
||||
CONF_LIMIT_HIGH = "limit_high"
|
||||
CONF_FAULT_COUNT = "fault_count"
|
||||
CONF_POLARITY = "polarity"
|
||||
CONF_CONVERSION_RATE = "conversion_rate"
|
||||
CONF_FUNCTION = "function"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(
|
||||
TMP1075Sensor,
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
icon=ICON_THERMOMETER,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.Optional(CONF_CONVERSION_RATE): cv.enum(CONVERSION_RATES, lower=True),
|
||||
cv.Optional(CONF_ALERT, default={}): cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_LIMIT_LOW): cv.temperature,
|
||||
cv.Optional(CONF_LIMIT_HIGH): cv.temperature,
|
||||
cv.Optional(CONF_FAULT_COUNT): cv.int_range(min=1, max=4),
|
||||
cv.Optional(CONF_POLARITY): cv.enum(POLARITY, upper=True),
|
||||
cv.Optional(CONF_FUNCTION): cv.enum(ALERT_FUNCTION, upper=True),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x48))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await sensor.new_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
if CONF_CONVERSION_RATE in config:
|
||||
cg.add(var.set_conversion_rate(config[CONF_CONVERSION_RATE]))
|
||||
|
||||
alert = config[CONF_ALERT]
|
||||
if CONF_LIMIT_LOW in alert:
|
||||
cg.add(var.set_alert_limit_low(alert[CONF_LIMIT_LOW]))
|
||||
if CONF_LIMIT_HIGH in alert:
|
||||
cg.add(var.set_alert_limit_high(alert[CONF_LIMIT_HIGH]))
|
||||
if CONF_FAULT_COUNT in alert:
|
||||
cg.add(var.set_fault_count(alert[CONF_FAULT_COUNT]))
|
||||
if CONF_POLARITY in alert:
|
||||
cg.add(var.set_alert_polarity(alert[CONF_POLARITY]))
|
||||
if CONF_FUNCTION in alert:
|
||||
cg.add(var.set_alert_function(alert[CONF_FUNCTION]))
|
129
esphome/components/tmp1075/tmp1075.cpp
Normal file
129
esphome/components/tmp1075/tmp1075.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "tmp1075.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace tmp1075 {
|
||||
|
||||
static const char *const TAG = "tmp1075";
|
||||
|
||||
constexpr uint8_t REG_TEMP = 0x0; // Temperature result
|
||||
constexpr uint8_t REG_CFGR = 0x1; // Configuration
|
||||
constexpr uint8_t REG_LLIM = 0x2; // Low limit
|
||||
constexpr uint8_t REG_HLIM = 0x3; // High limit
|
||||
constexpr uint8_t REG_DIEID = 0xF; // Device ID
|
||||
|
||||
constexpr uint16_t EXPECT_DIEID = 0x0075; // Expected Device ID.
|
||||
|
||||
static uint16_t temp2regvalue(float temp);
|
||||
static float regvalue2temp(uint16_t regvalue);
|
||||
|
||||
void TMP1075Sensor::setup() {
|
||||
uint8_t die_id;
|
||||
if (!this->read_byte(REG_DIEID, &die_id)) {
|
||||
ESP_LOGW(TAG, "'%s' - unable to read ID", this->name_.c_str());
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
if (die_id != EXPECT_DIEID) {
|
||||
ESP_LOGW(TAG, "'%s' - unexpected ID 0x%x found, expected 0x%x", this->name_.c_str(), die_id, EXPECT_DIEID);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
this->write_config();
|
||||
}
|
||||
|
||||
void TMP1075Sensor::update() {
|
||||
uint16_t regvalue;
|
||||
if (!read_byte_16(REG_TEMP, ®value)) {
|
||||
ESP_LOGW(TAG, "'%s' - unable to read temperature register", this->name_.c_str());
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
|
||||
const float temp = regvalue2temp(regvalue);
|
||||
this->publish_state(temp);
|
||||
}
|
||||
|
||||
void TMP1075Sensor::dump_config() {
|
||||
LOG_SENSOR("", "TMP1075 Sensor", this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, " Communication with TMP1075 failed!");
|
||||
return;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " limit low : %.4f °C", alert_limit_low_);
|
||||
ESP_LOGCONFIG(TAG, " limit high : %.4f °C", alert_limit_high_);
|
||||
ESP_LOGCONFIG(TAG, " oneshot : %d", config_.fields.oneshot);
|
||||
ESP_LOGCONFIG(TAG, " rate : %d", config_.fields.rate);
|
||||
ESP_LOGCONFIG(TAG, " fault_count: %d", config_.fields.faults);
|
||||
ESP_LOGCONFIG(TAG, " polarity : %d", config_.fields.polarity);
|
||||
ESP_LOGCONFIG(TAG, " alert_mode : %d", config_.fields.alert_mode);
|
||||
ESP_LOGCONFIG(TAG, " shutdown : %d", config_.fields.shutdown);
|
||||
}
|
||||
|
||||
void TMP1075Sensor::set_fault_count(const int faults) {
|
||||
if (faults < 1) {
|
||||
ESP_LOGE(TAG, "'%s' - fault_count too low: %d", this->name_.c_str(), faults);
|
||||
return;
|
||||
}
|
||||
if (faults > 4) {
|
||||
ESP_LOGE(TAG, "'%s' - fault_count too high: %d", this->name_.c_str(), faults);
|
||||
return;
|
||||
}
|
||||
config_.fields.faults = faults - 1;
|
||||
}
|
||||
|
||||
void TMP1075Sensor::log_config_() {
|
||||
ESP_LOGV(TAG, " oneshot : %d", config_.fields.oneshot);
|
||||
ESP_LOGV(TAG, " rate : %d", config_.fields.rate);
|
||||
ESP_LOGV(TAG, " faults : %d", config_.fields.faults);
|
||||
ESP_LOGV(TAG, " polarity : %d", config_.fields.polarity);
|
||||
ESP_LOGV(TAG, " alert_mode: %d", config_.fields.alert_mode);
|
||||
ESP_LOGV(TAG, " shutdown : %d", config_.fields.shutdown);
|
||||
}
|
||||
|
||||
void TMP1075Sensor::write_config() {
|
||||
send_alert_limit_low_();
|
||||
send_alert_limit_high_();
|
||||
send_config_();
|
||||
}
|
||||
|
||||
void TMP1075Sensor::send_config_() {
|
||||
ESP_LOGV(TAG, "'%s' - sending configuration %04x", this->name_.c_str(), config_.regvalue);
|
||||
log_config_();
|
||||
if (!this->write_byte_16(REG_CFGR, config_.regvalue)) {
|
||||
ESP_LOGW(TAG, "'%s' - unable to write configuration register", this->name_.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TMP1075Sensor::send_alert_limit_low_() {
|
||||
ESP_LOGV(TAG, "'%s' - sending alert limit low %.3f °C", this->name_.c_str(), alert_limit_low_);
|
||||
const uint16_t regvalue = temp2regvalue(alert_limit_low_);
|
||||
if (!this->write_byte_16(REG_LLIM, regvalue)) {
|
||||
ESP_LOGW(TAG, "'%s' - unable to write low limit register", this->name_.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TMP1075Sensor::send_alert_limit_high_() {
|
||||
ESP_LOGV(TAG, "'%s' - sending alert limit high %.3f °C", this->name_.c_str(), alert_limit_high_);
|
||||
const uint16_t regvalue = temp2regvalue(alert_limit_high_);
|
||||
if (!this->write_byte_16(REG_HLIM, regvalue)) {
|
||||
ESP_LOGW(TAG, "'%s' - unable to write high limit register", this->name_.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t temp2regvalue(const float temp) {
|
||||
const uint16_t regvalue = temp / 0.0625f;
|
||||
return regvalue << 4;
|
||||
}
|
||||
|
||||
static float regvalue2temp(const uint16_t regvalue) {
|
||||
const int16_t signed_value = regvalue;
|
||||
return (signed_value >> 4) * 0.0625f;
|
||||
}
|
||||
|
||||
} // namespace tmp1075
|
||||
} // namespace esphome
|
92
esphome/components/tmp1075/tmp1075.h
Normal file
92
esphome/components/tmp1075/tmp1075.h
Normal file
@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace tmp1075 {
|
||||
|
||||
struct TMP1075Config {
|
||||
union {
|
||||
struct {
|
||||
uint8_t oneshot : 1; // One-shot conversion mode. Writing 1, starts a single temperature
|
||||
// conversion. Read returns 0.
|
||||
|
||||
uint8_t rate : 2; // Conversion rate setting when device is in continuous conversion mode.
|
||||
// 00: 27.5 ms conversion rate
|
||||
// 01: 55 ms conversion rate
|
||||
// 10: 110 ms conversion rate
|
||||
// 11: 220 ms conversion rate (35 ms TMP1075N)
|
||||
|
||||
uint8_t faults : 2; // Consecutive fault measurements to trigger the alert function.
|
||||
// 00: 1 fault
|
||||
// 01: 2 faults
|
||||
// 10: 3 faults (4 faults TMP1075N)
|
||||
// 11: 4 faults (6 faults TMP1075N)
|
||||
|
||||
uint8_t polarity : 1; // Polarity of the output pin.
|
||||
// 0: Active low ALERT pin
|
||||
// 1: Active high ALERT pin
|
||||
|
||||
uint8_t alert_mode : 1; // Selects the function of the ALERT pin.
|
||||
// 0: ALERT pin functions in comparator mode
|
||||
// 1: ALERT pin functions in interrupt mode
|
||||
|
||||
uint8_t shutdown : 1; // Sets the device in shutdown mode to conserve power.
|
||||
// 0: Device is in continuous conversion
|
||||
// 1: Device is in shutdown mode
|
||||
uint8_t unused : 8;
|
||||
} fields;
|
||||
uint16_t regvalue;
|
||||
};
|
||||
};
|
||||
|
||||
enum EConversionRate {
|
||||
CONV_RATE_27_5_MS,
|
||||
CONV_RATE_55_MS,
|
||||
CONV_RATE_110_MS,
|
||||
CONV_RATE_220_MS,
|
||||
};
|
||||
|
||||
enum EAlertFunction {
|
||||
ALERT_COMPARATOR = 0,
|
||||
ALERT_INTERRUPT = 1,
|
||||
};
|
||||
|
||||
class TMP1075Sensor : public PollingComponent, public sensor::Sensor, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void update() override;
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
// Call write_config() after calling any of these to send the new config to
|
||||
// the IC. The setup() function also does this.
|
||||
void set_alert_limit_low(const float temp) { this->alert_limit_low_ = temp; }
|
||||
void set_alert_limit_high(const float temp) { this->alert_limit_high_ = temp; }
|
||||
void set_oneshot(const bool oneshot) { config_.fields.oneshot = oneshot; }
|
||||
void set_conversion_rate(const enum EConversionRate rate) { config_.fields.rate = rate; }
|
||||
void set_alert_polarity(const bool polarity) { config_.fields.polarity = polarity; }
|
||||
void set_alert_function(const enum EAlertFunction function) { config_.fields.alert_mode = function; }
|
||||
void set_fault_count(int faults);
|
||||
|
||||
void write_config();
|
||||
|
||||
protected:
|
||||
TMP1075Config config_ = {};
|
||||
|
||||
// Disable the alert pin by default.
|
||||
float alert_limit_low_ = -128.0f;
|
||||
float alert_limit_high_ = 127.9375f;
|
||||
|
||||
void send_alert_limit_low_();
|
||||
void send_alert_limit_high_();
|
||||
void send_config_();
|
||||
void log_config_();
|
||||
};
|
||||
|
||||
} // namespace tmp1075
|
||||
} // namespace esphome
|
@ -58,11 +58,12 @@ void VoiceAssistant::setup() {
|
||||
}
|
||||
#endif
|
||||
|
||||
this->mic_->add_data_callback([this](const std::vector<uint8_t> &data) {
|
||||
this->mic_->add_data_callback([this](const std::vector<int16_t> &data) {
|
||||
if (!this->running_) {
|
||||
return;
|
||||
}
|
||||
this->socket_->sendto(data.data(), data.size(), 0, (struct sockaddr *) &this->dest_addr_, sizeof(this->dest_addr_));
|
||||
this->socket_->sendto(data.data(), data.size() * sizeof(int16_t), 0, (struct sockaddr *) &this->dest_addr_,
|
||||
sizeof(this->dest_addr_));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1314,6 +1314,17 @@ sensor:
|
||||
div_ratio: 100
|
||||
unit_of_measurement: °C
|
||||
device_class: temperature
|
||||
- platform: tmp1075
|
||||
name: "Temperature TMP1075"
|
||||
update_interval: 10s
|
||||
i2c_id: i2c_bus
|
||||
conversion_rate: 27.5ms
|
||||
alert:
|
||||
limit_low: 50
|
||||
limit_high: 75
|
||||
fault_count: 1
|
||||
polarity: active_high
|
||||
function: comparator
|
||||
|
||||
esp32_touch:
|
||||
setup_mode: false
|
||||
|
Loading…
Reference in New Issue
Block a user