#include "ads131m08.h" /* namespace esphome { namespace ads131m08 { static const char *const TAG = "ads131m08"; ADS131M08::ADS131M08(esphome::gpio::GPIOPin *pin) : drdy_pin_(pin) { } void ADS131M08::set_drdy_pin(InternalGPIOPin *pin) { drdy_pin_ = pin; } void ADS131M08::set_sensor(int channel, sensor::Sensor *s) { channels_[channel] = s; } void ADS131M08::set_reference_voltage(float reference_voltage) { this->reference_voltage_ = reference_voltage; } float ADS131M08::get_setup_priority() const { return setup_priority::HARDWARE; } void ADS131M08::setup() { // Initialize SPI with correct settings for ADS131M08 // SPI mode 1: CPOL=0, CPHA=1 //this->spi_setup(); SPI.begin(); SPI.setDataMode(SPI_MODE1); SPI.setBitOrder(MSBFIRST); SPI.setClockDivider(SPI_CLOCK_DIV8); // Adjust clock speed as needed // Configure DRDY pin drdy_pin_->setup(); drdy_pin_->pin_mode(esphome::gpio::FLAG_INPUT | esphome::gpio::FLAG_PULLUP); // Attach interrupt on falling edge of DRDY // esphome::gpio::attach_interrupt(drdy_pin_, esphome::gpio::INTERRUPT_FALLING_EDGE, [this]() { // this->data_ready_ = true; // }); this->drdy_pin_->attach_interrupt(&ADS131M08Component::handle_drdy, this, gpio::INTERRUPT_FALLING_EDGE); // Initialize ADS131M08 initialize_ads131m08(); } // interrupt handler void ADS131M08::handle_drdy(ADS131M08Component *arg) { arg->data_ready_ = true; } void ADS131M08::loop() { if (data_ready_) { data_ready_ = false; read_all_channels(); } } void ADS131M08::initialize_ads131m08() { // Send RESET command SPI.transfer(0x06); delay(1); // Send UNLOCK command SPI.transfer(0x55); SPI.transfer(0x55); // Configure registers as needed (example: set gain, etc.) // Write to MODE register for continuous conversion, disable internal reference (use external MAX6070AAUT12+T at 1.25V) write_register(0x02, 0x0000); // MODE register, continuous mode, INTREF_EN = 0 // Wait for external reference to settle delay(100); // Start conversions SPI.transfer(0x08); // START command } void ADS131M08::write_register(uint8_t reg, uint16_t value) { SPI.transfer(0x40 | reg); // WREG command SPI.transfer(0x00); // Number of registers - 1 (0 for one register) SPI.transfer((value >> 8) & 0xFF); SPI.transfer(value & 0xFF); } void ADS131M08::read_all_channels() { // Send RDATA command or read data directly SPI.transfer(0x12); // RDATA command // Read 24 bytes (3 bytes per channel for 8 channels) for (int i = 0; i < 24; i++) { data_buffer_[i] = SPI.transfer(0x00); } // Convert to voltages for all channels //Sensor *channels[8] = {channel1, channel2, channel3, channel4, channel5, channel6, channel7, channel8}; for (int ch = 0; ch < 8; ch++) { if (this->sensors_[ch] != nullptr) { int offset = ch * 3; int32_t raw = (data_buffer_[offset] << 16) | (data_buffer_[offset + 1] << 8) | data_buffer_[offset + 2]; if (raw & 0x800000) raw |= 0xFF000000; // Sign extend float v = (raw / 8388608.0) * this->reference_voltage_; // 2^23 = 8388608, Vref = 1.25V (MAX6070AAUT12+T) this->sensors_[ch]->publish_state(v); } } } float ADS131M08::read_data(uint8_t channel) { // This function assumes read_all_channels() has been called and data is in data_buffer_ int offset = channel * 3; int32_t raw = (data_buffer_[offset] << 16) | (data_buffer_[offset + 1] << 8) | data_buffer_[offset + 2]; if (raw & 0x800000) raw |= 0xFF000000; // Sign extend float v = (raw / 8388608.0) * this->reference_voltage_; // 2^23 = 8388608, Vref = 1.25V (MAX6070AAUT12+T) return v; } void ADS131M08::dump_config() { ESP_LOGCONFIG(TAG, "ADS131M08:"); LOG_PIN(" CS Pin:", this->cs_); ESP_LOGCONFIG(TAG, " Reference Voltage: %.2fV", this->reference_voltage_); } } // namespace ads131m08 } // namespace esphome */ namespace esphome { namespace ads131m08 { static const char *const TAG = "ads131m08"; void ADS131M08Hub::setup() { this->spi_setup(); this->drdy_pin_->setup(); this->drdy_pin_->attach_interrupt(&ADS131M08Hub::isr, this, gpio::INTERRUPT_FALLING_EDGE); } void IRAM_ATTR ADS131M08Hub::isr(ADS131M08Hub *arg) { arg->data_ready_ = true; } void ADS131M08Hub::loop() { if (this->data_ready_) { this->data_ready_ = false; this->read_data_(); } } void ADS131M08Hub::read_data_() { this->enable(); // ADS131M08 Frame: 1 Status Word + 8 Channel Words + 1 CRC Word (24-bit words) uint8_t frame[30]; // 10 words * 3 bytes this->read_array(frame, 30); this->disable(); for (int i = 0; i < 8; i++) { if (this->sensors_[i] != nullptr) { // Convert 24-bit two's complement to float (Simplified) int32_t raw = (frame[3+(i*3)] << 16) | (frame[4+(i*3)] << 8) | frame[5+(i*3)]; if (raw & 0x800000) raw |= 0xFF000000; // Sign extend this->sensors_[i]->publish_state(raw * (this->reference_voltage_ / 8388608.0)); // 2^23 = 8388608, Vref = 1.25V ( for MAX6070AAUT12+T ) } } } void ADS131M08Hub::dump_config() { ESP_LOGCONFIG(TAG, "ADS131M08:"); LOG_PIN(" CS Pin:", this->cs_); LOG_PIN(" DRDY Pin:", this->drdy_pin_); ESP_LOGCONFIG(TAG, " Reference Voltage: %.2fV", this->reference_voltage_); } } // namespace ads131m08 } // namespace esphome