ADS1115_int multiple Alert/Rdy lines, i.e. 1 per ADS1115 is working.

This commit is contained in:
Chris Stuurman 2026-01-15 08:22:00 +02:00
parent 602cd9dc0d
commit 391630fd06
5 changed files with 243 additions and 4206 deletions

View File

@ -14,14 +14,14 @@ static const uint8_t ADS1115_REGISTER_HI_TRESH = 0x03;
void ADS1115Component::setup()
{
uint16_t value;
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
this->mark_failed("Could not read ADS1115 conversion register on setup.");
return;
}
// 1. Create a binary semaphore
data_ready_sem = xSemaphoreCreateBinary();
this->alert_pin_->setup();
this->alert_pin_->attach_interrupt(&ADS1115Component::isr_handler, this, gpio::INTERRUPT_FALLING_EDGE);
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
this->mark_failed();
return;
}
// setup with default values
uint16_t config = 0;
// Clear single-shot bit
@ -60,12 +60,13 @@ void ADS1115Component::setup()
config |= 0b0000000000000011;
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
this->mark_failed();
this->mark_failed("Could not write to ADS1115 config register on setup.");
return;
}
this->prev_config_ = config;
if(!this->set_data_ready_mode()) {
this->mark_failed();
this->mark_failed("Could not set ADS1115 data ready mode on setup.");
return;
}
}
@ -92,23 +93,42 @@ void ADS1115Component::loop()
// we read data for the current mux index, then set up the next conversion
void ADS1115Component::read_request_next()
{
int mux_index = this->mux_data_index_ % 4;
auto multiplexer = this->muxdata_[mux_index].multiplexer;
if(multiplexer == ADS1115_MULTIPLEXER_INVALID) {
ESP_LOGE(TAG, "MUX data not set for index %d", mux_index);
}
else {
uint16_t config = 0x0000;
// We do not support multiple ads1115 sharing the same alert/rdy pin, however we still read the ads1115 config register to get the multiplexer value. This allows us to also check the operational status (OS) bit.
// If OS bit set, i.e. the conversion is done meaning we can read the data; this is valid only in single shot mode, in continuous mode (which is not supported by this code) we can read data without checking the status bit
//ESP_LOGD(TAG, "Config: 0x%04X", this->prev_config_);
if(this->read_byte_16(ADS1115_REGISTER_CONFIG, &config)) {
//ESP_LOGD(TAG, "Config register: 0x%04X", config);
int ads_mux = (config >> 12) & 0b111;
bool conversion_done = (config >> 15) == 1;
//ESP_LOGD(TAG, "Current MUX setting according to ADS1115: %d", ads_mux);
int ads_mux_index = get_mux_index(static_cast<ADS1115Multiplexer>(ads_mux));
//ESP_LOGD(TAG, "Current MUX index according to ADS1115: %d", ads_mux_index);
if (conversion_done && ads_mux_index != -1) {
int16_t raw_value = 0;
double v = this->read_data(raw_value, mux_index);
double v = this->read_data(raw_value, ads_mux_index);
if (!std::isnan(v)) {
auto sensor_ptr = this->muxdata_[mux_index].sensor_ptr;
auto sensor_ptr = this->muxdata_[ads_mux_index].sensor_ptr;
ESP_LOGV(TAG, "'% -18s': Raw=% 6d %fV", sensor_ptr->get_name().c_str(), raw_value, v);
sensor_ptr->publish_state(v);
}
// we have read data for the current mux index, move to next
int next_index = next_mux_data_index(ads_mux_index);
if(next_index != -1) {
this->start_single_shot_conversion(next_index);
}
if(next_mux_data_index() != -1) {
this->start_single_shot_conversion();
}
}
}
int ADS1115Component::get_mux_index(ADS1115Multiplexer multiplexer)
{
for(int i=0; i<4; i++) {
if(this->muxdata_[i].multiplexer == multiplexer) {
return i;
}
}
return -1; // not found
}
double ADS1115Component::read_data(int16_t& raw_value, int mux_index)
@ -192,28 +212,34 @@ int ADS1115Component::set_mux_data(ADS1115Multiplexer multiplexer, ADS1115Gain g
bool ADS1115Component::set_data_ready_mode()
{
bool success = true;
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;
ESP_LOGE(TAG, "Failed to write to ads1115 to set comparator que mode");
success = false;
}
else {
this->prev_config_ = config;
if(!this->write_byte_16(ADS1115_REGISTER_HI_TRESH, 0x8000)) {
return false;
ESP_LOGE(TAG, "Failed to write to ads1115 to set high threshold register for alert pin");
success = false;
}
else {
if(!this->write_byte_16(ADS1115_REGISTER_LO_TRESH, 0x0000)) {
return false;
ESP_LOGE(TAG, "Failed to write to ads1115 to set low threshold register for alert pin");
success = false;
}
return true;
}
}
return success;
}
bool ADS1115Component::start_single_shot_conversion()
bool ADS1115Component::start_single_shot_conversion(int mux_index)
{
int mux_index = this->mux_data_index_;
auto& muxdata = this->muxdata_[mux_index];
auto multiplexer = muxdata.multiplexer;
if (multiplexer != ADS1115_MULTIPLEXER_INVALID) {
@ -248,15 +274,16 @@ bool ADS1115Component::start_single_shot_conversion()
}
return false;
}
int ADS1115Component::next_mux_data_index()
int ADS1115Component::next_mux_data_index(int start_index)
{
int start_index = this->mux_data_index_;
int result = start_index;
do {
this->mux_data_index_ = (this->mux_data_index_ + 1) % 4;
if(this->muxdata_[this->mux_data_index_].multiplexer != ADS1115_MULTIPLEXER_INVALID) {
return this->mux_data_index_;
result = (result + 1) % 4;
if(this->muxdata_[result].multiplexer != ADS1115_MULTIPLEXER_INVALID) {
return result;
}
} while(this->mux_data_index_ != start_index);
} while(result != start_index);
return -1; // no valid mux data found
}

View File

@ -60,10 +60,11 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
sensor::Sensor *sensor_ptr;
mux_data_item() { multiplexer = ADS1115_MULTIPLEXER_INVALID; }
};
int next_mux_data_index();
void read_request_next();
int mux_data_index_{0};
mux_data_item muxdata_[4];
int next_mux_data_index(int start_index);
void read_request_next();
int get_mux_index(ADS1115Multiplexer multiplexer);
public:
// Semaphore handle
@ -72,7 +73,7 @@ class ADS1115Component : public Component, public i2c::I2CDevice {
void loop() override;
void dump_config() override;
double read_data(int16_t& raw_value, int mux_index);
bool start_single_shot_conversion();
bool start_single_shot_conversion(int mux_index);
void set_alert_pin(InternalGPIOPin *pin) { alert_pin_ = pin; }
bool set_data_ready_mode();
int set_mux_data(ADS1115Multiplexer multiplexer, ADS1115Gain gain, ADS1115Resolution resolution, ADS1115Samplerate samplerate, sensor::Sensor *sensor_ptr);

View File

@ -10,9 +10,9 @@ static const char *const TAG = "ads1115_int.sensor";
void ADS1115Sensor::loop()
{
if(this->first_reading_) {
this->parent_->set_mux_data(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_, this);
int mux_index = this->parent_->set_mux_data(this->multiplexer_, this->gain_, this->resolution_, this->samplerate_, this);
this->first_reading_ = false;
this->parent_->start_single_shot_conversion(); // this will set off the first conversion; subsequent conversions will be triggered by the ISR
this->parent_->start_single_shot_conversion(mux_index); // this will set off the first conversion; subsequent conversions will be triggered by the ISR
}
}

View File

@ -12,7 +12,7 @@ static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
void ADS1115Component::setup() {
uint16_t value;
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
this->mark_failed();
this->mark_failed(/*LOG_STR*/("Could not read ADS1115 conversion register on setup."));
return;
}
@ -59,13 +59,13 @@ void ADS1115Component::setup() {
config |= 0b0000000000000011;
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
this->mark_failed();
this->mark_failed(/*LOG_STR*/("Could not write to ADS1115 config register on setup."));
return;
}
this->prev_config_ = config;
}
void ADS1115Component::dump_config() {
ESP_LOGCONFIG(TAG, "ADS1115:");
ESP_LOGCONFIG(TAG, "ADS1115_pol:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);

File diff suppressed because it is too large Load Diff