Added ads131m08, etc. external component
This commit is contained in:
parent
da6e5961e9
commit
d0f97b46a6
6
.gitignore
vendored
6
.gitignore
vendored
@ -2,10 +2,4 @@
|
||||
# This is an example and may include too much for your use-case.
|
||||
# You can modify this file to suit your needs.
|
||||
/.esphome/
|
||||
.esphome/external_components
|
||||
/secrets.yaml
|
||||
/.esphome.bak/
|
||||
/fonts/
|
||||
**/__pycache__/
|
||||
components/ads131m08/__pycache__/sensor.cpython-312.pyc
|
||||
components/ads131m08/__pycache__/__init__.cpython-312.pyc
|
||||
|
||||
@ -1,29 +1,80 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import spi
|
||||
from esphome.const import (
|
||||
CONF_ID
|
||||
)
|
||||
|
||||
CONF_DRDY_PIN = "drdy_pin"
|
||||
CONF_REFERENCE_VOLTAGE = "reference_voltage"
|
||||
|
||||
DEPENDENCIES = ["spi"]
|
||||
ads131m08_ns = cg.esphome_ns.namespace("ads131m08")
|
||||
ADS131M08Hub = ads131m08_ns.class_("ADS131M08Hub", cg.Component, spi.SPIDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(ADS131M08Hub),
|
||||
cv.Required(CONF_DRDY_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_REFERENCE_VOLTAGE, default=1.2): cv.float_range(min=1.1, max=1.3),
|
||||
}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=True))
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
drdy = await cg.gpio_pin_expression(config[CONF_DRDY_PIN])
|
||||
reference_voltage = config[CONF_REFERENCE_VOLTAGE]
|
||||
cg.add(var.set_reference_voltage(reference_voltage))
|
||||
cg.add(var.set_drdy_pin(drdy))
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import spi
|
||||
from esphome.const import CONF_ID #, CONF_MODE
|
||||
|
||||
# Import ThreadModel enum
|
||||
#from esphome.core import ThreadModel
|
||||
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_DRDY_PIN = "drdy_pin"
|
||||
CONF_SYNC_RESET_PIN = "sync_reset_pin"
|
||||
CONF_REFERENCE_VOLTAGE = "reference_voltage"
|
||||
CONF_CLOCK_FREQUENCY = "clock_frequency"
|
||||
CONF_ADS131M08_ID = "_ads131m08_id"
|
||||
CONF_OSR = "oversampling_ratio"
|
||||
|
||||
DEPENDENCIES = ["spi"]
|
||||
|
||||
ads131m08_ns = cg.esphome_ns.namespace("ads131m08")
|
||||
ADS131M08Hub = ads131m08_ns.class_("ADS131M08Hub", cg.Component, spi.SPIDevice)
|
||||
|
||||
OSR = ads131m08_ns.enum("ADS131M08_OVERSAMPLING_RATIO")
|
||||
ALLOWED_OSRS = {
|
||||
128: OSR.OSR_128,
|
||||
256: OSR.OSR_256,
|
||||
512: OSR.OSR_512,
|
||||
1024: OSR.OSR_1024,
|
||||
2048: OSR.OSR_2048,
|
||||
4096: OSR.OSR_4096,
|
||||
8192: OSR.OSR_8192,
|
||||
16256: OSR.OSR_16256,
|
||||
}
|
||||
|
||||
ALLOWED_CLOCK_FREQUENCIES = {
|
||||
2048000: 2048000,
|
||||
4096000: 4096000,
|
||||
8192000: 8192000,
|
||||
"2048kHz": 2048000,
|
||||
"4096kHz": 4096000,
|
||||
"8192kHz": 8192000,
|
||||
"2.048MHz": 2048000,
|
||||
"4.096MHz": 4096000,
|
||||
"8.192MHz": 8192000,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ADS131M08Hub),
|
||||
cv.Required(CONF_DRDY_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_SYNC_RESET_PIN): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_CLOCK_FREQUENCY, default="8192kHz"): cv.All(cv.frequency, cv.one_of(*ALLOWED_CLOCK_FREQUENCIES.keys())),
|
||||
cv.Optional(CONF_OSR, default=1024): cv.enum(ALLOWED_OSRS, int=True),
|
||||
cv.Optional(CONF_REFERENCE_VOLTAGE, default=1.2): cv.float_range(min=1.1, max=1.3),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(spi.spi_device_schema(cs_pin_required=True, default_data_rate="10MHz"))
|
||||
)
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
drdy = await cg.gpio_pin_expression(config[CONF_DRDY_PIN])
|
||||
if CONF_SYNC_RESET_PIN in config:
|
||||
sync_reset = await cg.gpio_pin_expression(config[CONF_SYNC_RESET_PIN])
|
||||
cg.add(var.set_sync_reset_pin(sync_reset))
|
||||
clock_frequency = ALLOWED_CLOCK_FREQUENCIES[config[CONF_CLOCK_FREQUENCY]]
|
||||
cg.add(var.set_clock_frequency(clock_frequency))
|
||||
osr = config[CONF_OSR]
|
||||
cg.add(var.set_osr(osr))
|
||||
reference_voltage = config[CONF_REFERENCE_VOLTAGE]
|
||||
cg.add(var.set_reference_voltage(reference_voltage))
|
||||
cg.add(var.set_drdy_pin(drdy))
|
||||
#cg.add(var.set_thread_model(ThreadModel.MULTI_ATOMICS))
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,503 +1,229 @@
|
||||
#pragma once
|
||||
// using external voltage reference
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace ads131m08 {
|
||||
|
||||
typedef union {
|
||||
|
||||
int32_t i;
|
||||
float f;
|
||||
uint16_t u[2];
|
||||
uint8_t b[4];
|
||||
} flex32_t;
|
||||
|
||||
|
||||
/* Adc Structure. Ch can be read as int32 or float*/
|
||||
struct AdcOutput
|
||||
{
|
||||
uint16_t status;
|
||||
flex32_t ch[8];
|
||||
};
|
||||
|
||||
enum ADS131M08_DRDY_STATE
|
||||
{
|
||||
DS_LOGIC_HIGH = 0, // DEFAULT
|
||||
DS_HI_Z = 1
|
||||
};
|
||||
|
||||
enum ADS131M08_POWERMODE
|
||||
{
|
||||
PM_VERY_LOW_POWER = 0,
|
||||
PM_LOW_POWER = 1,
|
||||
PM_HIGH_RESOLUTION = 2 // DEFAULT
|
||||
};
|
||||
|
||||
enum ADS131M08_PGA_GAIN
|
||||
{
|
||||
PGA_1 = 0,
|
||||
PGA_2 = 1,
|
||||
PGA_4 = 2,
|
||||
PGA_8 = 3,
|
||||
PGA_16 = 4,
|
||||
PGA_32 = 5,
|
||||
PGA_64 = 6,
|
||||
PGA_128 = 7,
|
||||
PGA_INVALID
|
||||
};
|
||||
|
||||
enum ADS131M08_INPUT_CHANNEL_MUX
|
||||
{
|
||||
ICM_AIN0P_AIN0N = 0, // DEFAULT
|
||||
ICM_INPUT_SHORTED = 1,
|
||||
ICM_POSITIVE_DC_TEST_SIGNAL = 2,
|
||||
ICM_NEGATIVE_DC_TEST_SIGNAL = 3,
|
||||
};
|
||||
|
||||
enum ADS131M08_OVERSAMPLING_RATIO
|
||||
{
|
||||
OSR_128 = 0,
|
||||
OSR_256 = 1,
|
||||
OSR_512 = 2,
|
||||
OSR_1024 = 3, // default
|
||||
OSR_2048 = 4,
|
||||
OSR_4096 = 5,
|
||||
OSR_8192 = 6,
|
||||
OSR_16384 = 7
|
||||
};
|
||||
|
||||
enum ADS131M08_WAIT_TIME
|
||||
{
|
||||
WT_128 = 856,
|
||||
WT_256 = 1112,
|
||||
WT_512 = 1624,
|
||||
WT_1024 = 2648,
|
||||
WT_2048 = 4696,
|
||||
WT_4096 = 8792,
|
||||
WT_8192 = 16984,
|
||||
WT_16384 = 33368
|
||||
};
|
||||
|
||||
// MODE Register
|
||||
enum ADS131M08_RESET : uint16_t
|
||||
{
|
||||
MODE_NO_RESET = 0x0000, // DEFAULT
|
||||
MODE_RESET_HAPPENED = 0x0400
|
||||
};
|
||||
|
||||
enum ADS131M08_CRC_TYPE : uint16_t
|
||||
{
|
||||
CRC_CCITT_16BIT = 0x0000, // DEFAULT
|
||||
CRC_ANSI_16BIT = 0x0800
|
||||
};
|
||||
|
||||
enum ADS131M08_WORD_LENGTH : uint16_t
|
||||
{
|
||||
WLENGTH_16_BITS = 0x0000,
|
||||
WLENGTH_24_BITS = 0x0100, // DEFAULT
|
||||
WLENGTH_32_BITS_LSB_ZERO_PADDING = 0x0200,
|
||||
WLENGTH_32_BITS_MSB_SIGN_EXTEND = 0x0300
|
||||
};
|
||||
|
||||
enum ADS131M08_TIMEOUT : uint16_t
|
||||
{
|
||||
TIMEOUT_DISABLED = 0x0000,
|
||||
TIMEOUT_ENABLED = 0x0010 // DEFAULT
|
||||
};
|
||||
|
||||
enum ADS131M08_DRDY_SELECTION : uint16_t
|
||||
{
|
||||
DRDY_SEL_MOST_LAGGING = 0x0000, // DEFAULT
|
||||
DRDY_SEL_LOGICAL_OR = 0x0004,
|
||||
DRDY_SEL_MOST_LEADING_CHAN = 0x0008,
|
||||
DRDY_SEL_MOST_LEADING_CHAN = 0x000C
|
||||
};
|
||||
enum ADS131M08_DRDY_FORMAT : uint16_t
|
||||
{
|
||||
DRDY_FMT_LEVEL = 0x0000, // Logic low (default)
|
||||
DRDY_FMT_PULSE = 0x0001 // Low pulse with a fixed duration
|
||||
};
|
||||
// end of MODE Register
|
||||
|
||||
// GAIN1 Register
|
||||
enum ADS131M08_GAIN1_CHANNEL_PGA : uint16_t {
|
||||
PGAGAIN0_1 = 0x0000, // default
|
||||
PGAGAIN0_2 = 0x0001,
|
||||
PGAGAIN0_4 = 0x0002,
|
||||
PGAGAIN0_8 = 0x0003,
|
||||
PGAGAIN0_16 = 0x0004,
|
||||
PGAGAIN0_32 = 0x0005,
|
||||
PGAGAIN0_64 = 0x0006,
|
||||
PGAGAIN0_128 = 0x0007,
|
||||
PGAGAIN1_1 = 0x0000, // default
|
||||
PGAGAIN1_2 = 0x0010,
|
||||
PGAGAIN1_4 = 0x0020,
|
||||
PGAGAIN1_8 = 0x0030,
|
||||
PGAGAIN1_16 = 0x0040,
|
||||
PGAGAIN1_32 = 0x0050,
|
||||
PGAGAIN1_64 = 0x0060,
|
||||
PGAGAIN1_128 = 0x0070,
|
||||
PGAGAIN2_1 = 0x0000, // default
|
||||
PGAGAIN2_2 = 0x0100,
|
||||
PGAGAIN2_4 = 0x0200,
|
||||
PGAGAIN2_8 = 0x0300,
|
||||
PGAGAIN2_16 = 0x0400,
|
||||
PGAGAIN2_32 = 0x0500,
|
||||
PGAGAIN2_64 = 0x0600,
|
||||
PGAGAIN2_128 = 0x0700,
|
||||
PGAGAIN3_1 = 0x0000, // default
|
||||
PGAGAIN3_2 = 0x1000,
|
||||
PGAGAIN3_4 = 0x2000,
|
||||
PGAGAIN3_8 = 0x3000,
|
||||
PGAGAIN3_16 = 0x4000,
|
||||
PGAGAIN3_32 = 0x5000, // Set PGA gain to 32 for channel
|
||||
PGAGAIN3_64 = 0x6000,
|
||||
PGAGAIN3_128 = 0x7000
|
||||
};
|
||||
// end of GAIN1 Register
|
||||
|
||||
// GAIN2 Register
|
||||
enum ADS131M08_GAIN2_CHANNEL_PGA : uint16_t {
|
||||
PGAGAIN4_1 = 0x0000, // default
|
||||
PGAGAIN4_2 = 0x0001,
|
||||
PGAGAIN4_4 = 0x0002,
|
||||
PGAGAIN4_8 = 0x0003,
|
||||
PGAGAIN4_16 = 0x0004,
|
||||
PGAGAIN4_32 = 0x0005,
|
||||
PGAGAIN4_64 = 0x0006,
|
||||
PGAGAIN4_128 = 0x0007,
|
||||
PGAGAIN5_1 = 0x0000, // default
|
||||
PGAGAIN5_2 = 0x0010,
|
||||
PGAGAIN5_4 = 0x0020,
|
||||
PGAGAIN5_8 = 0x0030,
|
||||
PGAGAIN5_16 = 0x0040,
|
||||
PGAGAIN5_32 = 0x0050,
|
||||
PGAGAIN5_64 = 0x0060,
|
||||
PGAGAIN5_128 = 0x0070,
|
||||
PGAGAIN6_1 = 0x0000, // default
|
||||
PGAGAIN6_2 = 0x0100,
|
||||
PGAGAIN6_4 = 0x0200,
|
||||
PGAGAIN6_8 = 0x0300,
|
||||
PGAGAIN6_16 = 0x0400,
|
||||
PGAGAIN6_32 = 0x0500,
|
||||
PGAGAIN6_64 = 0x0600,
|
||||
PGAGAIN6_128 = 0x0700,
|
||||
PGAGAIN7_1 = 0x0000, // default
|
||||
PGAGAIN7_2 = 0x1000,
|
||||
PGAGAIN7_4 = 0x2000,
|
||||
PGAGAIN7_8 = 0x3000,
|
||||
PGAGAIN7_16 = 0x4000,
|
||||
PGAGAIN7_32 = 0x5000,
|
||||
PGAGAIN7_64 = 0x6000,
|
||||
PGAGAIN7_128 = 0x7000
|
||||
};
|
||||
// end of GAIN2 Register
|
||||
|
||||
|
||||
// Commands
|
||||
enum ADS131M08_COMMANDS : uint16_t {
|
||||
CMD_NULL = 0x0000, // No operation; used to read STATUS register
|
||||
CMD_RESET = 0x0011, // RESET the device
|
||||
CMD_STANDBY = 0x0022, // Place the device into standby mode
|
||||
CMD_WAKEUP = 0x0033, // Wake up device from standby mode to conversion mode
|
||||
CMD_LOCK = 0x0555, // Lock the interface such that only the NULL, UNLOCK, and RREG commands are valid
|
||||
CMD_UNLOCK = 0x0655, // Unlock the interface after the interface is locked
|
||||
CMD_RREG = 0xA000, // Read register command base; number of registers to read added to lower byte; register address to upper byte
|
||||
CMD_WREG = 0x6000, // Write register command base; number of registers to write added to lower byte; register address to upper byte
|
||||
};
|
||||
|
||||
// Responses
|
||||
enum ADS131M08_RESPONSES : uint16_t {
|
||||
RSP_RESET_OK = 0xFF28,
|
||||
RSP_RESET_NOK = 0x0011
|
||||
};
|
||||
|
||||
enum ADS131M08_REG {
|
||||
REG_ID = 0x00,
|
||||
REG_STATUS = 0x01,
|
||||
REG_MODE = 0x02,
|
||||
REG_CLOCK = 0x03,
|
||||
REG_GAIN1 = 0x04,
|
||||
REG_GAIN2 = 0x05,
|
||||
REG_CFG = 0x06,
|
||||
REG_THRSHLD_MSB = 0x07,
|
||||
REG_THRSHLD_LSB = 0x08,
|
||||
REG_CH0_CFG = 0x09,
|
||||
REG_CH0_OCAL_MSB = 0x0A,
|
||||
REG_CH0_OCAL_LSB = 0x0B,
|
||||
REG_CH0_GCAL_MSB = 0x0C,
|
||||
REG_CH0_GCAL_LSB = 0x0D,
|
||||
REG_CH1_CFG = 0x0E,
|
||||
REG_CH1_OCAL_MSB = 0x0F,
|
||||
REG_CH1_OCAL_LSB = 0x10,
|
||||
REG_CH1_GCAL_MSB = 0x11,
|
||||
REG_CH1_GCAL_LSB = 0x12,
|
||||
REG_CH2_CFG = 0x13,
|
||||
REG_CH2_OCAL_MSB= 0x14,
|
||||
REG_CH2_OCAL_LSB= 0x15,
|
||||
REG_CH2_GCAL_MSB= 0x16,
|
||||
REG_CH2_GCAL_LSB= 0x17,
|
||||
REG_CH3_CFG = 0x18,
|
||||
REG_CH3_OCAL_MSB= 0x19,
|
||||
REG_CH3_OCAL_LSB= 0x1A,
|
||||
REG_CH3_GCAL_MSB= 0x1B,
|
||||
REG_CH3_GCAL_LSB= 0x1C,
|
||||
REG_CH4_CFG = 0x1D,
|
||||
REG_CH4_OCAL_MSB= 0x1E,
|
||||
REG_CH4_OCAL_LSB= 0x1F,
|
||||
REG_CH4_GCAL_MSB= 0x20,
|
||||
REG_CH4_GCAL_LSB= 0x21,
|
||||
REG_CH5_CFG = 0x22,
|
||||
REG_CH5_OCAL_MSB= 0x23,
|
||||
REG_CH5_OCAL_LSB= 0x24,
|
||||
REG_CH5_GCAL_MSB= 0x25,
|
||||
REG_CH5_GCAL_LSB= 0x26,
|
||||
REG_CH6_CFG = 0x27,
|
||||
REG_CH6_OCAL_MSB= 0x28,
|
||||
REG_CH6_OCAL_LSB= 0x29,
|
||||
REG_CH6_GCAL_MSB= 0x2A,
|
||||
REG_CH6_GCAL_LSB= 0x2B,
|
||||
REG_CH7_CFG = 0x2C,
|
||||
REG_CH7_OCAL_MSB= 0x2D,
|
||||
REG_CH7_OCAL_LSB= 0x2E,
|
||||
REG_CH7_GCAL_MSB= 0x2F,
|
||||
REG_CH7_GCAL_LSB= 0x30,
|
||||
REGMAP_CRC = 0x3E,
|
||||
};
|
||||
// Mask READ_REG
|
||||
static constexpr uint16_t MASK_CMD_READ_REG_ADDRESS = 0x1F80;
|
||||
static constexpr uint16_t MASK_CMD_READ_REG_BYTES = 0x007F;
|
||||
|
||||
// Mask Register STATUS
|
||||
static constexpr uint16_t MASK_STATUS_LOCK = 0x8000;
|
||||
static constexpr uint16_t MASK_STATUS_RESYNC = 0x4000;
|
||||
static constexpr uint16_t MASK_STATUS_REGMAP = 0x2000;
|
||||
static constexpr uint16_t MASK_STATUS_CRC_ERR = 0x1000;
|
||||
static constexpr uint16_t MASK_STATUS_CRC_TYPE = 0x0800;
|
||||
static constexpr uint16_t MASK_STATUS_RESET = 0x0400;
|
||||
static constexpr uint16_t MASK_STATUS_WLENGTH = 0x0300;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY7 = 0x0080;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY6 = 0x0040;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY5 = 0x0020;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY4 = 0x0010;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY3 = 0x0008;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY2 = 0x0004;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY1 = 0x0002;
|
||||
static constexpr uint16_t MASK_STATUS_DRDY0 = 0x0001;
|
||||
|
||||
// Mask Register MODE
|
||||
static constexpr uint16_t MASK_MODE_REG_CRC_EN = 0x2000;
|
||||
static constexpr uint16_t MASK_MODE_RX_CRC_EN = 0x1000;
|
||||
static constexpr uint16_t MASK_MODE_CRC_TYPE = 0x0800;
|
||||
static constexpr uint16_t MASK_MODE_RESET = 0x0400;
|
||||
static constexpr uint16_t MASK_MODE_WLENGTH = 0x0300;
|
||||
static constexpr uint16_t MASK_MODE_TIMEOUT = 0x0010;
|
||||
static constexpr uint16_t MASK_MODE_DRDY_SEL = 0x000C;
|
||||
static constexpr uint16_t MASK_MODE_DRDY_HiZ = 0x0002;
|
||||
static constexpr uint16_t MASK_MODE_DRDY_FMT = 0x0001;
|
||||
|
||||
// Mask Register CLOCK
|
||||
static constexpr uint16_t MASK_CLOCK_CH7_EN = 0x8000;
|
||||
static constexpr uint16_t MASK_CLOCK_CH6_EN = 0x4000;
|
||||
static constexpr uint16_t MASK_CLOCK_CH5_EN = 0x2000;
|
||||
static constexpr uint16_t MASK_CLOCK_CH4_EN = 0x1000;
|
||||
static constexpr uint16_t MASK_CLOCK_CH3_EN = 0x0800;
|
||||
static constexpr uint16_t MASK_CLOCK_CH2_EN = 0x0400;
|
||||
static constexpr uint16_t MASK_CLOCK_CH1_EN = 0x0200;
|
||||
static constexpr uint16_t MASK_CLOCK_CH0_EN = 0x0100;
|
||||
static constexpr uint16_t MASK_CLOCK_OSR = 0x001C;
|
||||
static constexpr uint16_t MASK_CLOCK_PWR = 0x0003;
|
||||
static constexpr uint32_t MASK_CLOCK_ALL_CH_DISABLE = 0x0000;
|
||||
static constexpr uint32_t MASK_CLOCK_ALL_CH_ENABLE = 0xFF00;
|
||||
// Mask Register GAIN
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN7 = 0x7000;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN6 = 0x0700;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN5 = 0x0070;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN4 = 0x0007;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN3 = 0x7000;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN2 = 0x0700;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN1 = 0x0070;
|
||||
static constexpr uint16_t MASK_GAIN_PGAGAIN0 = 0x0007;
|
||||
|
||||
// Mask Register CFG
|
||||
static constexpr uint16_t MASK_CFG_GC_DLY = 0x1E00;
|
||||
static constexpr uint16_t MASK_CFG_GC_EN = 0x0100;
|
||||
static constexpr uint16_t MASK_CFG_CD_ALLCH = 0x0080;
|
||||
static constexpr uint16_t MASK_CFG_CD_NUM = 0x0070;
|
||||
static constexpr uint16_t MASK_CFG_CD_LEN = 0x000E;
|
||||
static constexpr uint16_t MASK_CFG_CD_EN = 0x0001;
|
||||
|
||||
// Mask Register THRSHLD_MSB - dummy, for completeness
|
||||
static constexpr uint16_t MASK_THRSHLD_MSB_CD_TH_MSB = 0xFFFF;
|
||||
|
||||
// Mask Register THRSHLD_LSB
|
||||
static constexpr uint16_t MASK_THRSHLD_LSB_CD_TH_LSB = 0xFF00;
|
||||
static constexpr uint16_t MASK_THRSHLD_LSB_DCBLOCK = 0x000F;
|
||||
|
||||
// Mask Register CHX_CFG
|
||||
static constexpr uint16_t MASK_CHX_CFG_PHASE = 0xFFC0;
|
||||
static constexpr uint16_t MASK_CHX_CFG_DCBLKX_DIS = 0x0004;
|
||||
static constexpr uint16_t MASK_CHX_CFG_MUX = 0x0003;
|
||||
|
||||
// Mask Register CHX_OCAL_MSB - dummy, for completeness
|
||||
static constexpr uint16_t MASK_CHX_OCAL_MSB = 0xFFFF;
|
||||
|
||||
// Mask Register CHX_OCAL_LSB
|
||||
static constexpr uint16_t MASK_CHX_OCAL_LSB = 0xFF00;
|
||||
|
||||
// Mask Register CHX_GCAL_MSB - dummy, for completeness
|
||||
static constexpr uint16_t MASK_CHX_GCAL_MSB = 0xFFFF;
|
||||
|
||||
// Mask Register CHX_GCAL_LSB
|
||||
static constexpr uint16_t MASK_CHX_GCAL_LSB = 0xFF00;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Conversion modes
|
||||
static constexpr uint16_t CONVERSION_MODE_CONT = 0;
|
||||
static constexpr uint16_t CONVERSION_MODE_SINGLE = 1;
|
||||
|
||||
// Data Format
|
||||
static constexpr uint16_t DATA_FORMAT_TWO_COMPLEMENT = 0;
|
||||
static constexpr uint16_t DATA_FORMAT_BINARY = 1;
|
||||
|
||||
// Measure Mode
|
||||
static constexpr uint8_t MEASURE_UNIPOLAR = 1;
|
||||
static constexpr uint8_t MEASURE_BIPOLAR = 0;
|
||||
|
||||
// Clock Type
|
||||
static constexpr uint8_t CLOCK_EXTERNAL = 1;
|
||||
static constexpr uint8_t CLOCK_INTERNAL = 0;
|
||||
|
||||
// PGA Gain
|
||||
// static constexpr uint16_t PGA_GAIN_1 = 0;
|
||||
// static constexpr uint16_t PGA_GAIN_2 = 1;
|
||||
// static constexpr uint16_t PGA_GAIN_4 = 2;
|
||||
// static constexpr uint16_t PGA_GAIN_8 = 3;
|
||||
// static constexpr uint16_t PGA_GAIN_16 = 4;
|
||||
// static constexpr uint16_t PGA_GAIN_32 = 5;
|
||||
// static constexpr uint16_t PGA_GAIN_64 = 6;
|
||||
// static constexpr uint16_t PGA_GAIN_128 = 7;
|
||||
|
||||
// Input Filter
|
||||
static constexpr uint16_t FILTER_SYNC = 0;
|
||||
static constexpr uint16_t FILTER_FIR = 2;
|
||||
static constexpr uint16_t FILTER_FIR_IIR = 3;
|
||||
|
||||
// Data Mode
|
||||
static constexpr uint8_t DATA_MODE_24BITS = 0;
|
||||
static constexpr uint8_t DATA_MODE_32BITS = 1;
|
||||
|
||||
// Data Rate
|
||||
static constexpr uint8_t DATA_RATE_0 = 0;
|
||||
static constexpr uint8_t DATA_RATE_1 = 1;
|
||||
static constexpr uint8_t DATA_RATE_2 = 2;
|
||||
static constexpr uint8_t DATA_RATE_3 = 3;
|
||||
static constexpr uint8_t DATA_RATE_4 = 4;
|
||||
static constexpr uint8_t DATA_RATE_5 = 5;
|
||||
static constexpr uint8_t DATA_RATE_6 = 6;
|
||||
static constexpr uint8_t DATA_RATE_7 = 7;
|
||||
static constexpr uint8_t DATA_RATE_8 = 8;
|
||||
static constexpr uint8_t DATA_RATE_9 = 9;
|
||||
static constexpr uint8_t DATA_RATE_10 = 10;
|
||||
static constexpr uint8_t DATA_RATE_11 = 11;
|
||||
static constexpr uint8_t DATA_RATE_12 = 12;
|
||||
static constexpr uint8_t DATA_RATE_13 = 13;
|
||||
static constexpr uint8_t DATA_RATE_14 = 14;
|
||||
static constexpr uint8_t DATA_RATE_15 = 15;
|
||||
// Sync Mpdes
|
||||
static constexpr uint16_t SYNC_CONTINUOUS = 1;
|
||||
static constexpr uint16_t SYNC_PULSE = 0;
|
||||
|
||||
// DIO Config Mode
|
||||
static constexpr uint8_t DIO_OUTPUT = 1;
|
||||
static constexpr uint8_t DIO_INPUT = 0;
|
||||
|
||||
static constexpr uint8_t SPI_MASTER_DUMMY = 0xFF;
|
||||
static constexpr uint16_t SPI_MASTER_DUMMY16 = 0xFFFF;
|
||||
static constexpr uint32_t SPI_MASTER_DUMMY32 = 0xFFFFFFFF;
|
||||
|
||||
|
||||
// end of from datasheet
|
||||
|
||||
class ADS131M08Sensor : public sensor::Sensor, public Component
|
||||
{
|
||||
};
|
||||
|
||||
class ADS131M08Hub : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_8MHZ>
|
||||
{
|
||||
public:
|
||||
// from datasheet pg. 93:
|
||||
const int numFrameWords = 10; // Number of words in a full ADS131M08 SPI frame
|
||||
unsigned long spiDummyWord[10 /*numFrameWords*/] = {
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000
|
||||
}; // Dummy word frame to write ADC during ADC data reads
|
||||
bool firstRead = true; // Flag to tell us if we are reading ADC data for the first time
|
||||
signed long adcData; // Location where DMA will store ADC data in memory, length defined elsewhere
|
||||
void txf_init();
|
||||
bool adcRegisterWrite(unsigned short addrMask, unsigned short data, unsigned char adcWordLength);
|
||||
void initialize_ads131m08_datasheet();
|
||||
// end of from datasheet
|
||||
|
||||
bool setChannelPGA(uint8_t channel, uint8_t pga);
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void set_drdy_pin(InternalGPIOPin *pin) { drdy_pin_ = pin; }
|
||||
void register_sensor(int channel, ADS131M08Sensor *s) { sensors_[channel] = s; }
|
||||
void set_reference_voltage(float reference_voltage) { this->reference_voltage_ = reference_voltage; }
|
||||
void dump_config() override;
|
||||
|
||||
// from tpcorrea
|
||||
void begin(uint8_t clk_pin, uint8_t miso_pin, uint8_t mosi_pin, uint8_t cs_pin, uint8_t drdy_pin, uint8_t reset_pin);
|
||||
int8_t isDataReadySoft(uint8_t channel);
|
||||
bool isDataReady(void);
|
||||
bool isResetStatus(void);
|
||||
bool isLockSPI(void);
|
||||
bool setDrdyFormat(uint8_t drdyFormat);
|
||||
bool setDrdyStateWhenUnavailable(uint8_t drdyState);
|
||||
bool setPowerMode(uint8_t powerMode);
|
||||
bool setChannelEnable(uint8_t channel, uint16_t enable);
|
||||
bool setChannelPGA(uint8_t channel, ADS131M08_PGA_GAIN pga);
|
||||
ADS131M08_PGA_GAIN getChannelPGA(uint8_t channel);
|
||||
void setGlobalChop(uint16_t global_chop);
|
||||
void setGlobalChopDelay(uint16_t delay);
|
||||
bool setInputChannelSelection(uint8_t channel, uint8_t input);
|
||||
bool setChannelOffsetCalibration(uint8_t channel, int32_t offset);
|
||||
bool setChannelGainCalibration(uint8_t channel, uint32_t gain);
|
||||
bool setOsr(uint16_t osr);
|
||||
void setFullScale(uint8_t channel, float scale);
|
||||
float getFullScale(uint8_t channel);
|
||||
void reset();
|
||||
uint16_t getId();
|
||||
uint16_t getModeReg();
|
||||
uint16_t getClockReg();
|
||||
uint16_t getCfgReg();
|
||||
AdcOutput readAdcRaw(void);
|
||||
AdcOutput readAdcFloat(void);
|
||||
|
||||
protected:
|
||||
float reference_voltage_;
|
||||
InternalGPIOPin *drdy_pin_;
|
||||
ADS131M08Sensor *sensors_[8] = {nullptr};
|
||||
volatile bool data_ready_{false};
|
||||
static void isr(ADS131M08Hub *arg);
|
||||
void read_data_();
|
||||
void write_register(uint8_t reg, uint16_t value);
|
||||
|
||||
};
|
||||
|
||||
} // namespace ads131m08
|
||||
} // namespace esphome
|
||||
#pragma once
|
||||
// using external voltage reference
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/optional.h"
|
||||
#include "ads131m08_defs.h"
|
||||
#include "frame.h"
|
||||
#include <string>
|
||||
#include <charconv>
|
||||
#include <format>
|
||||
|
||||
//#include "esphome/core/component.h"
|
||||
//#include <esphome/core/hal.h>
|
||||
#include "esphome/components/spi/spi.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
//
|
||||
//#include <vector>
|
||||
//#include <esphome/core/gpio.h>
|
||||
//#include <freertos/FreeRTOS.h>
|
||||
//#include <freertos/semphr.h>
|
||||
//#include <atomic>
|
||||
|
||||
namespace esphome {
|
||||
namespace ads131m08 {
|
||||
|
||||
static const int MAX_CHANNELS = 11; // for debugging
|
||||
static const int ADC_CHANNELS = 8;
|
||||
static const int SAMPLE_TIME_SENSOR = 8; // for debugging
|
||||
static const int MAX_SAMPLES_SENSOR = 9; // for debugging
|
||||
static const int CRC_ERRORS_SENSOR = 10; // for debugging
|
||||
|
||||
typedef union {
|
||||
|
||||
int32_t i;
|
||||
float f;
|
||||
uint16_t u[2];
|
||||
uint8_t b[4];
|
||||
} flex32_t;
|
||||
|
||||
|
||||
/* Adc Structure. Ch can be read as int32 or float*/
|
||||
struct AdcOutput
|
||||
{
|
||||
uint16_t status;
|
||||
flex32_t ch[ADC_CHANNELS];
|
||||
};
|
||||
|
||||
//#define SET_IRAM IRAM_ATTR
|
||||
#define SET_IRAM
|
||||
|
||||
typedef std::vector<uint8_t> spiframe;
|
||||
typedef uint_str<uint16_t>::Ty_string uint16_str; // we want to use the stack to pass small arrays
|
||||
|
||||
class ADS131M08Hub : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_8MHZ>
|
||||
{
|
||||
friend class ads131m08_select;
|
||||
public:
|
||||
enum crc_pos: uint8_t {
|
||||
crc_after_frame,
|
||||
crc_after_firstword,
|
||||
};
|
||||
// register config values used
|
||||
static constexpr uint16_t reg_clock_cfg = MASK_CLOCK_EXTREF_EN | OSR_1024 | PM_HIGH_RESOLUTION;
|
||||
static constexpr uint16_t reg_clock_allch_on = MASK_CLOCK_ALLCH | reg_clock_cfg;
|
||||
static constexpr uint16_t reg_clock_allch_off = ~MASK_CLOCK_ALLCH & reg_clock_cfg;
|
||||
static constexpr uint16_t reg_mode_cfg16 = WLENGTH_16_BITS | DRDY_FMT_PULSE | TIMEOUT_ENABLED;
|
||||
static constexpr uint16_t reg_mode_cfg24 = WLENGTH_24_BITS | DRDY_FMT_PULSE | TIMEOUT_ENABLED;
|
||||
static constexpr uint16_t reg_mode_cfg32 = WLENGTH_32_BITS_MSB_SIGN_EXTEND | DRDY_FMT_PULSE | TIMEOUT_ENABLED;
|
||||
// masks for the above
|
||||
static constexpr uint16_t reg_clock_cfg_mask = MASK_CLOCK_EXTREF_EN | MASK_CLOCK_OSR | MASK_CLOCK_PWR;
|
||||
static constexpr uint16_t reg_clock_allch_mask = MASK_CLOCK_ALLCH_OFF | reg_clock_cfg_mask;
|
||||
static constexpr uint16_t reg_mode_cfg_mask = MASK_MODE_WLENGTH | MASK_MODE_DRDY_FMT | MASK_MODE_TIMEOUT;
|
||||
// Semaphore handles
|
||||
SemaphoreHandle_t data_ready_semhandle = NULL;
|
||||
//SemaphoreHandle_t spi_mutex = NULL;
|
||||
// from datasheet pg. 93:
|
||||
const int numFrameWords = 10; // Number of words in a full ADS131M08 SPI frame
|
||||
spiframe base_frame;
|
||||
bool firstRead = true; // Flag to tell us if we are reading ADC data for the first time
|
||||
signed long adcData; // Location where DMA will store ADC data in memory, length defined elsewhere
|
||||
ADS131M08Hub();
|
||||
void txf_init();
|
||||
bool adc_initialize(uint8_t word_length);
|
||||
bool adc_set_word_length(uint8_t word_length);
|
||||
// end of from datasheet
|
||||
void set_channel_gain(uint8_t channel, ADS131M08_PGA_GAIN gain);
|
||||
//virtual void spi_setup() override;
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void set_drdy_pin(InternalGPIOPin *pin) { drdy_pin_ = pin; }
|
||||
void set_sync_reset_pin(InternalGPIOPin *pin) { sync_reset_pin_ = pin; }
|
||||
void set_clock_frequency(float clock_frequency) { this->clock_frequency_ = clock_frequency; }
|
||||
void register_sensor_ac(int channel, sensor::Sensor *s) { sensors_ac[channel] = s; }
|
||||
void register_sensor_dc(int channel, sensor::Sensor *s) { sensors_dc[channel] = s; }
|
||||
void set_reference_voltage(float reference_voltage) { this->reference_voltage_ = reference_voltage; }
|
||||
void set_osr(uint16_t osr) { this->osr_ = osr; }
|
||||
void dump_config() override;
|
||||
|
||||
// from tpcorrea
|
||||
ADS131M08_PGA_GAIN pgaGain[ADC_CHANNELS] = {PGA_1}; // Store the current PGA gain settings for each channel
|
||||
int8_t is_data_ready_soft(uint8_t channel);
|
||||
bool is_data_ready();
|
||||
bool is_reset_status();
|
||||
bool is_lock_spi();
|
||||
bool set_drdy_format(uint8_t drdy_format);
|
||||
bool set_drdy_idle_state(uint8_t drdy_state);
|
||||
bool set_power_mode(uint8_t power_mode);
|
||||
bool set_channel_enable(uint8_t channel, bool enable);
|
||||
bool set_channel_pga(uint8_t channel, ADS131M08_PGA_GAIN pga);
|
||||
ADS131M08_PGA_GAIN get_channel_pga(uint8_t channel);
|
||||
void set_global_chop(uint16_t global_chop);
|
||||
void set_global_chop_delay(uint16_t delay);
|
||||
bool set_channel_input_selection(uint8_t channel, ADS131M08_INPUT_CHANNEL_MUX input);
|
||||
bool set_channel_offset_calibration(uint8_t channel, int32_t offset);
|
||||
bool set_channel_gain_calibration(uint8_t channel, uint32_t gain);
|
||||
bool set_channel_phase_calibration(uint8_t channel, int16_t phase_offset);
|
||||
bool set_dcblock_filter_disable(uint8_t channel, bool disable);
|
||||
void set_measure_rms(uint8_t channel, bool enable);
|
||||
float get_sampled_value(uint8_t channel) { return sampled_values_[channel]; }
|
||||
bool set_reg_osr();
|
||||
void set_full_scale(uint8_t channel, float scale);
|
||||
float get_full_scale(uint8_t channel);
|
||||
uint16_t get_id();
|
||||
uint16_t get_mode_reg();
|
||||
uint16_t get_clock_reg();
|
||||
uint16_t get_cfg_reg();
|
||||
AdcOutput read_adc_raw();
|
||||
AdcOutput read_adc_float();
|
||||
|
||||
protected:
|
||||
static void IRAM_ATTR isr_handler(ADS131M08Hub *arg);
|
||||
//volatile bool data_ready_{false};
|
||||
//static void isr(ADS131M08Hub *arg);
|
||||
float reference_voltage_;
|
||||
float clock_frequency_;
|
||||
InternalGPIOPin *drdy_pin_;
|
||||
InternalGPIOPin *sync_reset_pin_= {nullptr};
|
||||
sensor::Sensor *sensors_ac[MAX_CHANNELS] = {nullptr};
|
||||
sensor::Sensor *sensors_dc[MAX_CHANNELS] = {nullptr};
|
||||
float sampled_values_[ADC_CHANNELS];
|
||||
bool rms_enabled_[ADC_CHANNELS];
|
||||
bool rms_calc_req_{false};
|
||||
uint16_t osr_{3};
|
||||
uint8_t update_adc_word_length();
|
||||
void SET_IRAM read_single();
|
||||
std::pair<uint32_t, uint32_t> SET_IRAM read_multi();
|
||||
bool adc_lock(bool enable);
|
||||
bool adc_register_write(uint16_t address, uint16_t data);
|
||||
bool adc_register_write(uint16_t address, const uint16_str& data);
|
||||
uint16_str adc_register_read(uint8_t address, uint8_t nregs);
|
||||
bool adc_register_write_masked(uint8_t address, uint16_t value, uint16_t mask, int line);
|
||||
bool adc_register_write_masked(uint8_t start_address, const uint16_str& values, const uint16_str& masks, int line);
|
||||
uint16_t readRegister(uint8_t address);
|
||||
bool adc_reset_retry();
|
||||
bool adc_soft_reset();
|
||||
void adc_hard_reset();
|
||||
void adc_sync();
|
||||
void write_byte(uint8_t byte);
|
||||
bool write(uint32_t data, uint8_t adcWordLength);
|
||||
uint8_t read_byte();
|
||||
void write_array(const spiframe& data);
|
||||
void SET_IRAM read_array(spiframe& buffer);
|
||||
void transfer_array(const spiframe& data_out, spiframe& data_in);
|
||||
uint16_t SET_IRAM get_crc(const spiframe& frame);
|
||||
bool SET_IRAM check_crc(const spiframe& frame_with_crc);
|
||||
size_t SET_IRAM add_crc(spiframe& frame, crc_pos crcpos);
|
||||
uint16_t SET_IRAM read_frame_crc(const spiframe& frame);
|
||||
uint16_t SET_IRAM crc(uint16_t crc_register, uint8_t data);
|
||||
bool SET_IRAM set_frame_word(spiframe& frame, int w_index, uint16_t data); // write 16 bit data to first two bytes of word
|
||||
bool SET_IRAM set_frame_word(spiframe& frame, int w_index, uint32_t data);
|
||||
uint32_t SET_IRAM get_unsigned_frame_word(const spiframe& frame, int w_index, bool force_16bits = false);
|
||||
int32_t SET_IRAM get_sign_ext_frame_word(const spiframe& frame, int w_index);
|
||||
std::atomic<int> adc_init_{0};
|
||||
std::atomic<int> cs_ctr_{0}; // Counter to track nested CS enable/disable calls for proper handling of multiple transfers in a row
|
||||
std::atomic<uint16_t> isr_ctr_{0};
|
||||
void enable(const char *txt);
|
||||
void disable(const char *txt);
|
||||
struct chipselect {
|
||||
ADS131M08Hub* parent_{nullptr};
|
||||
const char *txt_;
|
||||
chipselect(ADS131M08Hub *parent, const char *txt = nullptr) {
|
||||
parent_ = parent;
|
||||
if(parent_ != nullptr)
|
||||
txt_ = txt;
|
||||
parent_->enable(txt_);
|
||||
}
|
||||
~chipselect() {
|
||||
if(parent_ != nullptr) {
|
||||
parent_->disable(txt_);
|
||||
parent_ = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
private:
|
||||
|
||||
uint8_t adc_word_length_{24};
|
||||
float conversion_factor_{1.2/8388608.0};
|
||||
const uint32_t sample_time_ = 40000; // 250 ms
|
||||
float sps_{0.0f};
|
||||
uint32_t num_samples_[ADC_CHANNELS];
|
||||
int64_t sample_sum_[ADC_CHANNELS];
|
||||
float sample_squared_sum_[ADC_CHANNELS];
|
||||
// for debug only
|
||||
std::string frame_to_string(const spiframe& frame);
|
||||
std::string conversion_frame_to_string(const spiframe& frame);
|
||||
std::string command_to_string(uint16_t cmdadr);
|
||||
void print_command_response_to_string(uint16_t cmdadr_sent, const spiframe& frame);
|
||||
std::string rwreg_command_frame_to_string(const spiframe& frame);
|
||||
std::string status_to_string(uint16_t response);
|
||||
std::string reg_data_to_string(int address, uint16_t data, bool nameonly = false);
|
||||
std::string reg_addr_to_string(int address);
|
||||
std::string reg_config_to_string(int address, uint16_t data, bool nameonly = false);
|
||||
//temp
|
||||
int first_read_data {0};
|
||||
};
|
||||
|
||||
#ifndef CHIP_SELECT
|
||||
# if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
||||
# define CHIP_SELECT volatile chipselect cs(this, __FUNCTION__);
|
||||
# else
|
||||
# define CHIP_SELECT volatile chipselect cs(this);
|
||||
# endif
|
||||
# define CHIP_SELECTx volatile chipselect cs(this);
|
||||
#endif
|
||||
|
||||
} // namespace ads131m08
|
||||
} // namespace esphome
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ void DS3231Component::dump_config() {
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str());
|
||||
// ESP_LOGCONFIG(TAG, " Timezone: '%s'", this->timezone_.c_str());
|
||||
if (!this->read_bytes(0, this->ds3231_.raw, sizeof(this->ds3231_.raw))) {
|
||||
ESP_LOGE(TAG, "Can't read I2C data.");
|
||||
}
|
||||
@ -50,7 +50,8 @@ void DS3231Component::read_time() {
|
||||
.year = uint16_t(ds3231_.reg.year + 10u * ds3231_.reg.year_10 + 2000),
|
||||
.is_dst = false, // not used
|
||||
.timestamp = 0 // overwritten by recalc_timestamp_utc(false)
|
||||
};
|
||||
|
||||
};
|
||||
rtc_time.recalc_timestamp_utc(false);
|
||||
if (!rtc_time.is_valid()) {
|
||||
ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock.");
|
||||
@ -79,7 +80,7 @@ void DS3231Component::write_time() {
|
||||
ds3231_.reg.second = now.second % 10;
|
||||
ds3231_.reg.second_10 = now.second / 10;
|
||||
ds3231_.reg.ch = false;
|
||||
|
||||
// ESPHOME emits warning about synchronous mode; must check datasheet to see if this is a problem for us. Datasheet pg. 6 says "The DS3231 is designed to operate in a synchronous mode, where the timekeeping registers are updated at the end of each second. This ensures that the timekeeping registers always contain valid data and eliminates the need for software to handle potential timing issues when reading or writing the registers."
|
||||
this->write_rtc_();
|
||||
}
|
||||
|
||||
|
||||
@ -77,30 +77,30 @@ void TLC59208FOutput::setup() {
|
||||
auto errcode = this->bus_->write_readv(TLC59208F_SWRST_ADDR >> 1, TLC59208F_SWRST_SEQ, sizeof TLC59208F_SWRST_SEQ, nullptr, 0);
|
||||
if (errcode != i2c::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "RESET failed");
|
||||
this->mark_failed("RESET failed");
|
||||
this->mark_failed(LOG_STR("RESET failed"));
|
||||
return;
|
||||
}
|
||||
// Auto increment registers, and respond to all-call address
|
||||
if (!this->write_byte(TLC59208F_REG_MODE1, TLC59208F_MODE1_AI2 | TLC59208F_MODE1_ALLCALL)) {
|
||||
ESP_LOGE(TAG, "MODE1 failed");
|
||||
this->mark_failed("MODE1 failed");
|
||||
this->mark_failed(LOG_STR("MODE1 failed"));
|
||||
return;
|
||||
}
|
||||
if (!this->write_byte(TLC59208F_REG_MODE2, this->mode_)) {
|
||||
ESP_LOGE(TAG, "MODE2 failed");
|
||||
this->mark_failed("MODE2 failed");
|
||||
this->mark_failed(LOG_STR("MODE2 failed"));
|
||||
return;
|
||||
}
|
||||
// Set all 3 outputs to be individually controlled
|
||||
// TODO: think of a way to support group dimming
|
||||
if (!this->write_byte(TLC59208F_REG_LEDOUT0, (LDR_PWM << 6) | (LDR_PWM << 4) | (LDR_PWM << 2) | (LDR_PWM << 0))) {
|
||||
ESP_LOGE(TAG, "LEDOUT0 failed");
|
||||
this->mark_failed("LEDOUT0 failed");
|
||||
this->mark_failed(LOG_STR("LEDOUT0 failed"));
|
||||
return;
|
||||
}
|
||||
if (!this->write_byte(TLC59208F_REG_LEDOUT1, (LDR_PWM << 6) | (LDR_PWM << 4) | (LDR_PWM << 2) | (LDR_PWM << 0))) {
|
||||
ESP_LOGE(TAG, "LEDOUT1 failed");
|
||||
this->mark_failed("LEDOUT1 failed");
|
||||
this->mark_failed(LOG_STR("LEDOUT1 failed"));
|
||||
return;
|
||||
}
|
||||
delayMicroseconds(500);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define __SOLAR_CB_FRAME
|
||||
#include "esphome.h"
|
||||
#include <utility>
|
||||
#include <queue>
|
||||
#include "common.h"
|
||||
using namespace esphome;
|
||||
|
||||
|
||||
@ -12,8 +12,8 @@ namespace solar
|
||||
#define SEARCHWILD 0x0100000 // do wildcard comparison (only searchkey should contain wildcards)
|
||||
#define num_compare(a, b) ((a) > (b)) ? +1 : ((a) < (b)) ? -1 : 0
|
||||
#define bool_compare(a, b) ((!(a) && !(b)) || ((a) && (b))) ? 0 : (a) ? +1 : -1
|
||||
#define max(a, b) ((a) > (b)) ? (a) : (b)
|
||||
#define min(a, b) ((a) < (b)) ? (a) : (b)
|
||||
#define mmax(a, b) ((a) > (b)) ? (a) : (b)
|
||||
#define mmin(a, b) ((a) < (b)) ? (a) : (b)
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef std::vector<uint8_t> byte_vector;
|
||||
|
||||
2103
sthome-ut10.yaml
2103
sthome-ut10.yaml
File diff suppressed because it is too large
Load Diff
742
sthome-ut2.yaml
742
sthome-ut2.yaml
@ -1,6 +1,8 @@
|
||||
packages:
|
||||
- !include common/wifi.yaml
|
||||
- !include common/felicityinverter.yaml
|
||||
- !include common/canbus.yaml
|
||||
- !include common/modbus.yaml
|
||||
|
||||
substitutions:
|
||||
name: sthome-ut2
|
||||
@ -9,13 +11,38 @@ substitutions:
|
||||
esphome:
|
||||
name: "${name}"
|
||||
friendly_name: "${friendly_name}"
|
||||
includes:
|
||||
- source # copies folder with files to relevant to be included in esphome compile
|
||||
- <source/solar/cb_frame.h> # angle brackets ensure file is included above globals in main.cpp. Make sure to use include GUARDS in the file to prevent double inclusion
|
||||
- <source/solar/cbf_store.h>
|
||||
- <source/solar/cbf_pylon.h>
|
||||
- <source/solar/cbf_store_pylon.h>
|
||||
- <source/solar/cbf_sthome.h>
|
||||
- <source/solar/cbf_store_sthome.h>
|
||||
- <source/solar/cbf_cache.h>
|
||||
|
||||
external_components:
|
||||
- source: github://pr#8103
|
||||
components: [uart]
|
||||
- source: github://pr#8032
|
||||
components: [modbus, modbus_controller, growatt_solar]
|
||||
refresh: 1h
|
||||
#external_components:
|
||||
# - source: github://pr#8103
|
||||
# components: [uart]
|
||||
# - source: github://pr#8032
|
||||
# components: [modbus, modbus_controller, growatt_solar]
|
||||
# refresh: 1h
|
||||
globals:
|
||||
- id: can_msgctr
|
||||
type: int
|
||||
restore_value: no
|
||||
- id: can2_msgctr
|
||||
type: int
|
||||
restore_value: no
|
||||
- id: last_battery_message_time
|
||||
type: time_t
|
||||
restore_value: no
|
||||
- id: g_cb_cache # the cache is used to only accept a frame after it has been received a specified number of times within a specified period. this hopefully will iron out spurious corrupted frames
|
||||
type: solar::cbf_cache
|
||||
restore_value: no
|
||||
- id: g_cb_request_queue
|
||||
type: std::queue< std::set<uint32_t> >
|
||||
restore_value: no
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
@ -27,9 +54,10 @@ logger:
|
||||
level: VERY_VERBOSE
|
||||
initial_level: INFO
|
||||
logs:
|
||||
uart: VERY_VERBOSE
|
||||
modbus: DEBUG
|
||||
modbus_controller: DEBUG
|
||||
canbus: INFO
|
||||
uart_debug: VERY_VERBOSE
|
||||
modbus: VERBOSE
|
||||
modbus_controller: VERBOSE
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
@ -51,18 +79,30 @@ wifi:
|
||||
|
||||
captive_portal:
|
||||
|
||||
spi:
|
||||
- id: spi_bus0
|
||||
clk_pin: GPIO18
|
||||
mosi_pin: GPIO23
|
||||
miso_pin: GPIO19
|
||||
interface: any
|
||||
|
||||
uart:
|
||||
- id: inv_uart1
|
||||
rx_pin: GPIO16
|
||||
tx_pin: GPIO17
|
||||
baud_rate: 2400
|
||||
- id: sth_uart
|
||||
rx_pin:
|
||||
number: GPIO17
|
||||
inverted: false
|
||||
mode:
|
||||
input: true
|
||||
pullup: true
|
||||
tx_pin: GPIO16
|
||||
baud_rate: 9600
|
||||
stop_bits: 1
|
||||
parity: NONE
|
||||
debug:
|
||||
direction: BOTH
|
||||
dummy_receiver: false
|
||||
after:
|
||||
delimiter: "\r"
|
||||
delimiter: "\n"
|
||||
sequence:
|
||||
- lambda: UARTDebug::log_hex(direction, bytes, ',');
|
||||
|
||||
@ -80,328 +120,404 @@ switch:
|
||||
name: "${name} Restart"
|
||||
id: "restart_switch"
|
||||
|
||||
interval:
|
||||
- interval: 10s
|
||||
then:
|
||||
- lambda: |-
|
||||
id(canbus_send_heartbeat).execute();
|
||||
# - interval: 2.36s
|
||||
# then:
|
||||
# - uart.write:
|
||||
# data: "sthome2 heartbeat\r\n"
|
||||
# - sth_uart.write: !lambda
|
||||
# return std::vector<uint8_t>({0x0D, 0x0A, 0x43, 0x50, 0x53, 0x00, 0x0D, 0x0A, 0x43, 0x50, 0x53, 0x00});
|
||||
|
||||
canbus:
|
||||
- platform: mcp2515
|
||||
cs_pin: GPIO32 # CBCS
|
||||
spi_id: spi_bus0
|
||||
id: canbus_sthome
|
||||
mode: NORMAL
|
||||
can_id: ${CB_CANBUS_ID03}
|
||||
bit_rate: 500KBPS
|
||||
on_frame:
|
||||
- can_id: 0
|
||||
can_id_mask: 0
|
||||
then:
|
||||
- lambda: |-
|
||||
id(can_msgctr)++;
|
||||
using namespace solar;
|
||||
auto time_obj = id(time_source).now();
|
||||
//ESP_LOGI("CB REC", "%s", id(time_source).now().strftime("%a %d %b %Y - %I:%M:%S %p"));
|
||||
if(time_obj.is_valid()) {
|
||||
if (can_id >= 0x380 && can_id < 0x3C0) {
|
||||
auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
bool publish = id(g_cb_cache).additem(cbitem);
|
||||
if(publish) {
|
||||
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
}
|
||||
} else {
|
||||
auto cbitem = cbf_store_sthome(id(can_msgctr), can_id, x, remote_transmission_request, time_obj.timestamp);
|
||||
ESP_LOGI(cbitem.tag().c_str(), "%s", cbitem.to_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
modbus:
|
||||
- id: modbus1
|
||||
uart_id: inv_uart1
|
||||
flow_control_pin: GPIO4
|
||||
send_wait_time: 1000ms #250ms
|
||||
- id: modbus_server
|
||||
uart_id: sth_uart
|
||||
send_wait_time: 1200ms #250ms
|
||||
disable_crc: false
|
||||
role: server
|
||||
|
||||
modbus_controller:
|
||||
- id: modbus_device1
|
||||
modbus_id: modbus1
|
||||
address: 0x1
|
||||
allow_duplicate_commands: False
|
||||
command_throttle: 0ms
|
||||
update_interval: 4s #30s
|
||||
offline_skip_updates: 2
|
||||
max_cmd_retries: 04
|
||||
setup_priority: -10
|
||||
- id: modbus_alarm_server
|
||||
modbus_id: modbus_server
|
||||
address: 0x01
|
||||
server_registers:
|
||||
- address: ${Felicity_Inv_WorkingMode} # 0x1101
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0001;
|
||||
- address: ${Felicity_Inv_BatteryChargingStage} # 0x1102
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0002;
|
||||
- address: ${Felicity_Inv_FaultCode} # 0x1103
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0003;
|
||||
- address: ${Felicity_Inv_PowerFlowMsg} # 0x1104
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x0004;
|
||||
- address: 0x1106
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: ${Felicity_Inv_BatteryVoltage} # 0x1108
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0005;
|
||||
- address: ${Felicity_Inv_BatteryCurrent} # 0x1109
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0006;
|
||||
- address: ${Felicity_Inv_BatteryPower} # 0x110A
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x0007;
|
||||
- address: 0x110C
|
||||
value_type: U_QWORD_R
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: 0x1110
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: ${Felicity_Inv_ACOutputVoltage} # 0x1111
|
||||
value_type: U_QWORD_R
|
||||
read_lambda: |-
|
||||
return 0x0008;
|
||||
- address: 0x1115
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: ${Felicity_Inv_ACInputVoltage} # 0x1117
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x0009;
|
||||
- address: ${Felicity_Inv_ACInputFrequency} # 0x1119
|
||||
value_type: U_QWORD_R
|
||||
read_lambda: |-
|
||||
return 0x000A;
|
||||
- address: 0x111D
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: ${Felicity_Inv_ACOutputActivePower} # 0x111E
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x000B;
|
||||
- address: ${Felicity_Inv_ACOutputApparentPower} # 0x111F
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x000C;
|
||||
- address: ${Felicity_Inv_LoadPercentage} # 0x1120
|
||||
value_type: U_QWORD_R
|
||||
read_lambda: |-
|
||||
return 0x000D;
|
||||
- address: 0x1124
|
||||
value_type: U_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
- address: ${Felicity_Inv_PVInputVoltage} # 0x1126
|
||||
value_type: U_QWORD_R
|
||||
read_lambda: |-
|
||||
return 0x000E;
|
||||
- address: ${Felicity_Inv_PVInputPower} # 0x112A
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0x0010;
|
||||
- address: 0x112C
|
||||
value_type: U_WORD
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
|
||||
- address: 0xF800
|
||||
- address: 0x0001
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x400D;
|
||||
- address: 0xF802
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x500E;
|
||||
- address: 0xF804
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x4142;
|
||||
- address: 0xF806
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x4344;
|
||||
- address: 0xF808
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x4546;
|
||||
- address: 0xF80A
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x4748;
|
||||
- address: 0xF80C
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x494A;
|
||||
- address: 0xF80E
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0x4B4C;
|
||||
- address: 0xF810
|
||||
value_type: S_DWORD_R
|
||||
read_lambda: |-
|
||||
return 0;
|
||||
uint16_t alarm_status = id(person_detected_switch).state ? 1 : 0;
|
||||
alarm_status |= id(alarm_zone4_relay).state ? 2 : 0;
|
||||
alarm_status |= id(lights_backyard_relay).state ? 4 : 0;
|
||||
alarm_status |= id(lights_frontyard_relay).state ? 8 : 0;
|
||||
alarm_status |= id(floodlight_test).state ? 16 : 0;
|
||||
alarm_status |= id(night_time).state ? 32 : 0;
|
||||
alarm_status |= id(zone1_triggered).state ? 64 : 0;
|
||||
alarm_status |= id(zone2_triggered).state ? 128 : 0;
|
||||
alarm_status |= id(zone3_triggered).state ? 256 : 0;
|
||||
alarm_status |= id(zone4_triggered).state ? 512 : 0;
|
||||
alarm_status |= id(zone5_triggered).state ? 1024 : 0;
|
||||
alarm_status |= id(zone6_triggered).state ? 2048 : 0;
|
||||
return alarm_status;
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
id: person_detected_switch
|
||||
name: "Person Detected Switch"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: alarm_zone4_relay
|
||||
name: "Alarm Zone 4 Relay"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: lights_backyard_relay
|
||||
name: "Lights Backyard Relay"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: lights_frontyard_relay
|
||||
name: "Lights Frontyard Relay"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: floodlight_test
|
||||
name: "Floodlight Test"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: night_time
|
||||
name: "Night Time"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone1_triggered
|
||||
name: "Zone 1 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone2_triggered
|
||||
name: "Zone 2 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone3_triggered
|
||||
name: "Zone 3 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone4_triggered
|
||||
name: "Zone 4 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone5_triggered
|
||||
name: "Zone 5 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
- platform: template
|
||||
id: zone6_triggered
|
||||
name: "Zone 6 Triggered"
|
||||
lambda: |-
|
||||
return true;
|
||||
|
||||
|
||||
#modbus:
|
||||
# - id: modbus1
|
||||
# uart_id: inv_uart1
|
||||
# flow_control_pin: GPIO4
|
||||
# send_wait_time: 1000ms #250ms
|
||||
# - id: modbus_client
|
||||
# uart_id: sth_uart
|
||||
# send_wait_time: 1200ms #250ms
|
||||
# disable_crc: false
|
||||
# role: client
|
||||
#
|
||||
#modbus_controller:
|
||||
# - id: modbus_device1
|
||||
# modbus_id: modbus1
|
||||
# - id: modbus_alarm_client
|
||||
# modbus_id: modbus_client
|
||||
# address: 0x01
|
||||
# allow_duplicate_commands: False
|
||||
# command_throttle: 0ms
|
||||
# update_interval: 4s #30s
|
||||
# command_throttle: 700ms #2022ms
|
||||
# update_interval: 10s #305s
|
||||
# offline_skip_updates: 2
|
||||
# max_cmd_retries: 0
|
||||
# max_cmd_retries: 1
|
||||
# setup_priority: -10
|
||||
#
|
||||
#binary_sensor:
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: person_detected
|
||||
# name: "Person Detected"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x1
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: alarm_zone4_relay
|
||||
# name: "Alarm Zone 4 Relay"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x2
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: lights_backyard_relay
|
||||
# name: "Lights Backyard Relay"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x4
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: lights_frontyard_relay
|
||||
# name: "Lights Frontyard Relay"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x8
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: floodlight_test
|
||||
# name: "Floodlight Test"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x10
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: night_time
|
||||
# name: "Night Time"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x20
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone1_triggered
|
||||
# name: "Zone 1 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x40
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone2_triggered
|
||||
# name: "Zone 2 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x80
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone3_triggered
|
||||
# name: "Zone 3 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x100
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone4_triggered
|
||||
# name: "Zone 4 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x200
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone5_triggered
|
||||
# name: "Zone 5 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x400
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: zone6_triggered
|
||||
# name: "Zone 6 Triggered"
|
||||
# register_type: read
|
||||
# address: 0x0001
|
||||
# bitmask: 0x800
|
||||
#
|
||||
#sensor:
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Type"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_Type} # 0xF800
|
||||
# value_type: U_DWORD
|
||||
# register_count: 1
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Sub Type"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_SubType} # 0xF801
|
||||
# value_type: U_DWORD
|
||||
# register_count: 3
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z1z4_current
|
||||
# name: "Z1Z4 Current"
|
||||
# address: 0x0002
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "mA"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 CPU1 F/W Version"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_CPU1_FW_Version} # 0xF80B
|
||||
# value_type: U_DWORD
|
||||
# register_count: 1
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z2z5_current
|
||||
# name: "Z2Z5 Current"
|
||||
# address: 0x0006
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "mA"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 CPU2 F/W Version"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_CPU2_FW_Version} # 0xF80C
|
||||
# value_type: U_DWORD
|
||||
# register_count: 3
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z3z6_current
|
||||
# name: "Z3Z6 Current"
|
||||
# address: 0x000A
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "mA"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Working Mode"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_WorkingMode} # 0x1101
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z1z4_bus_voltage
|
||||
# name: "Z1Z4 Bus Voltage"
|
||||
# address: 0x000E
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Charge Mode"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_BatteryChargingStage} # 0x1102
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z2z5_bus_voltage
|
||||
# name: "Z2Z5 Bus Voltage"
|
||||
# address: 0x0012
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Fault Code"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_FaultCode} # 0x1103
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z3z6_bus_voltage
|
||||
# name: "Z3Z6 Bus Voltage"
|
||||
# address: 0x0016
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Power Flow"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_PowerFlowMsg} # 0x1104
|
||||
# value_type: U_WORD
|
||||
# register_count: 4
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z1z4_power
|
||||
# name: "Z1Z4 Power"
|
||||
# address: 0x001A
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "W"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Battery Voltage"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_BatteryVoltage} # 0x1108
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Battery Current"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_BatteryCurrent} # 0x1109
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 BatteryPower"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_BatteryPower} # 0x110A
|
||||
# value_type: U_WORD
|
||||
# register_count: 7
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 AC Output Voltage"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_ACOutputVoltage} # 0x1111
|
||||
# value_type: U_WORD
|
||||
# register_count: 6
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 AC Input Voltage"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_ACInputVoltage} # 0x1117
|
||||
# value_type: U_WORD
|
||||
# register_count: 2
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 AC Input Frequency"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_ACInputFrequency} # 0x1119
|
||||
# value_type: U_WORD
|
||||
# register_count: 5
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 AC Output Active Power"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_ACOutputActivePower} # 0x111E
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 AC Output Apparent Power"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_ACOutputApparentPower} # 0x111F
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 Load Percentage"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_LoadPercentage} # 0x1120
|
||||
# value_type: U_WORD
|
||||
# register_count: 6
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 PV Input Voltage"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_PVInputVoltage} # 0x1126
|
||||
# value_type: U_WORD
|
||||
# register_count: 4
|
||||
#
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 PV Input Power"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_PVInputPower} # 0x112A
|
||||
# value_type: U_WORD
|
||||
# register_count: 1
|
||||
#
|
||||
#text_sensor:
|
||||
#- platform: modbus_controller
|
||||
# modbus_controller_id: modbus_device1
|
||||
# name: "Inverter1 SerialNo"
|
||||
# register_type: holding
|
||||
# address: ${Felicity_Inv_SerialNo} # 0xF804
|
||||
# response_size: 14
|
||||
# register_count: 7
|
||||
# raw_encode: HEXBYTES
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z2z5_power
|
||||
# name: "Z2Z5 Power"
|
||||
# address: 0x001E
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "W"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z3z6_power
|
||||
# name: "Z3Z6 Power"
|
||||
# address: 0x0022
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "W"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z1z4_shunt_voltage
|
||||
# name: "Z1Z4 Shunt Voltage"
|
||||
# address: 0x0026
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z2z5_shunt_voltage
|
||||
# name: "Z2Z5 Shunt Voltage"
|
||||
# address: 0x002A
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: z3z6_shunt_voltage
|
||||
# name: "Z3Z6 Shunt Voltage"
|
||||
# address: 0x002E
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
#
|
||||
# - platform: modbus_controller
|
||||
# modbus_controller_id: modbus_alarm_client
|
||||
# id: alarm_signal
|
||||
# name: "Alarm Signal"
|
||||
# address: 0x0032
|
||||
# register_type: holding
|
||||
# value_type: S_WORD
|
||||
# register_count: 4
|
||||
# unit_of_measurement: "V"
|
||||
# lambda: |-
|
||||
# return x / 1024.0;
|
||||
|
||||
script:
|
||||
- id: canbus_send_heartbeat
|
||||
then:
|
||||
lambda: |-
|
||||
using namespace solar;
|
||||
std::vector<uint8_t> x(cbf_sthome::heartbeat.begin(), cbf_sthome::heartbeat.end());
|
||||
id(g_cb_cache).send_frame(id(canbus_sthome), cbf_sthome::CB_CANBUS_ID02, x);
|
||||
960
sthome-ut3.yaml
960
sthome-ut3.yaml
File diff suppressed because it is too large
Load Diff
140
sthome-ut9.yaml
140
sthome-ut9.yaml
@ -47,6 +47,30 @@ wifi:
|
||||
|
||||
captive_portal:
|
||||
|
||||
uart:
|
||||
- id: sth_uart
|
||||
rx_pin: GPIO15
|
||||
tx_pin: GPIO16
|
||||
baud_rate: 2400
|
||||
stop_bits: 1
|
||||
parity: NONE
|
||||
debug:
|
||||
direction: BOTH
|
||||
dummy_receiver: true
|
||||
after:
|
||||
delimiter: "\r"
|
||||
sequence:
|
||||
- lambda: UARTDebug::log_hex(direction, bytes, ',');
|
||||
|
||||
interval:
|
||||
# - interval: 10s
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# id(canbus_send_heartbeat).execute();
|
||||
- interval: 3.14s
|
||||
then:
|
||||
- uart.write:
|
||||
data: "sthome9 heartbeat\r\n"
|
||||
|
||||
sun:
|
||||
id: sun_sensor
|
||||
@ -69,126 +93,12 @@ text_sensor:
|
||||
id: uptime_human
|
||||
icon: mdi:clock-start
|
||||
|
||||
|
||||
#define OUTPUT_R1 16
|
||||
#define OUTPUT_R2 17
|
||||
#define OUTPUT_R3 18
|
||||
#define OUTPUT_R4 19
|
||||
switch:
|
||||
- platform: restart
|
||||
name: "${name} Restart"
|
||||
id: "restart_switch"
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO16
|
||||
inverted: true
|
||||
id: relay1
|
||||
name: "Floodlights Backyard"
|
||||
icon: "mdi:light-flood-down"
|
||||
restore_mode: RESTORE_DEFAULT_OFF
|
||||
# the backyard floodlight auto turns off in 4min 14 sec. So we need to switch relay off just before or at this time
|
||||
# TODO: remove or extend auto turn off to >= 10min
|
||||
on_turn_on:
|
||||
- delay: 250s
|
||||
- switch.turn_off: relay1
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO17
|
||||
inverted: true
|
||||
id: relay2
|
||||
name: "Relay 2"
|
||||
icon: "mdi:run-fast"
|
||||
restore_mode: RESTORE_DEFAULT_OFF
|
||||
on_turn_on:
|
||||
- delay: 1000ms
|
||||
- switch.turn_off: relay2
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO18
|
||||
inverted: true
|
||||
id: relay3
|
||||
name: "Relay 3"
|
||||
icon: "mdi:run-fast"
|
||||
restore_mode: RESTORE_DEFAULT_OFF
|
||||
on_turn_on:
|
||||
- delay: 1000ms
|
||||
- switch.turn_off: relay3
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO19
|
||||
inverted: true
|
||||
id: relay4
|
||||
name: "Alarm Zone 4"
|
||||
icon: "mdi:alarm-light-outline"
|
||||
restore_mode: RESTORE_DEFAULT_OFF
|
||||
on_turn_on:
|
||||
- if:
|
||||
condition:
|
||||
- lambda: |-
|
||||
double sun_elevation = id(sun_sensor).elevation();
|
||||
return (sun_elevation <= -6); // -6° = civil twilight, -12° = nautical twilight, -18° = astronomical twilight
|
||||
#- sun.is_below_horizon:
|
||||
then:
|
||||
- switch.turn_on: relay1
|
||||
- if:
|
||||
condition:
|
||||
- binary_sensor.is_on: floodlight_test
|
||||
then:
|
||||
- switch.turn_on: relay1
|
||||
- delay: 30s
|
||||
- switch.turn_off: relay4
|
||||
|
||||
|
||||
# define DIGITAL_D1 04
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
# device_class: light
|
||||
id: floodlight_test
|
||||
pin:
|
||||
number: GPIO04
|
||||
mode:
|
||||
input: true
|
||||
pullup: true
|
||||
filters:
|
||||
- delayed_off: 100ms
|
||||
name: "Floodlights Test Mode"
|
||||
icon: "mdi:lightbulb-on-outline"
|
||||
|
||||
#define ANALOG_A1 33
|
||||
#define ANALOG_A2 32
|
||||
#define ANALOG_A3 35
|
||||
#define ANALOG_A4 34
|
||||
#define ANALOG_A5 39
|
||||
#define ANALOG_A6 36
|
||||
sensor:
|
||||
# - platform: adc
|
||||
# pin: 35
|
||||
# name: "Alarm Signal"
|
||||
# id: alarm_signal
|
||||
# update_interval: 2000ms
|
||||
# attenuation: 12db
|
||||
# sampling_mode: avg
|
||||
# filters:
|
||||
# - lambda:
|
||||
# if (x >= 3.11) {
|
||||
# return x * 1.60256;
|
||||
# } else if (x <= 0.25) {
|
||||
# return 0;
|
||||
# } else {
|
||||
# return x * 1.51;
|
||||
# }
|
||||
# on_value:
|
||||
# then:
|
||||
# # switch on floodlights
|
||||
# lambda: |-
|
||||
# if (id(alarm_signal).state > 1.5) {
|
||||
# id(relay1).turn_on();
|
||||
# }
|
||||
|
||||
sensor:
|
||||
# human readable uptime sensor output to the text sensor above
|
||||
- platform: uptime
|
||||
name: Uptime in Days
|
||||
|
||||
Loading…
Reference in New Issue
Block a user