ESPHome  2022.9.2
ads1115.cpp
Go to the documentation of this file.
1 #include "ads1115.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/hal.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;
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  uint16_t config = 0;
22  // Clear single-shot bit
23  // 0b0xxxxxxxxxxxxxxx
24  config |= 0b0000000000000000;
25  // Setup multiplexer
26  // 0bx000xxxxxxxxxxxx
27  config |= ADS1115_MULTIPLEXER_P0_N1 << 12;
28 
29  // Setup Gain
30  // 0bxxxx000xxxxxxxxx
31  config |= ADS1115_GAIN_6P144 << 9;
32 
33  if (this->continuous_mode_) {
34  // Set continuous mode
35  // 0bxxxxxxx0xxxxxxxx
36  config |= 0b0000000000000000;
37  } else {
38  // Set singleshot mode
39  // 0bxxxxxxx1xxxxxxxx
40  config |= 0b0000000100000000;
41  }
42 
43  // Set data rate - 860 samples per second (we're in singleshot mode)
44  // 0bxxxxxxxx100xxxxx
45  config |= ADS1115_DATA_RATE_860_SPS << 5;
46 
47  // Set comparator mode - hysteresis
48  // 0bxxxxxxxxxxx0xxxx
49  config |= 0b0000000000000000;
50 
51  // Set comparator polarity - active low
52  // 0bxxxxxxxxxxxx0xxx
53  config |= 0b0000000000000000;
54 
55  // Set comparator latch enabled - false
56  // 0bxxxxxxxxxxxxx0xx
57  config |= 0b0000000000000000;
58 
59  // Set comparator que mode - disabled
60  // 0bxxxxxxxxxxxxxx11
61  config |= 0b0000000000000011;
62 
63  if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
64  this->mark_failed();
65  return;
66  }
67  this->prev_config_ = config;
68 }
70  ESP_LOGCONFIG(TAG, "Setting up ADS1115...");
71  LOG_I2C_DEVICE(this);
72  if (this->is_failed()) {
73  ESP_LOGE(TAG, "Communication with ADS1115 failed!");
74  }
75 
76  for (auto *sensor : this->sensors_) {
77  LOG_SENSOR(" ", "Sensor", sensor);
78  ESP_LOGCONFIG(TAG, " Multiplexer: %u", sensor->get_multiplexer());
79  ESP_LOGCONFIG(TAG, " Gain: %u", sensor->get_gain());
80  }
81 }
83  uint16_t config = this->prev_config_;
84  // Multiplexer
85  // 0bxBBBxxxxxxxxxxxx
86  config &= 0b1000111111111111;
87  config |= (sensor->get_multiplexer() & 0b111) << 12;
88 
89  // Gain
90  // 0bxxxxBBBxxxxxxxxx
91  config &= 0b1111000111111111;
92  config |= (sensor->get_gain() & 0b111) << 9;
93 
94  if (!this->continuous_mode_) {
95  // Start conversion
96  config |= 0b1000000000000000;
97  }
98 
99  if (!this->continuous_mode_ || this->prev_config_ != config) {
100  if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
101  this->status_set_warning();
102  return NAN;
103  }
104  this->prev_config_ = config;
105 
106  // about 1.2 ms with 860 samples per second
107  delay(2);
108 
109  // in continuous mode, conversion will always be running, rely on the delay
110  // to ensure conversion is taking place with the correct settings
111  // can we use the rdy pin to trigger when a conversion is done?
112  if (!this->continuous_mode_) {
113  uint32_t start = millis();
114  while (this->read_byte_16(ADS1115_REGISTER_CONFIG, &config) && (config >> 15) == 0) {
115  if (millis() - start > 100) {
116  ESP_LOGW(TAG, "Reading ADS1115 timed out");
117  this->status_set_warning();
118  return NAN;
119  }
120  yield();
121  }
122  }
123  }
124 
125  uint16_t raw_conversion;
126  if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) {
127  this->status_set_warning();
128  return NAN;
129  }
130  auto signed_conversion = static_cast<int16_t>(raw_conversion);
131 
132  float millivolts;
133  switch (sensor->get_gain()) {
134  case ADS1115_GAIN_6P144:
135  millivolts = signed_conversion * 0.187500f;
136  break;
137  case ADS1115_GAIN_4P096:
138  millivolts = signed_conversion * 0.125000f;
139  break;
140  case ADS1115_GAIN_2P048:
141  millivolts = signed_conversion * 0.062500f;
142  break;
143  case ADS1115_GAIN_1P024:
144  millivolts = signed_conversion * 0.031250f;
145  break;
146  case ADS1115_GAIN_0P512:
147  millivolts = signed_conversion * 0.015625f;
148  break;
149  case ADS1115_GAIN_0P256:
150  millivolts = signed_conversion * 0.007813f;
151  break;
152  default:
153  millivolts = NAN;
154  }
155 
156  this->status_clear_warning();
157  return millivolts / 1e3f;
158 }
159 
160 float ADS1115Sensor::sample() { return this->parent_->request_measurement(this); }
162  float v = this->parent_->request_measurement(this);
163  if (!std::isnan(v)) {
164  ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
165  this->publish_state(v);
166  }
167 }
168 
169 } // namespace ads1115
170 } // namespace esphome
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition: i2c.h:107
uint8_t get_multiplexer() const
Definition: ads1115.h:61
float request_measurement(ADS1115Sensor *sensor)
Helper method to request a measurement from a sensor.
Definition: ads1115.cpp:82
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:26
Internal holder class that is in instance of Sensor so that the hub can create individual sensors...
Definition: ads1115.h:53
void status_clear_warning()
Definition: component.cpp:148
uint8_t get_gain() const
Definition: ads1115.h:62
void status_set_warning()
Definition: component.cpp:140
void IRAM_ATTR HOT yield()
Definition: core.cpp:25
std::vector< ADS1115Sensor * > sensors_
Definition: ads1115.h:47
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:111
void setup() override
Set up the internal sensor array.
Definition: ads1115.cpp:14
Definition: a4988.cpp:4
bool write_byte_16(uint8_t a_register, uint16_t data)
Definition: i2c.h:127
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:27