From fdd4536405523d4e3b9b5e39e0dca88281abedee Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Mon, 26 Feb 2024 00:14:10 +0100 Subject: [PATCH] initial --- CODEOWNERS | 1 + esphome/components/as7343/__init__.py | 1 + esphome/components/as7343/as7343.cpp | 308 +++++++++++++++++++ esphome/components/as7343/as7343.h | 139 +++++++++ esphome/components/as7343/as7343_registers.h | 107 +++++++ esphome/components/as7343/sensor.py | 126 ++++++++ 6 files changed, 682 insertions(+) create mode 100644 esphome/components/as7343/__init__.py create mode 100644 esphome/components/as7343/as7343.cpp create mode 100644 esphome/components/as7343/as7343.h create mode 100644 esphome/components/as7343/as7343_registers.h create mode 100644 esphome/components/as7343/sensor.py diff --git a/CODEOWNERS b/CODEOWNERS index 8d0ac7983f..0c1a549dfb 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -38,6 +38,7 @@ esphome/components/api/* @OttoWinter esphome/components/as5600/* @ammmze esphome/components/as5600/sensor/* @ammmze esphome/components/as7341/* @mrgnr +esphome/components/as7343/* @latonita @mrgnr esphome/components/async_tcp/* @OttoWinter esphome/components/atc_mithermometer/* @ahpohl esphome/components/atm90e26/* @danieltwagner diff --git a/esphome/components/as7343/__init__.py b/esphome/components/as7343/__init__.py new file mode 100644 index 0000000000..dd06cfffea --- /dev/null +++ b/esphome/components/as7343/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@latonita"] diff --git a/esphome/components/as7343/as7343.cpp b/esphome/components/as7343/as7343.cpp new file mode 100644 index 0000000000..2204cacb1c --- /dev/null +++ b/esphome/components/as7343/as7343.cpp @@ -0,0 +1,308 @@ +#include "as7343.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +namespace esphome { +namespace as7343 { + +static const char *const TAG = "as7343"; + +void AS7343Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up AS7343..."); + LOG_I2C_DEVICE(this); + + // Verify device ID + this->set_bank_for_reg_(AS7343Registers::ID); + uint8_t id = this->reg((uint8_t) AS7343Registers::ID).get(); + ESP_LOGCONFIG(TAG, " Read ID: 0x%X", id); + if (id != AS7343_CHIP_ID) { + this->mark_failed(); + ESP_LOGE(TAG, " Invalid chip ID: 0x%X", id); + return; + } + + this->set_bank_for_reg_(AS7343Registers::ENABLE); + // Power on (enter IDLE state) + if (!this->enable_power(true)) { + ESP_LOGE(TAG, " Power on failed!"); + this->mark_failed(); + return; + } + + // Set configuration + AS7343RegCfg20 cfg20; + cfg20.raw = this->reg((uint8_t) AS7343Registers::CFG20).get(); + cfg20.auto_smux = 0b11; + this->reg((uint8_t) AS7343Registers::CFG20) = cfg20.raw; + + this->setup_atime(this->atime_); + this->setup_astep(this->astep_); + this->setup_gain(this->gain_); + + // enable led false ? +} + +void AS7343Component::dump_config() { + ESP_LOGCONFIG(TAG, "AS7343:"); + LOG_I2C_DEVICE(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with AS7343 failed!"); + } + LOG_UPDATE_INTERVAL(this); + ESP_LOGCONFIG(TAG, " Gain: %u", get_gain()); + ESP_LOGCONFIG(TAG, " ATIME: %u", get_atime()); + ESP_LOGCONFIG(TAG, " ASTEP: %u", get_astep()); + + LOG_SENSOR(" ", "F1", this->f1_); + LOG_SENSOR(" ", "F2", this->f2_); + LOG_SENSOR(" ", "FZ", this->fz_); + LOG_SENSOR(" ", "F3", this->f3_); + LOG_SENSOR(" ", "F4", this->f4_); + LOG_SENSOR(" ", "F5", this->f5_); + LOG_SENSOR(" ", "FY", this->fy_); + LOG_SENSOR(" ", "FXL", this->fxl_); + LOG_SENSOR(" ", "F6", this->f6_); + LOG_SENSOR(" ", "F7", this->f7_); + LOG_SENSOR(" ", "F8", this->f8_); + LOG_SENSOR(" ", "NIR", this->nir_); + LOG_SENSOR(" ", "Clear", this->clear_); +} + +float AS7343Component::get_setup_priority() const { return setup_priority::DATA; } + +void AS7343Component::update() { + this->read_channels(this->channel_readings_); + + if (this->f1_ != nullptr) { + this->f1_->publish_state(this->channel_readings_[AS7343_CHANNEL_405_F1]); + } + if (this->f2_ != nullptr) { + this->f2_->publish_state(this->channel_readings_[AS7343_CHANNEL_425_F2]); + } + if (this->fz_ != nullptr) { + this->fz_->publish_state(this->channel_readings_[AS7343_CHANNEL_450_FZ]); + } + if (this->f3_ != nullptr) { + this->f3_->publish_state(this->channel_readings_[AS7343_CHANNEL_475_F3]); + } + if (this->f4_ != nullptr) { + this->f4_->publish_state(this->channel_readings_[AS7343_CHANNEL_515_F4]); + } + if (this->fy_ != nullptr) { + this->fy_->publish_state(this->channel_readings_[AS7343_CHANNEL_555_FY]); + } + if (this->f5_ != nullptr) { + this->f5_->publish_state(this->channel_readings_[AS7343_CHANNEL_550_F5]); + } + if (this->fxl_ != nullptr) { + this->fxl_->publish_state(this->channel_readings_[AS7343_CHANNEL_600_FXL]); + } + if (this->f6_ != nullptr) { + this->f6_->publish_state(this->channel_readings_[AS7343_CHANNEL_640_F6]); + } + if (this->f7_ != nullptr) { + this->f7_->publish_state(this->channel_readings_[AS7343_CHANNEL_690_F7]); + } + if (this->f8_ != nullptr) { + this->f8_->publish_state(this->channel_readings_[AS7343_CHANNEL_745_F8]); + } + if (this->nir_ != nullptr) { + this->nir_->publish_state(this->channel_readings_[AS7343_CHANNEL_855_NIR]); + } + if (this->clear_ != nullptr) { + this->clear_->publish_state(this->channel_readings_[AS7343_CHANNEL_CLEAR]); + } +} + +AS7343Gain AS7343Component::get_gain() { + uint8_t data; + this->read_byte((uint8_t) AS7343Registers::CFG1, &data); + return (AS7343Gain) data; +} + +uint8_t AS7343Component::get_atime() { + uint8_t data; + this->read_byte((uint8_t) AS7343Registers::ATIME, &data); + return data; +} + +uint16_t AS7343Component::get_astep() { + uint16_t data; + this->read_byte_16((uint8_t) AS7343Registers::ASTEP_LSB, &data); + return this->swap_bytes(data); +} + +bool AS7343Component::setup_gain(AS7343Gain gain) { return this->write_byte((uint8_t) AS7343Registers::CFG1, gain); } + +bool AS7343Component::setup_atime(uint8_t atime) { return this->write_byte((uint8_t) AS7343Registers::ATIME, atime); } + +bool AS7343Component::setup_astep(uint16_t astep) { + return this->write_byte_16((uint8_t) AS7343Registers::ASTEP_LSB, swap_bytes(astep)); +} + +bool AS7343Component::read_channels(uint16_t *data) { + this->enable_spectral_measurement(true); + this->wait_for_data(); + + return this->read_bytes_16((uint8_t) AS7343Registers::DATA_O, this->channel_readings_, AS7343_NUM_CHANNELS); + + // this->set_smux_low_channels(true); + // this->enable_spectral_measurement(true); + // this->wait_for_data(); + // bool low_success = this->read_bytes_16(AS7343_CH0_DATA_L, data, 6); + + // this->set_smux_low_channels(false); + // this->enable_spectral_measurement(true); + // this->wait_for_data(); + // bool high_sucess = this->read_bytes_16(AS7343_CH0_DATA_L, &data[6], 6); + + // return low_success && high_sucess; +} + +// void AS7343Component::set_smux_low_channels(bool enable) { +// // this->enable_spectral_measurement(false); +// // this->set_smux_command(AS7343_SMUX_CMD_WRITE); + +// // if (enable) { +// // this->configure_smux_low_channels(); + +// // } else { +// // this->configure_smux_high_channels(); +// // } +// // this->enable_smux(); +// } + +// bool AS7343Component::set_smux_command(AS7343SmuxCommand command) { +// // uint8_t data = command << 3; // Write to bits 4:3 of the register +// // return this->write_byte(AS7343_CFG6, data); +// } + +// void AS7343Component::configure_smux_low_channels() { +// // SMUX Config for F1,F2,F3,F4,NIR,Clear +// // this->write_byte(0x00, 0x30); // F3 left set to ADC2 +// // this->write_byte(0x01, 0x01); // F1 left set to ADC0 +// // this->write_byte(0x02, 0x00); // Reserved or disabled +// // this->write_byte(0x03, 0x00); // F8 left disabled +// // this->write_byte(0x04, 0x00); // F6 left disabled +// // this->write_byte(0x05, 0x42); // F4 left connected to ADC3/f2 left connected to ADC1 +// // this->write_byte(0x06, 0x00); // F5 left disbled +// // this->write_byte(0x07, 0x00); // F7 left disbled +// // this->write_byte(0x08, 0x50); // CLEAR connected to ADC4 +// // this->write_byte(0x09, 0x00); // F5 right disabled +// // this->write_byte(0x0A, 0x00); // F7 right disabled +// // this->write_byte(0x0B, 0x00); // Reserved or disabled +// // this->write_byte(0x0C, 0x20); // F2 right connected to ADC1 +// // this->write_byte(0x0D, 0x04); // F4 right connected to ADC3 +// // this->write_byte(0x0E, 0x00); // F6/F8 right disabled +// // this->write_byte(0x0F, 0x30); // F3 right connected to AD2 +// // this->write_byte(0x10, 0x01); // F1 right connected to AD0 +// // this->write_byte(0x11, 0x50); // CLEAR right connected to AD4 +// // this->write_byte(0x12, 0x00); // Reserved or disabled +// // this->write_byte(0x13, 0x06); // NIR connected to ADC5 +// } + +// void AS7343Component::configure_smux_high_channels() { +// // SMUX Config for F5,F6,F7,F8,NIR,Clear +// // this->write_byte(0x00, 0x00); // F3 left disable +// // this->write_byte(0x01, 0x00); // F1 left disable +// // this->write_byte(0x02, 0x00); // reserved/disable +// // this->write_byte(0x03, 0x40); // F8 left connected to ADC3 +// // this->write_byte(0x04, 0x02); // F6 left connected to ADC1 +// // this->write_byte(0x05, 0x00); // F4/ F2 disabled +// // this->write_byte(0x06, 0x10); // F5 left connected to ADC0 +// // this->write_byte(0x07, 0x03); // F7 left connected to ADC2 +// // this->write_byte(0x08, 0x50); // CLEAR Connected to ADC4 +// // this->write_byte(0x09, 0x10); // F5 right connected to ADC0 +// // this->write_byte(0x0A, 0x03); // F7 right connected to ADC2 +// // this->write_byte(0x0B, 0x00); // Reserved or disabled +// // this->write_byte(0x0C, 0x00); // F2 right disabled +// // this->write_byte(0x0D, 0x00); // F4 right disabled +// // this->write_byte(0x0E, 0x24); // F8 right connected to ADC2/ F6 right connected to ADC1 +// // this->write_byte(0x0F, 0x00); // F3 right disabled +// // this->write_byte(0x10, 0x00); // F1 right disabled +// // this->write_byte(0x11, 0x50); // CLEAR right connected to AD4 +// // this->write_byte(0x12, 0x00); // Reserved or disabled +// // this->write_byte(0x13, 0x06); // NIR connected to ADC5 +// } + +// bool AS7343Component::enable_smux() { +// // this->set_register_bit(AS7343_ENABLE, 4); + +// // uint16_t timeout = 1000; +// // for (uint16_t time = 0; time < timeout; time++) { +// // // The SMUXEN bit is cleared once the SMUX operation is finished +// // bool smuxen = this->read_register_bit(AS7343_ENABLE, 4); +// // if (!smuxen) { +// // return true; +// // } + +// // delay(1); +// // } + +// // return false; +// } + +bool AS7343Component::wait_for_data(uint16_t timeout) { + for (uint16_t time = 0; time < timeout; time++) { + if (this->is_data_ready()) { + return true; + } + + delay(1); + } + + return false; +} + +bool AS7343Component::is_data_ready() { return this->read_register_bit((uint8_t) AS7343Registers::STATUS2, 6); } + +void AS7343Component::set_bank_for_reg_(AS7343Registers reg) { + bool bank = (uint8_t) reg < 0x80; + if (bank == this->bank_) { + return; + } + this->write_register_bit((uint8_t) AS7343Registers::CFG0, bank, AS7343_CFG0_REG_BANK_BIT); + this->bank_ = bank; +} + +bool AS7343Component::enable_power(bool enable) { + return this->write_register_bit((uint8_t) AS7343Registers::ENABLE, enable, AS7343_ENABLE_PON_BIT); +} + +bool AS7343Component::enable_spectral_measurement(bool enable) { + return this->write_register_bit((uint8_t) AS7343Registers::ENABLE, enable, AS7343_ENABLE_SP_EN_BIT); +} + +bool AS7343Component::read_register_bit(uint8_t address, uint8_t bit_position) { + uint8_t data; + this->read_byte(address, &data); + bool bit = (data & (1 << bit_position)) > 0; + return bit; +} + +bool AS7343Component::write_register_bit(uint8_t address, bool value, uint8_t bit_position) { + if (value) { + return this->set_register_bit(address, bit_position); + } + + return this->clear_register_bit(address, bit_position); +} + +bool AS7343Component::set_register_bit(uint8_t address, uint8_t bit_position) { + uint8_t data; + this->read_byte(address, &data); + data |= (1 << bit_position); + return this->write_byte(address, data); +} + +bool AS7343Component::clear_register_bit(uint8_t address, uint8_t bit_position) { + uint8_t data; + this->read_byte(address, &data); + data &= ~(1 << bit_position); + return this->write_byte(address, data); +} + +uint16_t AS7343Component::swap_bytes(uint16_t data) { return (data >> 8) | (data << 8); } + +} // namespace as7343 +} // namespace esphome diff --git a/esphome/components/as7343/as7343.h b/esphome/components/as7343/as7343.h new file mode 100644 index 0000000000..f0b864ecf4 --- /dev/null +++ b/esphome/components/as7343/as7343.h @@ -0,0 +1,139 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +#include "as7343_registers.h" + +namespace esphome { +namespace as7343 { + +static const uint8_t AS7341_CONFIG = 0x70; +static const uint8_t AS7341_LED = 0x74; + +static const uint8_t AS7341_ENABLE = 0x80; +static const uint8_t AS7341_ATIME = 0x81; + +static const uint8_t AS7341_WTIME = 0x83; + +static const uint8_t AS7341_AUXID = 0x90; +static const uint8_t AS7341_REVID = 0x91; +static const uint8_t AS7341_ID = 0x92; +static const uint8_t AS7341_STATUS = 0x93; + +// static const uint8_t AS7341_CH0_DATA_L = 0x95; +// static const uint8_t AS7341_CH0_DATA_H = 0x96; +// static const uint8_t AS7341_CH1_DATA_L = 0x97; +// static const uint8_t AS7341_CH1_DATA_H = 0x98; +// static const uint8_t AS7341_CH2_DATA_L = 0x99; +// static const uint8_t AS7341_CH2_DATA_H = 0x9A; +// static const uint8_t AS7341_CH3_DATA_L = 0x9B; +// static const uint8_t AS7341_CH3_DATA_H = 0x9C; +// static const uint8_t AS7341_CH4_DATA_L = 0x9D; +// static const uint8_t AS7341_CH4_DATA_H = 0x9E; +// static const uint8_t AS7341_CH5_DATA_L = 0x9F; +// static const uint8_t AS7341_CH5_DATA_H = 0xA0; + +// static const uint8_t AS7341_STATUS2 = 0xA3; + +// static const uint8_t AS7341_CFG1 = 0xAA; ///< Controls ADC Gain + +// static const uint8_t AS7341_CFG6 = 0xAF; // Stores SMUX command +// static const uint8_t AS7341_CFG9 = 0xB2; // Config for system interrupts (SMUX, Flicker detection) + +// static const uint8_t AS7341_ASTEP = 0xCA; // LSB +// static const uint8_t AS7341_ASTEP_MSB = 0xCB; // MSB + +// enum AS7343AdcChannel { +// AS7343_ADC_CHANNEL_0, +// AS7343_ADC_CHANNEL_1, +// AS7343_ADC_CHANNEL_2, +// AS7343_ADC_CHANNEL_3, +// AS7343_ADC_CHANNEL_4, +// AS7343_ADC_CHANNEL_5, +// }; + +// enum AS7343SmuxCommand { +// AS7343_SMUX_CMD_ROM_RESET, ///< ROM code initialization of SMUX +// AS7343_SMUX_CMD_READ, ///< Read SMUX configuration to RAM from SMUX chain +// AS7343_SMUX_CMD_WRITE, ///< Write SMUX configuration from RAM to SMUX chain +// }; + +class AS7343Component : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + float get_setup_priority() const override; + void update() override; + + void set_f1_sensor(sensor::Sensor *f1_sensor) { f1_ = f1_sensor; } + void set_f2_sensor(sensor::Sensor *f2_sensor) { f2_ = f2_sensor; } + void set_fz_sensor(sensor::Sensor *fz_sensor) { fz_ = fz_sensor; } + void set_f3_sensor(sensor::Sensor *f3_sensor) { f3_ = f3_sensor; } + void set_f4_sensor(sensor::Sensor *f4_sensor) { f4_ = f4_sensor; } + void set_fy_sensor(sensor::Sensor *fy_sensor) { fy_ = fy_sensor; } + void set_f5_sensor(sensor::Sensor *f5_sensor) { f5_ = f5_sensor; } + void set_fxl_sensor(sensor::Sensor *fxl_sensor) { fxl_ = fxl_sensor; } + void set_f6_sensor(sensor::Sensor *f6_sensor) { f6_ = f6_sensor; } + void set_f7_sensor(sensor::Sensor *f7_sensor) { f7_ = f7_sensor; } + void set_f8_sensor(sensor::Sensor *f8_sensor) { f8_ = f8_sensor; } + void set_nir_sensor(sensor::Sensor *nir_sensor) { nir_ = nir_sensor; } + void set_clear_sensor(sensor::Sensor *clear_sensor) { clear_ = clear_sensor; } + + void set_gain(AS7343Gain gain) { gain_ = gain; } + void set_atime(uint8_t atime) { atime_ = atime; } + void set_astep(uint16_t astep) { astep_ = astep; } + + AS7343Gain get_gain(); + uint8_t get_atime(); + uint16_t get_astep(); + bool setup_gain(AS7343Gain gain); + bool setup_atime(uint8_t atime); + bool setup_astep(uint16_t astep); + + // uint16_t read_channel(AS7343AdcChannel channel); + bool read_channels(uint16_t *data); + // void set_smux_low_channels(bool enable); + // bool set_smux_command(AS7343SmuxCommand command); + // void configure_smux_low_channels(); + // void configure_smux_high_channels(); + // bool enable_smux(); + + bool wait_for_data(uint16_t timeout = 1000); + bool is_data_ready(); + bool enable_power(bool enable); + bool enable_spectral_measurement(bool enable); + + bool read_register_bit(uint8_t address, uint8_t bit_position); + bool write_register_bit(uint8_t address, bool value, uint8_t bit_position); + bool set_register_bit(uint8_t address, uint8_t bit_position); + bool clear_register_bit(uint8_t address, uint8_t bit_position); + uint16_t swap_bytes(uint16_t data); + + protected: + void set_bank_for_reg_(AS7343Registers reg = AS7343Registers::ENABLE); + bool bank_{false}; + + sensor::Sensor *f1_{nullptr}; + sensor::Sensor *f2_{nullptr}; + sensor::Sensor *fz_{nullptr}; + sensor::Sensor *f3_{nullptr}; + sensor::Sensor *f4_{nullptr}; + sensor::Sensor *fy_{nullptr}; + sensor::Sensor *f5_{nullptr}; + sensor::Sensor *fxl_{nullptr}; + sensor::Sensor *f6_{nullptr}; + sensor::Sensor *f7_{nullptr}; + sensor::Sensor *f8_{nullptr}; + sensor::Sensor *nir_{nullptr}; + sensor::Sensor *clear_{nullptr}; + + uint16_t astep_; + AS7343Gain gain_; + uint8_t atime_; + uint16_t channel_readings_[AS7343_NUM_CHANNELS]; +}; + +} // namespace as7343 +} // namespace esphome diff --git a/esphome/components/as7343/as7343_registers.h b/esphome/components/as7343/as7343_registers.h new file mode 100644 index 0000000000..45f2b00174 --- /dev/null +++ b/esphome/components/as7343/as7343_registers.h @@ -0,0 +1,107 @@ +#pragma once +#include + +namespace esphome { +namespace as7343 { + +enum class AS7343Registers : uint8_t { + AUXID = 0x58, + REVID = 0x59, + ID = 0x5A, + CFG12 = 0x66, + ENABLE = 0x80, + ATIME = 0x81, + WTIME = 0x83, + SP_TH_L_LSB = 0x84, + SP_TH_L_MSB = 0x85, + SP_TH_H_LSB = 0x86, + SP_TH_H_MSB = 0x87, + STATUS = 0x93, + ASTATUS = 0x94, + DATA_O = 0x95, + STATUS2 = 0x90, + STATUS3 = 0x91, + STATUS5 = 0xBB, + STATUS4 = 0xBC, + CFG0 = 0xBF, + CFG1 = 0xC6, + CFG3 = 0xC7, + CFG6 = 0xF5, + CFG8 = 0xC9, + CFG9 = 0xCA, + CFG10 = 0x65, + PERS = 0xCF, + GPIO = 0x6B, + ASTEP_LSB = 0xD4, + ASTEP_MSB = 0xD5, + CFG20 = 0xD6, + LED = 0xCD, + AGC_GAIN_MAX = 0xD7, + AZ_CONFIG = 0xDE, + FD_TIME_1 = 0xE0, + FD_TIME_2 = 0xE2, + FD_CFG0 = 0xDF, + FD_STATUS = 0xE3, + INTENAB = 0xF9, + CONTROL = 0xFA, + FIFO_MAP = 0xFC, + FIFO_LVL = 0xFD, + FDATA_L = 0xFE, + FDATA_H = 0xFF, +}; + +static constexpr uint8_t AS7343_CHIP_ID = 0b10000001; +static constexpr uint8_t AS7343_ENABLE_PON_BIT = 0; +static constexpr uint8_t AS7343_ENABLE_SP_EN_BIT = 1; +static constexpr uint8_t AS7343_CFG0_REG_BANK_BIT = 4; + +union AS7343RegCfg20 { + uint8_t raw; + struct { + uint8_t reserved : 5; + uint8_t auto_smux : 2; + uint8_t fd_fifo_8b : 1; + }; +}; + +enum AS7343Gain : uint8_t { + AS7343_GAIN_0_5X, + AS7343_GAIN_1X, + AS7343_GAIN_2X, + AS7343_GAIN_4X, + AS7343_GAIN_8X, + AS7343_GAIN_16X, + AS7343_GAIN_32X, + AS7343_GAIN_64X, + AS7343_GAIN_128X, + AS7343_GAIN_256X, + AS7343_GAIN_512X, + AS7343_GAIN_1024X, + AS7343_GAIN_2048X, +}; + +enum AS7343Channel : uint8_t { + AS7343_CHANNEL_450_FZ, + AS7343_CHANNEL_555_FY, + AS7343_CHANNEL_600_FXL, + AS7343_CHANNEL_855_NIR, + AS7343_CHANNEL_CLEAR_1, + AS7343_CHANNEL_FD_1, + AS7343_CHANNEL_425_F2, + AS7343_CHANNEL_475_F3, + AS7343_CHANNEL_515_F4, + AS7343_CHANNEL_640_F6, + AS7343_CHANNEL_CLEAR_0, + AS7343_CHANNEL_FD_0, + AS7343_CHANNEL_405_F1, + AS7343_CHANNEL_550_F5, + AS7343_CHANNEL_690_F7, + AS7343_CHANNEL_745_F8, + AS7343_CHANNEL_CLEAR, + AS7343_CHANNEL_FD, +}; + +static constexpr uint8_t AS7343_NUM_CHANNELS = 18; + +} // namespace as7343 +} // namespace esphome diff --git a/esphome/components/as7343/sensor.py b/esphome/components/as7343/sensor.py new file mode 100644 index 0000000000..e0ffe1c848 --- /dev/null +++ b/esphome/components/as7343/sensor.py @@ -0,0 +1,126 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import i2c, sensor +from esphome.const import ( + CONF_GAIN, + CONF_ID, + CONF_NAME, + DEVICE_CLASS_ILLUMINANCE, + ICON_BRIGHTNESS_5, + STATE_CLASS_MEASUREMENT, +) + + +CODEOWNERS = ["@mrgnr", "@latonita"] +DEPENDENCIES = ["i2c"] + +as7343_ns = cg.esphome_ns.namespace("as7343") + +AS7343Component = as7343_ns.class_( + "AS7343Component", cg.PollingComponent, i2c.I2CDevice +) + +CONF_ATIME = "atime" +CONF_ASTEP = "astep" + +CONF_F1 = "f1" +CONF_F2 = "f2" +CONF_FZ = "fz" +CONF_F3 = "f3" +CONF_F4 = "f4" +CONF_FY = "fy" +CONF_F5 = "f5" +CONF_FXL = "fxl" +CONF_F6 = "f6" +CONF_F7 = "f7" +CONF_F8 = "f8" +CONF_NIR = "nir" +CONF_CLEAR = "clear" + +UNIT_COUNTS = "#" + +AS7343_GAIN = as7343_ns.enum("AS7343Gain") +GAIN_OPTIONS = { + "X0.5": AS7343_GAIN.AS7343_GAIN_0_5X, + "X1": AS7343_GAIN.AS7343_GAIN_1X, + "X2": AS7343_GAIN.AS7343_GAIN_2X, + "X4": AS7343_GAIN.AS7343_GAIN_4X, + "X8": AS7343_GAIN.AS7343_GAIN_8X, + "X16": AS7343_GAIN.AS7343_GAIN_16X, + "X32": AS7343_GAIN.AS7343_GAIN_32X, + "X64": AS7343_GAIN.AS7343_GAIN_64X, + "X128": AS7343_GAIN.AS7343_GAIN_128X, + "X256": AS7343_GAIN.AS7343_GAIN_256X, + "X512": AS7343_GAIN.AS7343_GAIN_512X, + "X1024": AS7343_GAIN.AS7343_GAIN_1024X, + "X2048": AS7343_GAIN.AS7343_GAIN_2048X, +} + + +SENSOR_SCHEMA = cv.maybe_simple_value( + sensor.sensor_schema( + unit_of_measurement=UNIT_COUNTS, + icon=ICON_BRIGHTNESS_5, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), + key=CONF_NAME, +) + + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(AS7343Component), + cv.Optional(CONF_F1): SENSOR_SCHEMA, + cv.Optional(CONF_F2): SENSOR_SCHEMA, + cv.Optional(CONF_FZ): SENSOR_SCHEMA, + cv.Optional(CONF_F3): SENSOR_SCHEMA, + cv.Optional(CONF_F4): SENSOR_SCHEMA, + cv.Optional(CONF_FY): SENSOR_SCHEMA, + cv.Optional(CONF_F5): SENSOR_SCHEMA, + cv.Optional(CONF_FXL): SENSOR_SCHEMA, + cv.Optional(CONF_F6): SENSOR_SCHEMA, + cv.Optional(CONF_F7): SENSOR_SCHEMA, + cv.Optional(CONF_F8): SENSOR_SCHEMA, + cv.Optional(CONF_NIR): SENSOR_SCHEMA, + cv.Optional(CONF_GAIN, default="X8"): cv.enum(GAIN_OPTIONS), + cv.Optional(CONF_ATIME, default=29): cv.int_range(min=0, max=255), + cv.Optional(CONF_ASTEP, default=599): cv.int_range(min=0, max=65534), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x39)) +) + +SENSORS = { + CONF_F1: "set_f1_sensor", + CONF_F2: "set_f2_sensor", + CONF_FZ: "set_fz_sensor", + CONF_F3: "set_f3_sensor", + CONF_F4: "set_f4_sensor", + CONF_FY: "set_fy_sensor", + CONF_F5: "set_f5_sensor", + CONF_FXL: "set_fxl_sensor", + CONF_F6: "set_f6_sensor", + CONF_F7: "set_f7_sensor", + CONF_F8: "set_f8_sensor", + CONF_NIR: "set_nir_sensor", + CONF_CLEAR: "set_clear_sensor", +} + + +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) + + cg.add(var.set_gain(config[CONF_GAIN])) + cg.add(var.set_atime(config[CONF_ATIME])) + cg.add(var.set_astep(config[CONF_ASTEP])) + + for conf_id, set_sensor_func in SENSORS.items(): + if sens_config := config.get(conf_id): + sens = await sensor.new_sensor(sens_config) + cg.add(getattr(var, set_sensor_func)(sens))