configs/components/ads1115_int/ads1115_int.cpp

229 lines
6.5 KiB
C++

#include "ads1115_int.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
namespace esphome {
namespace ads1115_int {
static const char *const TAG = "ads1115_int";
static const uint8_t ADS1115_REGISTER_CONVERSION = 0x00;
static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
static const uint8_t ADS1115_REGISTER_LO_TRESH = 0x02;
static const uint8_t ADS1115_REGISTER_HI_TRESH = 0x03;
void ADS1115Component::setup() {
uint16_t value;
this->alert_pin_->setup();
this->alert_pin_->attach_interrupt(&ADS1115Component::isr, this, gpio::INTERRUPT_FALLING_EDGE);
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
this->mark_failed();
return;
}
uint16_t config = 0;
// Clear single-shot bit
// 0b0xxxxxxxxxxxxxxx
config |= 0b0000000000000000;
// Setup multiplexer
// 0bx000xxxxxxxxxxxx
config |= ADS1115_MULTIPLEXER_P0_N1 << 12;
// Setup Gain
// 0bxxxx000xxxxxxxxx
config |= ADS1115_GAIN_6P144 << 9;
if (this->continuous_mode_) {
// Set continuous mode
// 0bxxxxxxx0xxxxxxxx
config |= 0b0000000000000000;
} else {
// Set singleshot mode
// 0bxxxxxxx1xxxxxxxx
config |= 0b0000000100000000;
}
// Set data rate - 860 samples per second
// 0bxxxxxxxx100xxxxx
config |= ADS1115_860SPS << 5;
// Set comparator mode - hysteresis
// 0bxxxxxxxxxxx0xxxx
config |= 0b0000000000000000;
// Set comparator polarity - active low
// 0bxxxxxxxxxxxx0xxx
config |= 0b0000000000000000;
// Set comparator latch enabled - false
// 0bxxxxxxxxxxxxx0xx
config |= 0b0000000000000000;
// Set comparator que mode - disabled
// 0bxxxxxxxxxxxxxx11
config |= 0b0000000000000011;
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
this->mark_failed();
return;
}
this->prev_config_ = config;
if(!this->set_alert_ready_mode()) {
this->mark_failed();
return;
}
}
bool ADS1115Component::set_alert_ready_mode()
{
uint16_t config = this->prev_config_;
// Set comparator que mode - assert after one conversion
// 0bxxxxxxxxxxxxxx00
config &= 0b1111111111111100;
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
return false;
}
this->prev_config_ = config;
if(!this->write_byte_16(ADS1115_REGISTER_HI_TRESH, 0x8000)) {
return false;
}
if(!this->write_byte_16(ADS1115_REGISTER_LO_TRESH, 0x0000)) {
return false;
}
// also clear all data_ready_ flags
for (int i = 0; i < 8; i++)
this->data_ready_[i] = false;
return true;
}
// ISR function to handle interrupt from alert pin
// only function that sets data_ready_ flags
void IRAM_ATTR ADS1115Component::isr(ADS1115Component *arg)
{
for (int i = 0; i < 8; i++)
arg->data_ready_[i] = true;
}
bool ADS1115Component::is_data_ready(ADS1115Multiplexer multiplexer)
{
int index = static_cast<int>(multiplexer);
if(index < 0 || index >= 8)
return false;
return this->data_ready_[index];
}
void ADS1115Component::clear_alert_ready(ADS1115Multiplexer multiplexer)
{
int index = static_cast<int>(multiplexer);
if(index < 0 || index >= 8)
return;
this->data_ready_[index] = false;
}
// call only when data_ready_ is true
double ADS1115Component::read_data(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, ADS1115Samplerate samplerate)
{
uint16_t config = this->prev_config_;
// Multiplexer
// 0bxBBBxxxxxxxxxxxx
config &= 0b1000111111111111;
config |= (multiplexer & 0b111) << 12;
// Gain
// 0bxxxxBBBxxxxxxxxx
config &= 0b1111000111111111;
config |= (gain & 0b111) << 9;
// Sample rate
// 0bxxxxxxxxBBBxxxxx
config &= 0b1111111100011111;
config |= (samplerate & 0b111) << 5;
if (!this->continuous_mode_) {
// Start conversion
config |= 0b1000000000000000;
}
this->clear_alert_ready(multiplexer);
//ESP_LOGI(TAG, "'mux:%d': Gain=%d, Res=%d, CONF=<0x%04X>", static_cast<int>(multiplexer), static_cast<int>(gain), static_cast<int>(resolution), config);
// write config if in single-shot mode or config has changed
if (!this->continuous_mode_ || this->prev_config_ != config) {
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
this->status_set_warning();
return false;
}
this->prev_config_ = config;
if (!this->continuous_mode_) {
uint32_t start = millis();
// wait for conversion to complete
while (this->read_byte_16(ADS1115_REGISTER_CONFIG, &config) && (config >> 15) == 0) {
if (millis() - start > 100) {
ESP_LOGW(TAG, "Reading ADS1115 timed out");
this->status_set_warning();
return NAN;
}
yield();
}
}
}
uint16_t raw_conversion;
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &raw_conversion)) {
this->status_set_warning();
return NAN;
}
//ESP_LOGI(TAG, "'mux:%d': raw=<0x%04X>", static_cast<int>(multiplexer), raw_conversion);
if (resolution == ADS1015_12_BITS) {
bool negative = (raw_conversion >> 15) == 1;
// shift raw_conversion as it's only 12-bits, left justified
raw_conversion = raw_conversion >> (16 - ADS1015_12_BITS);
// check if number was negative in order to keep the sign
if (negative) {
// the number was negative
// 1) set the negative bit back
raw_conversion |= 0x8000;
// 2) reset the former (shifted) negative bit
raw_conversion &= 0xF7FF;
}
}
auto signed_conversion = static_cast<int16_t>(raw_conversion);
double millivolts;
double divider = (resolution == ADS1115_16_BITS) ? 32768.0f : 2048.0f;
switch (gain) {
case ADS1115_GAIN_6P144:
millivolts = (signed_conversion * 6144) / divider;
break;
case ADS1115_GAIN_4P096:
millivolts = (signed_conversion * 4096) / divider;
break;
case ADS1115_GAIN_2P048:
millivolts = (signed_conversion * 2048) / divider;
break;
case ADS1115_GAIN_1P024:
millivolts = (signed_conversion * 1024) / divider;
break;
case ADS1115_GAIN_0P512:
millivolts = (signed_conversion * 512) / divider;
break;
case ADS1115_GAIN_0P256:
millivolts = (signed_conversion * 256) / divider;
break;
default:
millivolts = NAN;
}
this->status_clear_warning();
return millivolts / 1e3f;
}
void ADS1115Component::dump_config()
{
ESP_LOGCONFIG(TAG, "ADS1115_INT:");
LOG_I2C_DEVICE(this);
LOG_PIN(" ALERT Pin:", this->alert_pin_);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
} // namespace ads1115_int
} // namespace esphome