mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 06:58:11 +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_i2c/* @angelnu
|
||||
esphome/components/ade7953_spi/* @angelnu
|
||||
esphome/components/ads1118/* @solomondg1
|
||||
esphome/components/ags10/* @mak-42
|
||||
esphome/components/airthings_ble/* @jeromelaban
|
||||
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
|
||||
i2c_id: i2c_bus
|
||||
|
||||
ads1118:
|
||||
spi_id: spi_bus
|
||||
cs_pin:
|
||||
allow_other_uses: true
|
||||
number: GPIO12
|
||||
|
||||
as5600:
|
||||
i2c_id: i2c_bus
|
||||
dir_pin:
|
||||
|
@ -571,6 +577,14 @@ sensor:
|
|||
state_topic: hi/me
|
||||
retain: false
|
||||
availability:
|
||||
- platform: ads1118
|
||||
name: ads1118 adc
|
||||
multiplexer: A0_A1
|
||||
gain: 1.024
|
||||
type: adc
|
||||
- platform: ads1118
|
||||
name: ads1118 temperature
|
||||
type: temperature
|
||||
- platform: as5600
|
||||
name: AS5600 Position
|
||||
raw_position:
|
||||
|
|
Loading…
Reference in a new issue