197 lines
5.2 KiB
C++
197 lines
5.2 KiB
C++
#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
|