From 8aeb08f8689a5d746c6ef0d36f4d3f958edd2ac3 Mon Sep 17 00:00:00 2001 From: brambo123 <52667932+brambo123@users.noreply.github.com> Date: Thu, 23 Jan 2025 00:31:07 +0100 Subject: [PATCH] [ads1115] Add sample rate control (#8102) --- esphome/components/ads1115/ads1115.cpp | 63 ++++++++++++++++--- esphome/components/ads1115/ads1115.h | 14 ++++- esphome/components/ads1115/sensor/__init__.py | 16 +++++ .../ads1115/sensor/ads1115_sensor.cpp | 3 +- .../ads1115/sensor/ads1115_sensor.h | 2 + tests/components/ads1115/test.esp32-ard.yaml | 1 + .../components/ads1115/test.esp32-c3-ard.yaml | 1 + .../components/ads1115/test.esp32-c3-idf.yaml | 1 + tests/components/ads1115/test.esp32-idf.yaml | 1 + .../components/ads1115/test.esp8266-ard.yaml | 1 + tests/components/ads1115/test.rp2040-ard.yaml | 1 + 11 files changed, 95 insertions(+), 9 deletions(-) diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index 218edc4c81..c05064383c 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -9,8 +9,6 @@ static const char *const TAG = "ads1115"; static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00; static const uint8_t ADS1115_REGISTER_CONFIG = 0x01; -static const uint8_t ADS1115_DATA_RATE_860_SPS = 0b111; // 3300_SPS for ADS1015 - void ADS1115Component::setup() { ESP_LOGCONFIG(TAG, "Setting up ADS1115..."); uint16_t value; @@ -43,9 +41,9 @@ void ADS1115Component::setup() { config |= 0b0000000100000000; } - // Set data rate - 860 samples per second (we're in singleshot mode) + // Set data rate - 860 samples per second // 0bxxxxxxxx100xxxxx - config |= ADS1115_DATA_RATE_860_SPS << 5; + config |= ADS1115_860SPS << 5; // Set comparator mode - hysteresis // 0bxxxxxxxxxxx0xxxx @@ -77,7 +75,7 @@ void ADS1115Component::dump_config() { } } float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, - ADS1115Resolution resolution) { + ADS1115Resolution resolution, ADS1115Samplerate samplerate) { uint16_t config = this->prev_config_; // Multiplexer // 0bxBBBxxxxxxxxxxxx @@ -89,6 +87,11 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1 config &= 0b1111000111111111; config |= (gain & 0b111) << 9; + // Sample rate + // 0bxxxxxxxxBBBxxxxx + config &= 0b1111111100011111; + config |= (samplerate & 0b111) << 5; + if (!this->continuous_mode_) { // Start conversion config |= 0b1000000000000000; @@ -101,8 +104,54 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1 } this->prev_config_ = config; - // about 1.2 ms with 860 samples per second - delay(2); + // Delay calculated as: ceil((1000/SPS)+.5) + if (resolution == ADS1015_12_BITS) { + switch (samplerate) { + case ADS1115_8SPS: + delay(9); + break; + case ADS1115_16SPS: + delay(5); + break; + case ADS1115_32SPS: + delay(3); + break; + case ADS1115_64SPS: + case ADS1115_128SPS: + delay(2); + break; + default: + delay(1); + break; + } + } else { + switch (samplerate) { + case ADS1115_8SPS: + delay(126); // NOLINT + break; + case ADS1115_16SPS: + delay(63); // NOLINT + break; + case ADS1115_32SPS: + delay(32); + break; + case ADS1115_64SPS: + delay(17); + break; + case ADS1115_128SPS: + delay(9); + break; + case ADS1115_250SPS: + delay(5); + break; + case ADS1115_475SPS: + delay(3); + break; + case ADS1115_860SPS: + delay(2); + break; + } + } // in continuous mode, conversion will always be running, rely on the delay // to ensure conversion is taking place with the correct settings diff --git a/esphome/components/ads1115/ads1115.h b/esphome/components/ads1115/ads1115.h index 509333d2c8..e65835a386 100644 --- a/esphome/components/ads1115/ads1115.h +++ b/esphome/components/ads1115/ads1115.h @@ -33,6 +33,17 @@ enum ADS1115Resolution { ADS1015_12_BITS = 12, }; +enum ADS1115Samplerate { + ADS1115_8SPS = 0b000, + ADS1115_16SPS = 0b001, + ADS1115_32SPS = 0b010, + ADS1115_64SPS = 0b011, + ADS1115_128SPS = 0b100, + ADS1115_250SPS = 0b101, + ADS1115_475SPS = 0b110, + ADS1115_860SPS = 0b111 +}; + class ADS1115Component : public Component, public i2c::I2CDevice { public: void setup() override; @@ -42,7 +53,8 @@ class ADS1115Component : public Component, public i2c::I2CDevice { void set_continuous_mode(bool continuous_mode) { continuous_mode_ = continuous_mode; } /// Helper method to request a measurement from a sensor. - float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution); + float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, + ADS1115Samplerate samplerate); protected: uint16_t prev_config_{0}; diff --git a/esphome/components/ads1115/sensor/__init__.py b/esphome/components/ads1115/sensor/__init__.py index baec31d35c..f346a71198 100644 --- a/esphome/components/ads1115/sensor/__init__.py +++ b/esphome/components/ads1115/sensor/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_GAIN, CONF_MULTIPLEXER, CONF_RESOLUTION, + CONF_SAMPLE_RATE, DEVICE_CLASS_VOLTAGE, STATE_CLASS_MEASUREMENT, UNIT_VOLT, @@ -43,6 +44,17 @@ RESOLUTION = { "12_BITS": ADS1115Resolution.ADS1015_12_BITS, } +ADS1115Samplerate = ads1115_ns.enum("ADS1115Samplerate") +SAMPLERATE = { + "8": ADS1115Samplerate.ADS1115_8SPS, + "16": ADS1115Samplerate.ADS1115_16SPS, + "32": ADS1115Samplerate.ADS1115_32SPS, + "64": ADS1115Samplerate.ADS1115_64SPS, + "128": ADS1115Samplerate.ADS1115_128SPS, + "250": ADS1115Samplerate.ADS1115_250SPS, + "475": ADS1115Samplerate.ADS1115_475SPS, + "860": ADS1115Samplerate.ADS1115_860SPS, +} ADS1115Sensor = ads1115_ns.class_( "ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler @@ -64,6 +76,9 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_RESOLUTION, default="16_BITS"): cv.enum( RESOLUTION, upper=True, space="_" ), + cv.Optional(CONF_SAMPLE_RATE, default="860"): cv.enum( + SAMPLERATE, string=True + ), } ) .extend(cv.polling_component_schema("60s")) @@ -79,3 +94,4 @@ async def to_code(config): cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) cg.add(var.set_gain(config[CONF_GAIN])) cg.add(var.set_resolution(config[CONF_RESOLUTION])) + cg.add(var.set_samplerate(config[CONF_SAMPLE_RATE])) diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.cpp b/esphome/components/ads1115/sensor/ads1115_sensor.cpp index 335fca4845..6de95f1d12 100644 --- a/esphome/components/ads1115/sensor/ads1115_sensor.cpp +++ b/esphome/components/ads1115/sensor/ads1115_sensor.cpp @@ -8,7 +8,7 @@ namespace ads1115 { static const char *const TAG = "ads1115.sensor"; float ADS1115Sensor::sample() { - return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_); + return this->parent_->request_measurement(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_); } void ADS1115Sensor::update() { @@ -24,6 +24,7 @@ void ADS1115Sensor::dump_config() { ESP_LOGCONFIG(TAG, " Multiplexer: %u", this->multiplexer_); ESP_LOGCONFIG(TAG, " Gain: %u", this->gain_); ESP_LOGCONFIG(TAG, " Resolution: %u", this->resolution_); + ESP_LOGCONFIG(TAG, " Sample rate: %u", this->samplerate_); } } // namespace ads1115 diff --git a/esphome/components/ads1115/sensor/ads1115_sensor.h b/esphome/components/ads1115/sensor/ads1115_sensor.h index 191afc3de6..5ca25c13ad 100644 --- a/esphome/components/ads1115/sensor/ads1115_sensor.h +++ b/esphome/components/ads1115/sensor/ads1115_sensor.h @@ -21,6 +21,7 @@ class ADS1115Sensor : public sensor::Sensor, void set_multiplexer(ADS1115Multiplexer multiplexer) { this->multiplexer_ = multiplexer; } void set_gain(ADS1115Gain gain) { this->gain_ = gain; } void set_resolution(ADS1115Resolution resolution) { this->resolution_ = resolution; } + void set_samplerate(ADS1115Samplerate samplerate) { this->samplerate_ = samplerate; } float sample() override; void dump_config() override; @@ -29,6 +30,7 @@ class ADS1115Sensor : public sensor::Sensor, ADS1115Multiplexer multiplexer_; ADS1115Gain gain_; ADS1115Resolution resolution_; + ADS1115Samplerate samplerate_; }; } // namespace ads1115 diff --git a/tests/components/ads1115/test.esp32-ard.yaml b/tests/components/ads1115/test.esp32-ard.yaml index a869f2379b..0fdaeff275 100644 --- a/tests/components/ads1115/test.esp32-ard.yaml +++ b/tests/components/ads1115/test.esp32-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-c3-ard.yaml b/tests/components/ads1115/test.esp32-c3-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp32-c3-ard.yaml +++ b/tests/components/ads1115/test.esp32-c3-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-c3-idf.yaml b/tests/components/ads1115/test.esp32-c3-idf.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp32-c3-idf.yaml +++ b/tests/components/ads1115/test.esp32-c3-idf.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp32-idf.yaml b/tests/components/ads1115/test.esp32-idf.yaml index a869f2379b..0fdaeff275 100644 --- a/tests/components/ads1115/test.esp32-idf.yaml +++ b/tests/components/ads1115/test.esp32-idf.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.esp8266-ard.yaml b/tests/components/ads1115/test.esp8266-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.esp8266-ard.yaml +++ b/tests/components/ads1115/test.esp8266-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor diff --git a/tests/components/ads1115/test.rp2040-ard.yaml b/tests/components/ads1115/test.rp2040-ard.yaml index 7ac5a09f3f..265d2cad2c 100644 --- a/tests/components/ads1115/test.rp2040-ard.yaml +++ b/tests/components/ads1115/test.rp2040-ard.yaml @@ -10,4 +10,5 @@ sensor: - platform: ads1115 multiplexer: A0_A1 gain: 1.024 + sample_rate: 128 id: ads1115_sensor