ESPHome  2024.7.1
ads1115.cpp
Go to the documentation of this file.
1 #include "ads1115.h"
2 #include "esphome/core/hal.h"
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace ads1115 {
7 
8 static const char *const TAG = "ads1115";
9 static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
10 static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
11 
12 static const uint8_t ADS1115_DATA_RATE_860_SPS = 0b111; // 3300_SPS for ADS1015
13 
15  ESP_LOGCONFIG(TAG, "Setting up ADS1115...");
16  uint16_t value;
17  if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
18  this->mark_failed();
19  return;
20  }
21 
22  ESP_LOGCONFIG(TAG, "Configuring ADS1115...");
23 
24  uint16_t config = 0;
25  // Clear single-shot bit
26  // 0b0xxxxxxxxxxxxxxx
27  config |= 0b0000000000000000;
28  // Setup multiplexer
29  // 0bx000xxxxxxxxxxxx
30  config |= ADS1115_MULTIPLEXER_P0_N1 << 12;
31 
32  // Setup Gain
33  // 0bxxxx000xxxxxxxxx
34  config |= ADS1115_GAIN_6P144 << 9;
35 
36  if (this->continuous_mode_) {
37  // Set continuous mode
38  // 0bxxxxxxx0xxxxxxxx
39  config |= 0b0000000000000000;
40  } else {
41  // Set singleshot mode
42  // 0bxxxxxxx1xxxxxxxx
43  config |= 0b0000000100000000;
44  }
45 
46  // Set data rate - 860 samples per second (we're in singleshot mode)
47  // 0bxxxxxxxx100xxxxx
48  config |= ADS1115_DATA_RATE_860_SPS << 5;
49 
50  // Set comparator mode - hysteresis
51  // 0bxxxxxxxxxxx0xxxx
52  config |= 0b0000000000000000;
53 
54  // Set comparator polarity - active low
55  // 0bxxxxxxxxxxxx0xxx
56  config |= 0b0000000000000000;
57 
58  // Set comparator latch enabled - false
59  // 0bxxxxxxxxxxxxx0xx
60  config |= 0b0000000000000000;
61 
62  // Set comparator que mode - disabled
63  // 0bxxxxxxxxxxxxxx11
64  config |= 0b0000000000000011;
65 
66  if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
67  this->mark_failed();
68  return;
69  }
70  this->prev_config_ = config;
71 }
73  ESP_LOGCONFIG(TAG, "Setting up ADS1115...");
74  LOG_I2C_DEVICE(this);
75  if (this->is_failed()) {
76  ESP_LOGE(TAG, "Communication with ADS1115 failed!");
77  }
78 }
80  ADS1115Resolution resolution) {
81  uint16_t config = this->prev_config_;
82  // Multiplexer
83  // 0bxBBBxxxxxxxxxxxx
84  config &= 0b1000111111111111;
85  config |= (multiplexer & 0b111) << 12;
86 
87  // Gain
88  // 0bxxxxBBBxxxxxxxxx
89  config &= 0b1111000111111111;
90  config |= (gain & 0b111) << 9;
91 
92  if (!this->continuous_mode_) {
93  // Start conversion
94  config |= 0b1000000000000000;
95  }
96 
97  if (!this->continuous_mode_ || this->prev_config_ != config) {
98  if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
99  this->status_set_warning();
100  return NAN;
101  }
102  this->prev_config_ = config;
103 
104  // about 1.2 ms with 860 samples per second
105  delay(2);
106 
107  // in continuous mode, conversion will always be running, rely on the delay
108  // to ensure conversion is taking place with the correct settings
109  // can we use the rdy pin to trigger when a conversion is done?
110  if (!this->continuous_mode_) {
111  uint32_t start = millis();
112  while (this->read_byte_16(ADS1115_REGISTER_CONFIG, &config) && (config >> 15) == 0) {
113  if (millis() - start > 100) {
114  ESP_LOGW(TAG, "Reading ADS1115 timed out");
115  this->status_set_warning();
116  return NAN;
117  }
118  yield();
119  }
120  }
121  }
122 
123  uint16_t raw_conversion;
124  if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) {
125  this->status_set_warning();
126  return NAN;
127  }
128 
129  if (resolution == ADS1015_12_BITS) {
130  bool negative = (raw_conversion >> 15) == 1;
131 
132  // shift raw_conversion as it's only 12-bits, left justified
133  raw_conversion = raw_conversion >> (16 - ADS1015_12_BITS);
134 
135  // check if number was negative in order to keep the sign
136  if (negative) {
137  // the number was negative
138  // 1) set the negative bit back
139  raw_conversion |= 0x8000;
140  // 2) reset the former (shifted) negative bit
141  raw_conversion &= 0xF7FF;
142  }
143  }
144 
145  auto signed_conversion = static_cast<int16_t>(raw_conversion);
146 
147  float millivolts;
148  float divider = (resolution == ADS1115_16_BITS) ? 32768.0f : 2048.0f;
149  switch (gain) {
150  case ADS1115_GAIN_6P144:
151  millivolts = (signed_conversion * 6144) / divider;
152  break;
153  case ADS1115_GAIN_4P096:
154  millivolts = (signed_conversion * 4096) / divider;
155  break;
156  case ADS1115_GAIN_2P048:
157  millivolts = (signed_conversion * 2048) / divider;
158  break;
159  case ADS1115_GAIN_1P024:
160  millivolts = (signed_conversion * 1024) / divider;
161  break;
162  case ADS1115_GAIN_0P512:
163  millivolts = (signed_conversion * 512) / divider;
164  break;
165  case ADS1115_GAIN_0P256:
166  millivolts = (signed_conversion * 256) / divider;
167  break;
168  default:
169  millivolts = NAN;
170  }
171 
172  this->status_clear_warning();
173  return millivolts / 1e3f;
174 }
175 
176 } // namespace ads1115
177 } // namespace esphome
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition: i2c.h:246
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
float request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution)
Helper method to request a measurement from a sensor.
Definition: ads1115.cpp:79
bool is_failed() const
Definition: component.cpp:143
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
AlsGain gain
void status_clear_warning()
Definition: component.cpp:166
void IRAM_ATTR HOT yield()
Definition: core.cpp:24
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
bool write_byte_16(uint8_t a_register, uint16_t data)
Definition: i2c.h:266
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26