mirror of
https://github.com/esphome/esphome.git
synced 2024-11-12 18:27:46 +01:00
ads1118 component (#5711)
Co-authored-by: Solomon <solomon.gorkhover@finnpartners.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
89b3bc7d70
commit
c52052563f
8 changed files with 374 additions and 0 deletions
|
@ -22,6 +22,7 @@ esphome/components/ade7880/* @kpfleming
|
||||||
esphome/components/ade7953/* @angelnu
|
esphome/components/ade7953/* @angelnu
|
||||||
esphome/components/ade7953_i2c/* @angelnu
|
esphome/components/ade7953_i2c/* @angelnu
|
||||||
esphome/components/ade7953_spi/* @angelnu
|
esphome/components/ade7953_spi/* @angelnu
|
||||||
|
esphome/components/ads1118/* @solomondg1
|
||||||
esphome/components/ags10/* @mak-42
|
esphome/components/ags10/* @mak-42
|
||||||
esphome/components/airthings_ble/* @jeromelaban
|
esphome/components/airthings_ble/* @jeromelaban
|
||||||
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
|
esphome/components/airthings_wave_base/* @jeromelaban @kpfleming @ncareau
|
||||||
|
|
25
esphome/components/ads1118/__init__.py
Normal file
25
esphome/components/ads1118/__init__.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import spi
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
CODEOWNERS = ["@solomondg1"]
|
||||||
|
DEPENDENCIES = ["spi"]
|
||||||
|
MULTI_CONF = True
|
||||||
|
|
||||||
|
CONF_ADS1118_ID = "ads1118_id"
|
||||||
|
|
||||||
|
ads1118_ns = cg.esphome_ns.namespace("ads1118")
|
||||||
|
ADS1118 = ads1118_ns.class_("ADS1118", cg.Component, spi.SPIDevice)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(ADS1118),
|
||||||
|
}
|
||||||
|
).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)
|
126
esphome/components/ads1118/ads1118.cpp
Normal file
126
esphome/components/ads1118/ads1118.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include "ads1118.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ads1118 {
|
||||||
|
|
||||||
|
static const char *const TAG = "ads1118";
|
||||||
|
static const uint8_t ADS1118_DATA_RATE_860_SPS = 0b111;
|
||||||
|
|
||||||
|
void ADS1118::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up ads1118");
|
||||||
|
this->spi_setup();
|
||||||
|
|
||||||
|
this->config_ = 0;
|
||||||
|
// Setup multiplexer
|
||||||
|
// 0bx000xxxxxxxxxxxx
|
||||||
|
this->config_ |= ADS1118_MULTIPLEXER_P0_NG << 12;
|
||||||
|
|
||||||
|
// Setup Gain
|
||||||
|
// 0bxxxx000xxxxxxxxx
|
||||||
|
this->config_ |= ADS1118_GAIN_6P144 << 9;
|
||||||
|
|
||||||
|
// Set singleshot mode
|
||||||
|
// 0bxxxxxxx1xxxxxxxx
|
||||||
|
this->config_ |= 0b0000000100000000;
|
||||||
|
|
||||||
|
// Set data rate - 860 samples per second (we're in singleshot mode)
|
||||||
|
// 0bxxxxxxxx100xxxxx
|
||||||
|
this->config_ |= ADS1118_DATA_RATE_860_SPS << 5;
|
||||||
|
|
||||||
|
// Set temperature sensor mode - ADC
|
||||||
|
// 0bxxxxxxxxxxx0xxxx
|
||||||
|
this->config_ |= 0b0000000000000000;
|
||||||
|
|
||||||
|
// Set DOUT pull up - enable
|
||||||
|
// 0bxxxxxxxxxxxx0xxx
|
||||||
|
this->config_ |= 0b0000000000001000;
|
||||||
|
|
||||||
|
// NOP - must be 01
|
||||||
|
// 0bxxxxxxxxxxxxx01x
|
||||||
|
this->config_ |= 0b0000000000000010;
|
||||||
|
|
||||||
|
// Not used - can be 0 or 1, lets be positive
|
||||||
|
// 0bxxxxxxxxxxxxxxx1
|
||||||
|
this->config_ |= 0b0000000000000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADS1118::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "ADS1118:");
|
||||||
|
LOG_PIN(" CS Pin:", this->cs_);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ADS1118::request_measurement(ADS1118Multiplexer multiplexer, ADS1118Gain gain, bool temperature_mode) {
|
||||||
|
uint16_t temp_config = this->config_;
|
||||||
|
// Multiplexer
|
||||||
|
// 0bxBBBxxxxxxxxxxxx
|
||||||
|
temp_config &= 0b1000111111111111;
|
||||||
|
temp_config |= (multiplexer & 0b111) << 12;
|
||||||
|
|
||||||
|
// Gain
|
||||||
|
// 0bxxxxBBBxxxxxxxxx
|
||||||
|
temp_config &= 0b1111000111111111;
|
||||||
|
temp_config |= (gain & 0b111) << 9;
|
||||||
|
|
||||||
|
if (temperature_mode) {
|
||||||
|
// Set temperature sensor mode
|
||||||
|
// 0bxxxxxxxxxxx1xxxx
|
||||||
|
temp_config |= 0b0000000000010000;
|
||||||
|
} else {
|
||||||
|
// Set ADC mode
|
||||||
|
// 0bxxxxxxxxxxx0xxxx
|
||||||
|
temp_config &= 0b1111111111101111;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start conversion
|
||||||
|
temp_config |= 0b1000000000000000;
|
||||||
|
|
||||||
|
this->enable();
|
||||||
|
this->write_byte16(temp_config);
|
||||||
|
this->disable();
|
||||||
|
|
||||||
|
// about 1.2 ms with 860 samples per second
|
||||||
|
delay(2);
|
||||||
|
|
||||||
|
this->enable();
|
||||||
|
uint8_t adc_first_byte = this->read_byte();
|
||||||
|
uint8_t adc_second_byte = this->read_byte();
|
||||||
|
this->disable();
|
||||||
|
uint16_t raw_conversion = encode_uint16(adc_first_byte, adc_second_byte);
|
||||||
|
|
||||||
|
auto signed_conversion = static_cast<int16_t>(raw_conversion);
|
||||||
|
|
||||||
|
if (temperature_mode) {
|
||||||
|
return (signed_conversion >> 2) * 0.03125f;
|
||||||
|
} else {
|
||||||
|
float millivolts;
|
||||||
|
float divider = 32768.0f;
|
||||||
|
switch (gain) {
|
||||||
|
case ADS1118_GAIN_6P144:
|
||||||
|
millivolts = (signed_conversion * 6144) / divider;
|
||||||
|
break;
|
||||||
|
case ADS1118_GAIN_4P096:
|
||||||
|
millivolts = (signed_conversion * 4096) / divider;
|
||||||
|
break;
|
||||||
|
case ADS1118_GAIN_2P048:
|
||||||
|
millivolts = (signed_conversion * 2048) / divider;
|
||||||
|
break;
|
||||||
|
case ADS1118_GAIN_1P024:
|
||||||
|
millivolts = (signed_conversion * 1024) / divider;
|
||||||
|
break;
|
||||||
|
case ADS1118_GAIN_0P512:
|
||||||
|
millivolts = (signed_conversion * 512) / divider;
|
||||||
|
break;
|
||||||
|
case ADS1118_GAIN_0P256:
|
||||||
|
millivolts = (signed_conversion * 256) / divider;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
millivolts = NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return millivolts / 1e3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ads1118
|
||||||
|
} // namespace esphome
|
46
esphome/components/ads1118/ads1118.h
Normal file
46
esphome/components/ads1118/ads1118.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/components/spi/spi.h"
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ads1118 {
|
||||||
|
|
||||||
|
enum ADS1118Multiplexer {
|
||||||
|
ADS1118_MULTIPLEXER_P0_N1 = 0b000,
|
||||||
|
ADS1118_MULTIPLEXER_P0_N3 = 0b001,
|
||||||
|
ADS1118_MULTIPLEXER_P1_N3 = 0b010,
|
||||||
|
ADS1118_MULTIPLEXER_P2_N3 = 0b011,
|
||||||
|
ADS1118_MULTIPLEXER_P0_NG = 0b100,
|
||||||
|
ADS1118_MULTIPLEXER_P1_NG = 0b101,
|
||||||
|
ADS1118_MULTIPLEXER_P2_NG = 0b110,
|
||||||
|
ADS1118_MULTIPLEXER_P3_NG = 0b111,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ADS1118Gain {
|
||||||
|
ADS1118_GAIN_6P144 = 0b000,
|
||||||
|
ADS1118_GAIN_4P096 = 0b001,
|
||||||
|
ADS1118_GAIN_2P048 = 0b010,
|
||||||
|
ADS1118_GAIN_1P024 = 0b011,
|
||||||
|
ADS1118_GAIN_0P512 = 0b100,
|
||||||
|
ADS1118_GAIN_0P256 = 0b101,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ADS1118 : public Component,
|
||||||
|
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING,
|
||||||
|
spi::DATA_RATE_1MHZ> {
|
||||||
|
public:
|
||||||
|
ADS1118() = default;
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
/// Helper method to request a measurement from a sensor.
|
||||||
|
float request_measurement(ADS1118Multiplexer multiplexer, ADS1118Gain gain, bool temperature_mode);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t config_{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ads1118
|
||||||
|
} // namespace esphome
|
97
esphome/components/ads1118/sensor/__init__.py
Normal file
97
esphome/components/ads1118/sensor/__init__.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor, voltage_sampler
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_GAIN,
|
||||||
|
CONF_MULTIPLEXER,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
UNIT_VOLT,
|
||||||
|
CONF_TYPE,
|
||||||
|
)
|
||||||
|
from .. import ads1118_ns, ADS1118, CONF_ADS1118_ID
|
||||||
|
|
||||||
|
AUTO_LOAD = ["voltage_sampler"]
|
||||||
|
DEPENDENCIES = ["ads1118"]
|
||||||
|
|
||||||
|
ADS1118Multiplexer = ads1118_ns.enum("ADS1118Multiplexer")
|
||||||
|
MUX = {
|
||||||
|
"A0_A1": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P0_N1,
|
||||||
|
"A0_A3": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P0_N3,
|
||||||
|
"A1_A3": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P1_N3,
|
||||||
|
"A2_A3": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P2_N3,
|
||||||
|
"A0_GND": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P0_NG,
|
||||||
|
"A1_GND": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P1_NG,
|
||||||
|
"A2_GND": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P2_NG,
|
||||||
|
"A3_GND": ADS1118Multiplexer.ADS1118_MULTIPLEXER_P3_NG,
|
||||||
|
}
|
||||||
|
|
||||||
|
ADS1118Gain = ads1118_ns.enum("ADS1118Gain")
|
||||||
|
GAIN = {
|
||||||
|
"6.144": ADS1118Gain.ADS1118_GAIN_6P144,
|
||||||
|
"4.096": ADS1118Gain.ADS1118_GAIN_4P096,
|
||||||
|
"2.048": ADS1118Gain.ADS1118_GAIN_2P048,
|
||||||
|
"1.024": ADS1118Gain.ADS1118_GAIN_1P024,
|
||||||
|
"0.512": ADS1118Gain.ADS1118_GAIN_0P512,
|
||||||
|
"0.256": ADS1118Gain.ADS1118_GAIN_0P256,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ADS1118Sensor = ads1118_ns.class_(
|
||||||
|
"ADS1118Sensor",
|
||||||
|
cg.PollingComponent,
|
||||||
|
sensor.Sensor,
|
||||||
|
voltage_sampler.VoltageSampler,
|
||||||
|
cg.Parented.template(ADS1118),
|
||||||
|
)
|
||||||
|
|
||||||
|
TYPE_ADC = "adc"
|
||||||
|
TYPE_TEMPERATURE = "temperature"
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.typed_schema(
|
||||||
|
{
|
||||||
|
TYPE_ADC: sensor.sensor_schema(
|
||||||
|
ADS1118Sensor,
|
||||||
|
unit_of_measurement=UNIT_VOLT,
|
||||||
|
accuracy_decimals=3,
|
||||||
|
device_class=DEVICE_CLASS_VOLTAGE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_ADS1118_ID): cv.use_id(ADS1118),
|
||||||
|
cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"),
|
||||||
|
cv.Required(CONF_GAIN): cv.enum(GAIN, string=True),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s")),
|
||||||
|
TYPE_TEMPERATURE: sensor.sensor_schema(
|
||||||
|
ADS1118Sensor,
|
||||||
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
|
accuracy_decimals=2,
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_ADS1118_ID): cv.use_id(ADS1118),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s")),
|
||||||
|
},
|
||||||
|
default_type=TYPE_ADC,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = await sensor.new_sensor(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await cg.register_parented(var, config[CONF_ADS1118_ID])
|
||||||
|
|
||||||
|
if config[CONF_TYPE] == TYPE_ADC:
|
||||||
|
cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER]))
|
||||||
|
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||||
|
if config[CONF_TYPE] == TYPE_TEMPERATURE:
|
||||||
|
cg.add(var.set_temperature_mode(True))
|
29
esphome/components/ads1118/sensor/ads1118_sensor.cpp
Normal file
29
esphome/components/ads1118/sensor/ads1118_sensor.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "ads1118_sensor.h"
|
||||||
|
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ads1118 {
|
||||||
|
|
||||||
|
static const char *const TAG = "ads1118.sensor";
|
||||||
|
|
||||||
|
void ADS1118Sensor::dump_config() {
|
||||||
|
LOG_SENSOR(" ", "ADS1118 Sensor", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ADS1118Sensor::sample() {
|
||||||
|
return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->temperature_mode_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADS1118Sensor::update() {
|
||||||
|
float v = this->sample();
|
||||||
|
if (!std::isnan(v)) {
|
||||||
|
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
|
||||||
|
this->publish_state(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ads1118
|
||||||
|
} // namespace esphome
|
36
esphome/components/ads1118/sensor/ads1118_sensor.h
Normal file
36
esphome/components/ads1118/sensor/ads1118_sensor.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
|
|
||||||
|
#include "../ads1118.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ads1118 {
|
||||||
|
|
||||||
|
class ADS1118Sensor : public PollingComponent,
|
||||||
|
public sensor::Sensor,
|
||||||
|
public voltage_sampler::VoltageSampler,
|
||||||
|
public Parented<ADS1118> {
|
||||||
|
public:
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
void set_multiplexer(ADS1118Multiplexer multiplexer) { this->multiplexer_ = multiplexer; }
|
||||||
|
void set_gain(ADS1118Gain gain) { this->gain_ = gain; }
|
||||||
|
void set_temperature_mode(bool temp) { this->temperature_mode_ = temp; }
|
||||||
|
|
||||||
|
float sample() override;
|
||||||
|
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ADS1118Multiplexer multiplexer_{ADS1118_MULTIPLEXER_P0_NG};
|
||||||
|
ADS1118Gain gain_{ADS1118_GAIN_6P144};
|
||||||
|
bool temperature_mode_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ads1118
|
||||||
|
} // namespace esphome
|
|
@ -322,6 +322,12 @@ ads1115:
|
||||||
address: 0x48
|
address: 0x48
|
||||||
i2c_id: i2c_bus
|
i2c_id: i2c_bus
|
||||||
|
|
||||||
|
ads1118:
|
||||||
|
spi_id: spi_bus
|
||||||
|
cs_pin:
|
||||||
|
allow_other_uses: true
|
||||||
|
number: GPIO12
|
||||||
|
|
||||||
as5600:
|
as5600:
|
||||||
i2c_id: i2c_bus
|
i2c_id: i2c_bus
|
||||||
dir_pin:
|
dir_pin:
|
||||||
|
@ -571,6 +577,14 @@ sensor:
|
||||||
state_topic: hi/me
|
state_topic: hi/me
|
||||||
retain: false
|
retain: false
|
||||||
availability:
|
availability:
|
||||||
|
- platform: ads1118
|
||||||
|
name: ads1118 adc
|
||||||
|
multiplexer: A0_A1
|
||||||
|
gain: 1.024
|
||||||
|
type: adc
|
||||||
|
- platform: ads1118
|
||||||
|
name: ads1118 temperature
|
||||||
|
type: temperature
|
||||||
- platform: as5600
|
- platform: as5600
|
||||||
name: AS5600 Position
|
name: AS5600 Position
|
||||||
raw_position:
|
raw_position:
|
||||||
|
|
Loading…
Reference in a new issue