Added datasheet example code and some arduino git code from tpcorrea. Still WIP.

This commit is contained in:
Chris Stuurman 2026-01-10 23:08:07 +02:00
parent 81c179b556
commit 76fd7fa443
2 changed files with 573 additions and 103 deletions

View File

@ -1,74 +1,28 @@
#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()
void ADS131M08Hub::setup()
{
// Initialize SPI with correct settings for ADS131M08
// SPI mode 1: CPOL=0, CPHA=1
//this->spi_setup();
this->spi_setup();
// not sure if next few lines are needed here or is it handled in 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();
SPI.setClockDivider(SPI_CLOCK_DIV8); // Adjust clock speed as needed
this->drdy_pin_->setup();
this->drdy_pin_->pin_mode(esphome::gpio::FLAG_INPUT | esphome::gpio::FLAG_PULLUP);
this->drdy_pin_->attach_interrupt(&ADS131M08Hub::isr, this, gpio::INTERRUPT_FALLING_EDGE);
this->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()
void ADS131M08Hub::initialize_ads131m08()
{
// Send RESET command
SPI.transfer(0x06);
@ -89,7 +43,7 @@ void ADS131M08::initialize_ads131m08()
SPI.transfer(0x08); // START command
}
void ADS131M08::write_register(uint8_t reg, uint16_t value)
void ADS131M08Hub::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)
@ -97,6 +51,99 @@ void ADS131M08::write_register(uint8_t reg, uint16_t value)
SPI.transfer(value & 0xFF);
}
void IRAM_ATTR ADS131M08Hub::isr(ADS131M08Hub *arg)
{
arg->txf_init(); // implementing datasheet recommended TXF init in ISR
arg->data_ready_ = true;
}
void ADS131M08Hub::loop()
{
if (this->data_ready_) {
this->data_ready_ = false;
this->read_data_();
}
}
// ********************** from datasheet ************************
void ADS131M08Hub::txf_init()
{
if (firstRead) {
// Clear the ADC's 2-deep FIFO on the first read
for (int i = 0; i <numFrameWords; i++) {
SPI.write(spiDummyWord + i);
}
for(int i = 0; i < numFrameWords; i++) {
SPI.read();
}
firstRead = false; // Clear the flag
DMA.enable(); // Let the DMA start sending ADC data to memory
}
for (int i = 0; i < numFrameWords; i++) {// Send the dummy data to the ADC to get the ADC data
SPI.write(spiDummyWord + i);
}
}
/* adcRegisterWrite
Short function that writes one ADC register at a time.
Blocks return until SPI is idle.
Returns false if the word length is wrong.
param
addrMask: 16-bit register address mask
data: data to write adcWord
Length: word length which ADC expects. Either 16, 24 or 32.
return true if word length was valid false if not
*/
bool ADS131M08Hub::adcRegisterWrite(unsigned short addrMask, unsigned short data, unsigned char adcWordLength)
{
unsigned char shiftValue; // Stores the amount of bit shift based on ADC word length
if(adcWordLength == 16) {
shiftValue = 0; // If length is 16, no shift
}
else if(adcWordLength == 24) {
shiftValue = 8; // If length is 24, shift left by 8
}
else if(adcWordLength == 32) {
shiftValue = 16; // If length is 32, shift left by 16
} else {
return false; // If not, invalid length
}
SPI.write((CMD_WREG | addrMask) << shiftValue); // Write address and opcode; Shift to accommodate ADC word length
SPI.write(data << shiftValue); // Write register data
while(SPI.isBusy()); // Wait for data to complete sending
return true;
}
void ADS131M08Hub::initialize_ads131m08_datasheet()
{
// enableSupplies();
// GPIO.inputEnable('input'); // Enable GPIO connected to DRDY
// clkout.enable(8192000); // Enable 8.192 MHz clock to CLKIN
// SPI.enable(); // Enable SPI port
// SPI.wordLengthSet(24); // ADC default word length is 24 bits
// SPI.configCS(STAY_ASSERTED);// Configure CS to remain asserted until frame is complete
while(!GPIO.read()){} // Wait for DRDY to go high indicating it is ok to talk to ADC
adcRegisterWrite(REG_CLOCK, MASK_CLOCK_ALL_CH_DISABLE | OSR_1024 | PM_HIGH_RESOLUTION, 24); // Write CLOCK register; Turn off all channels so short frames can be written during config
// Re-write defaults for other bits in CLOCK register
adcRegisterWrite(REG_MODE, MODE_NO_RESET | DRDY_FMT_PULSE | WLENGTH_24_BITS | TIMEOUT_ENABLED, 24); // Write MODE register; Clear the RESET flag, make DRDY active low pulse
// Re-write defaults for other bits in MODE register
adcRegisterWrite(REG_GAIN1, PGAGAIN3_32 | PGAGAIN1_32, 24); // Write GAIN1 register; Set channels 1 and 3 PGA gain to 32 in this example
// Leave channels 0 and 2 at default gain of 1
adcRegisterWrite(REG_THRSHLD_LSB, 0x09, 24); // Write THRSHLD_LSB register; Set DCBLOCK filter to have a corner frequency of 622 mHz
DMA.triggerSet(SPI);// Configure DMA to trigger when data comes in on the MCU SPI port
DMA.txAddrSet(SPI.rxAddr());// Set the DMA to take from the incoming SPI port
DMA.rxAddrSet(&adcData);// Set the DMA to send ADC data to a predefined memory location
adcRegisterWrite(REG_MODE, WLENGTH_32_BITS_MSB_SIGN_EXTEND | DRDY_FMT_PULSE | TIMEOUT_ENABLED, 24); // Write MODE register; Make ADC word size 32 bits to accommodate DMA;
// Re-write other set bits in MODE register
SPI.wordLengthSet(32); // Set SPI word size to 32 bits to accomodate DMA
adcRegisterWrite(REG_CLOCK, MASK_CLOCK_ALL_CH_ENABLE | OSR_1024 | PM_HIGH_RESOLUTION, 32); // Write CLOCK register; Turn on all ADC channels; Re-write defaults for other bits in CLOCK register
GPIO.interuptEnable();// Enable DRDY interrupt and begin streaming data
}
// ********************** end of from datasheet ************************
/*
void ADS131M08::read_all_channels()
{
// Send RDATA command or read data directly
@ -120,52 +167,7 @@ void ADS131M08::read_all_channels()
}
}
}
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();

View File

@ -8,6 +8,422 @@
namespace esphome {
namespace ads131m08 {
typedef union {
int32_t i;
float f;
uint16_t u[2];
uint8_t b[4];
} flex32_t;
/* Adc Structure. Ch can be read as int32 or float*/
struct AdcOutput
{
uint16_t status;
flex32_t ch[8];
};
enum ADS131M08_DRDY_STATE
{
DS_LOGIC_HIGH = 0, // DEFAULT
DS_HI_Z = 1
};
enum ADS131M08_POWERMODE
{
PM_VERY_LOW_POWER = 0,
PM_LOW_POWER = 1,
PM_HIGH_RESOLUTION = 2 // DEFAULT
};
enum ADS131M08_PGA_GAIN
{
PGA_1 = 0,
PGA_2 = 1,
PGA_4 = 2,
PGA_8 = 3,
PGA_16 = 4,
PGA_32 = 5,
PGA_64 = 6,
PGA_128 = 7,
PGA_INVALID
};
enum ADS131M08_INPUT_CHANNEL_MUX
{
ICM_AIN0P_AIN0N = 0, // DEFAULT
ICM_INPUT_SHORTED = 1,
ICM_POSITIVE_DC_TEST_SIGNAL = 2,
ICM_NEGATIVE_DC_TEST_SIGNAL = 3,
};
enum ADS131M08_OVERSAMPLING_RATIO
{
OSR_128 = 0,
OSR_256 = 1,
OSR_512 = 2,
OSR_1024 = 3, // default
OSR_2048 = 4,
OSR_4096 = 5,
OSR_8192 = 6,
OSR_16384 = 7
};
enum ADS131M08_WAIT_TIME
{
WT_128 = 856,
WT_256 = 1112,
WT_512 = 1624,
WT_1024 = 2648,
WT_2048 = 4696,
WT_4096 = 8792,
WT_8192 = 16984,
WT_16384 = 33368
};
// MODE Register
enum ADS131M08_RESET : uint16_t
{
MODE_NO_RESET = 0x0000, // DEFAULT
MODE_RESET_HAPPENED = 0x0400
};
enum ADS131M08_CRC_TYPE : uint16_t
{
CRC_CCITT_16BIT = 0x0000, // DEFAULT
CRC_ANSI_16BIT = 0x0800
};
enum ADS131M08_WORD_LENGTH : uint16_t
{
WLENGTH_16_BITS = 0x0000,
WLENGTH_24_BITS = 0x0100, // DEFAULT
WLENGTH_32_BITS_LSB_ZERO_PADDING = 0x0200,
WLENGTH_32_BITS_MSB_SIGN_EXTEND = 0x0300
};
enum ADS131M08_TIMEOUT : uint16_t
{
TIMEOUT_DISABLED = 0x0000,
TIMEOUT_ENABLED = 0x0010 // DEFAULT
};
enum ADS131M08_DRDY_SELECTION : uint16_t
{
DRDY_SEL_MOST_LAGGING = 0x0000, // DEFAULT
DRDY_SEL_LOGICAL_OR = 0x0004,
DRDY_SEL_MOST_LEADING_CHAN = 0x0008,
DRDY_SEL_MOST_LEADING_CHAN = 0x000C
};
enum ADS131M08_DRDY_FORMAT : uint16_t
{
DRDY_FMT_LEVEL = 0x0000, // Logic low (default)
DRDY_FMT_PULSE = 0x0001 // Low pulse with a fixed duration
};
// end of MODE Register
// GAIN1 Register
enum ADS131M08_GAIN1_CHANNEL_PGA : uint16_t {
PGAGAIN0_1 = 0x0000, // default
PGAGAIN0_2 = 0x0001,
PGAGAIN0_4 = 0x0002,
PGAGAIN0_8 = 0x0003,
PGAGAIN0_16 = 0x0004,
PGAGAIN0_32 = 0x0005,
PGAGAIN0_64 = 0x0006,
PGAGAIN0_128 = 0x0007,
PGAGAIN1_1 = 0x0000, // default
PGAGAIN1_2 = 0x0010,
PGAGAIN1_4 = 0x0020,
PGAGAIN1_8 = 0x0030,
PGAGAIN1_16 = 0x0040,
PGAGAIN1_32 = 0x0050,
PGAGAIN1_64 = 0x0060,
PGAGAIN1_128 = 0x0070,
PGAGAIN2_1 = 0x0000, // default
PGAGAIN2_2 = 0x0100,
PGAGAIN2_4 = 0x0200,
PGAGAIN2_8 = 0x0300,
PGAGAIN2_16 = 0x0400,
PGAGAIN2_32 = 0x0500,
PGAGAIN2_64 = 0x0600,
PGAGAIN2_128 = 0x0700,
PGAGAIN3_1 = 0x0000, // default
PGAGAIN3_2 = 0x1000,
PGAGAIN3_4 = 0x2000,
PGAGAIN3_8 = 0x3000,
PGAGAIN3_16 = 0x4000,
PGAGAIN3_32 = 0x5000, // Set PGA gain to 32 for channel
PGAGAIN3_64 = 0x6000,
PGAGAIN3_128 = 0x7000
};
// end of GAIN1 Register
// GAIN2 Register
enum ADS131M08_GAIN2_CHANNEL_PGA : uint16_t {
PGAGAIN4_1 = 0x0000, // default
PGAGAIN4_2 = 0x0001,
PGAGAIN4_4 = 0x0002,
PGAGAIN4_8 = 0x0003,
PGAGAIN4_16 = 0x0004,
PGAGAIN4_32 = 0x0005,
PGAGAIN4_64 = 0x0006,
PGAGAIN4_128 = 0x0007,
PGAGAIN5_1 = 0x0000, // default
PGAGAIN5_2 = 0x0010,
PGAGAIN5_4 = 0x0020,
PGAGAIN5_8 = 0x0030,
PGAGAIN5_16 = 0x0040,
PGAGAIN5_32 = 0x0050,
PGAGAIN5_64 = 0x0060,
PGAGAIN5_128 = 0x0070,
PGAGAIN6_1 = 0x0000, // default
PGAGAIN6_2 = 0x0100,
PGAGAIN6_4 = 0x0200,
PGAGAIN6_8 = 0x0300,
PGAGAIN6_16 = 0x0400,
PGAGAIN6_32 = 0x0500,
PGAGAIN6_64 = 0x0600,
PGAGAIN6_128 = 0x0700,
PGAGAIN7_1 = 0x0000, // default
PGAGAIN7_2 = 0x1000,
PGAGAIN7_4 = 0x2000,
PGAGAIN7_8 = 0x3000,
PGAGAIN7_16 = 0x4000,
PGAGAIN7_32 = 0x5000,
PGAGAIN7_64 = 0x6000,
PGAGAIN7_128 = 0x7000
};
// end of GAIN2 Register
// Commands
enum ADS131M08_COMMANDS : uint16_t {
CMD_NULL = 0x0000, // No operation; used to read STATUS register
CMD_RESET = 0x0011, // RESET the device
CMD_STANDBY = 0x0022, // Place the device into standby mode
CMD_WAKEUP = 0x0033, // Wake up device from standby mode to conversion mode
CMD_LOCK = 0x0555, // Lock the interface such that only the NULL, UNLOCK, and RREG commands are valid
CMD_UNLOCK = 0x0655, // Unlock the interface after the interface is locked
CMD_RREG = 0xA000, // Read register command base; number of registers to read added to lower byte; register address to upper byte
CMD_WREG = 0x6000, // Write register command base; number of registers to write added to lower byte; register address to upper byte
};
// Responses
enum ADS131M08_RESPONSES : uint16_t {
RSP_RESET_OK = 0xFF28,
RSP_RESET_NOK = 0x0011
};
enum ADS131M08_REG {
REG_ID = 0x00,
REG_STATUS = 0x01,
REG_MODE = 0x02,
REG_CLOCK = 0x03,
REG_GAIN1 = 0x04,
REG_GAIN2 = 0x05,
REG_CFG = 0x06,
REG_THRSHLD_MSB = 0x07,
REG_THRSHLD_LSB = 0x08,
REG_CH0_CFG = 0x09,
REG_CH0_OCAL_MSB = 0x0A,
REG_CH0_OCAL_LSB = 0x0B,
REG_CH0_GCAL_MSB = 0x0C,
REG_CH0_GCAL_LSB = 0x0D,
REG_CH1_CFG = 0x0E,
REG_CH1_OCAL_MSB = 0x0F,
REG_CH1_OCAL_LSB = 0x10,
REG_CH1_GCAL_MSB = 0x11,
REG_CH1_GCAL_LSB = 0x12,
REG_CH2_CFG = 0x13,
REG_CH2_OCAL_MSB= 0x14,
REG_CH2_OCAL_LSB= 0x15,
REG_CH2_GCAL_MSB= 0x16,
REG_CH2_GCAL_LSB= 0x17,
REG_CH3_CFG = 0x18,
REG_CH3_OCAL_MSB= 0x19,
REG_CH3_OCAL_LSB= 0x1A,
REG_CH3_GCAL_MSB= 0x1B,
REG_CH3_GCAL_LSB= 0x1C,
REG_CH4_CFG = 0x1D,
REG_CH4_OCAL_MSB= 0x1E,
REG_CH4_OCAL_LSB= 0x1F,
REG_CH4_GCAL_MSB= 0x20,
REG_CH4_GCAL_LSB= 0x21,
REG_CH5_CFG = 0x22,
REG_CH5_OCAL_MSB= 0x23,
REG_CH5_OCAL_LSB= 0x24,
REG_CH5_GCAL_MSB= 0x25,
REG_CH5_GCAL_LSB= 0x26,
REG_CH6_CFG = 0x27,
REG_CH6_OCAL_MSB= 0x28,
REG_CH6_OCAL_LSB= 0x29,
REG_CH6_GCAL_MSB= 0x2A,
REG_CH6_GCAL_LSB= 0x2B,
REG_CH7_CFG = 0x2C,
REG_CH7_OCAL_MSB= 0x2D,
REG_CH7_OCAL_LSB= 0x2E,
REG_CH7_GCAL_MSB= 0x2F,
REG_CH7_GCAL_LSB= 0x30,
REGMAP_CRC = 0x3E,
};
// Mask READ_REG
static constexpr uint16_t MASK_CMD_READ_REG_ADDRESS = 0x1F80;
static constexpr uint16_t MASK_CMD_READ_REG_BYTES = 0x007F;
// Mask Register STATUS
static constexpr uint16_t MASK_STATUS_LOCK = 0x8000;
static constexpr uint16_t MASK_STATUS_RESYNC = 0x4000;
static constexpr uint16_t MASK_STATUS_REGMAP = 0x2000;
static constexpr uint16_t MASK_STATUS_CRC_ERR = 0x1000;
static constexpr uint16_t MASK_STATUS_CRC_TYPE = 0x0800;
static constexpr uint16_t MASK_STATUS_RESET = 0x0400;
static constexpr uint16_t MASK_STATUS_WLENGTH = 0x0300;
static constexpr uint16_t MASK_STATUS_DRDY7 = 0x0080;
static constexpr uint16_t MASK_STATUS_DRDY6 = 0x0040;
static constexpr uint16_t MASK_STATUS_DRDY5 = 0x0020;
static constexpr uint16_t MASK_STATUS_DRDY4 = 0x0010;
static constexpr uint16_t MASK_STATUS_DRDY3 = 0x0008;
static constexpr uint16_t MASK_STATUS_DRDY2 = 0x0004;
static constexpr uint16_t MASK_STATUS_DRDY1 = 0x0002;
static constexpr uint16_t MASK_STATUS_DRDY0 = 0x0001;
// Mask Register MODE
static constexpr uint16_t MASK_MODE_REG_CRC_EN = 0x2000;
static constexpr uint16_t MASK_MODE_RX_CRC_EN = 0x1000;
static constexpr uint16_t MASK_MODE_CRC_TYPE = 0x0800;
static constexpr uint16_t MASK_MODE_RESET = 0x0400;
static constexpr uint16_t MASK_MODE_WLENGTH = 0x0300;
static constexpr uint16_t MASK_MODE_TIMEOUT = 0x0010;
static constexpr uint16_t MASK_MODE_DRDY_SEL = 0x000C;
static constexpr uint16_t MASK_MODE_DRDY_HiZ = 0x0002;
static constexpr uint16_t MASK_MODE_DRDY_FMT = 0x0001;
// Mask Register CLOCK
static constexpr uint16_t MASK_CLOCK_CH7_EN = 0x8000;
static constexpr uint16_t MASK_CLOCK_CH6_EN = 0x4000;
static constexpr uint16_t MASK_CLOCK_CH5_EN = 0x2000;
static constexpr uint16_t MASK_CLOCK_CH4_EN = 0x1000;
static constexpr uint16_t MASK_CLOCK_CH3_EN = 0x0800;
static constexpr uint16_t MASK_CLOCK_CH2_EN = 0x0400;
static constexpr uint16_t MASK_CLOCK_CH1_EN = 0x0200;
static constexpr uint16_t MASK_CLOCK_CH0_EN = 0x0100;
static constexpr uint16_t MASK_CLOCK_OSR = 0x001C;
static constexpr uint16_t MASK_CLOCK_PWR = 0x0003;
static constexpr uint32_t MASK_CLOCK_ALL_CH_DISABLE = 0x0000;
static constexpr uint32_t MASK_CLOCK_ALL_CH_ENABLE = 0xFF00;
// Mask Register GAIN
static constexpr uint16_t MASK_GAIN_PGAGAIN7 = 0x7000;
static constexpr uint16_t MASK_GAIN_PGAGAIN6 = 0x0700;
static constexpr uint16_t MASK_GAIN_PGAGAIN5 = 0x0070;
static constexpr uint16_t MASK_GAIN_PGAGAIN4 = 0x0007;
static constexpr uint16_t MASK_GAIN_PGAGAIN3 = 0x7000;
static constexpr uint16_t MASK_GAIN_PGAGAIN2 = 0x0700;
static constexpr uint16_t MASK_GAIN_PGAGAIN1 = 0x0070;
static constexpr uint16_t MASK_GAIN_PGAGAIN0 = 0x0007;
// Mask Register CFG
static constexpr uint16_t MASK_CFG_GC_DLY = 0x1E00;
static constexpr uint16_t MASK_CFG_GC_EN = 0x0100;
static constexpr uint16_t MASK_CFG_CD_ALLCH = 0x0080;
static constexpr uint16_t MASK_CFG_CD_NUM = 0x0070;
static constexpr uint16_t MASK_CFG_CD_LEN = 0x000E;
static constexpr uint16_t MASK_CFG_CD_EN = 0x0001;
// Mask Register THRSHLD_MSB - dummy, for completeness
static constexpr uint16_t MASK_THRSHLD_MSB_CD_TH_MSB = 0xFFFF;
// Mask Register THRSHLD_LSB
static constexpr uint16_t MASK_THRSHLD_LSB_CD_TH_LSB = 0xFF00;
static constexpr uint16_t MASK_THRSHLD_LSB_DCBLOCK = 0x000F;
// Mask Register CHX_CFG
static constexpr uint16_t MASK_CHX_CFG_PHASE = 0xFFC0;
static constexpr uint16_t MASK_CHX_CFG_DCBLKX_DIS = 0x0004;
static constexpr uint16_t MASK_CHX_CFG_MUX = 0x0003;
// Mask Register CHX_OCAL_MSB - dummy, for completeness
static constexpr uint16_t MASK_CHX_OCAL_MSB = 0xFFFF;
// Mask Register CHX_OCAL_LSB
static constexpr uint16_t MASK_CHX_OCAL_LSB = 0xFF00;
// Mask Register CHX_GCAL_MSB - dummy, for completeness
static constexpr uint16_t MASK_CHX_GCAL_MSB = 0xFFFF;
// Mask Register CHX_GCAL_LSB
static constexpr uint16_t MASK_CHX_GCAL_LSB = 0xFF00;
// --------------------------------------------------------------------
// Conversion modes
static constexpr uint16_t CONVERSION_MODE_CONT = 0;
static constexpr uint16_t CONVERSION_MODE_SINGLE = 1;
// Data Format
static constexpr uint16_t DATA_FORMAT_TWO_COMPLEMENT = 0;
static constexpr uint16_t DATA_FORMAT_BINARY = 1;
// Measure Mode
static constexpr uint8_t MEASURE_UNIPOLAR = 1;
static constexpr uint8_t MEASURE_BIPOLAR = 0;
// Clock Type
static constexpr uint8_t CLOCK_EXTERNAL = 1;
static constexpr uint8_t CLOCK_INTERNAL = 0;
// PGA Gain
// static constexpr uint16_t PGA_GAIN_1 = 0;
// static constexpr uint16_t PGA_GAIN_2 = 1;
// static constexpr uint16_t PGA_GAIN_4 = 2;
// static constexpr uint16_t PGA_GAIN_8 = 3;
// static constexpr uint16_t PGA_GAIN_16 = 4;
// static constexpr uint16_t PGA_GAIN_32 = 5;
// static constexpr uint16_t PGA_GAIN_64 = 6;
// static constexpr uint16_t PGA_GAIN_128 = 7;
// Input Filter
static constexpr uint16_t FILTER_SYNC = 0;
static constexpr uint16_t FILTER_FIR = 2;
static constexpr uint16_t FILTER_FIR_IIR = 3;
// Data Mode
static constexpr uint8_t DATA_MODE_24BITS = 0;
static constexpr uint8_t DATA_MODE_32BITS = 1;
// Data Rate
static constexpr uint8_t DATA_RATE_0 = 0;
static constexpr uint8_t DATA_RATE_1 = 1;
static constexpr uint8_t DATA_RATE_2 = 2;
static constexpr uint8_t DATA_RATE_3 = 3;
static constexpr uint8_t DATA_RATE_4 = 4;
static constexpr uint8_t DATA_RATE_5 = 5;
static constexpr uint8_t DATA_RATE_6 = 6;
static constexpr uint8_t DATA_RATE_7 = 7;
static constexpr uint8_t DATA_RATE_8 = 8;
static constexpr uint8_t DATA_RATE_9 = 9;
static constexpr uint8_t DATA_RATE_10 = 10;
static constexpr uint8_t DATA_RATE_11 = 11;
static constexpr uint8_t DATA_RATE_12 = 12;
static constexpr uint8_t DATA_RATE_13 = 13;
static constexpr uint8_t DATA_RATE_14 = 14;
static constexpr uint8_t DATA_RATE_15 = 15;
// Sync Mpdes
static constexpr uint16_t SYNC_CONTINUOUS = 1;
static constexpr uint16_t SYNC_PULSE = 0;
// DIO Config Mode
static constexpr uint8_t DIO_OUTPUT = 1;
static constexpr uint8_t DIO_INPUT = 0;
static constexpr uint8_t SPI_MASTER_DUMMY = 0xFF;
static constexpr uint16_t SPI_MASTER_DUMMY16 = 0xFFFF;
static constexpr uint32_t SPI_MASTER_DUMMY32 = 0xFFFFFFFF;
// end of from datasheet
class ADS131M08Sensor : public sensor::Sensor, public Component
{
};
@ -15,6 +431,28 @@ class ADS131M08Sensor : public sensor::Sensor, public Component
class ADS131M08Hub : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_8MHZ>
{
public:
// from datasheet pg. 93:
const int numFrameWords = 10; // Number of words in a full ADS131M08 SPI frame
unsigned long spiDummyWord[10 /*numFrameWords*/] = {
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000
}; // Dummy word frame to write ADC during ADC data reads
bool firstRead = true; // Flag to tell us if we are reading ADC data for the first time
signed long adcData; // Location where DMA will store ADC data in memory, length defined elsewhere
void txf_init();
bool adcRegisterWrite(unsigned short addrMask, unsigned short data, unsigned char adcWordLength);
void initialize_ads131m08_datasheet();
// end of from datasheet
bool setChannelPGA(uint8_t channel, uint8_t pga);
void setup() override;
void loop() override;
void set_drdy_pin(InternalGPIOPin *pin) { drdy_pin_ = pin; }
@ -22,6 +460,34 @@ class ADS131M08Hub : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_
void set_reference_voltage(float reference_voltage) { this->reference_voltage_ = reference_voltage; }
void dump_config() override;
// from tpcorrea
void begin(uint8_t clk_pin, uint8_t miso_pin, uint8_t mosi_pin, uint8_t cs_pin, uint8_t drdy_pin, uint8_t reset_pin);
int8_t isDataReadySoft(uint8_t channel);
bool isDataReady(void);
bool isResetStatus(void);
bool isLockSPI(void);
bool setDrdyFormat(uint8_t drdyFormat);
bool setDrdyStateWhenUnavailable(uint8_t drdyState);
bool setPowerMode(uint8_t powerMode);
bool setChannelEnable(uint8_t channel, uint16_t enable);
bool setChannelPGA(uint8_t channel, ADS131M08_PGA_GAIN pga);
ADS131M08_PGA_GAIN getChannelPGA(uint8_t channel);
void setGlobalChop(uint16_t global_chop);
void setGlobalChopDelay(uint16_t delay);
bool setInputChannelSelection(uint8_t channel, uint8_t input);
bool setChannelOffsetCalibration(uint8_t channel, int32_t offset);
bool setChannelGainCalibration(uint8_t channel, uint32_t gain);
bool setOsr(uint16_t osr);
void setFullScale(uint8_t channel, float scale);
float getFullScale(uint8_t channel);
void reset();
uint16_t getId();
uint16_t getModeReg();
uint16_t getClockReg();
uint16_t getCfgReg();
AdcOutput readAdcRaw(void);
AdcOutput readAdcFloat(void);
protected:
float reference_voltage_;
InternalGPIOPin *drdy_pin_;
@ -29,6 +495,8 @@ class ADS131M08Hub : public Component, public spi::SPIDevice<spi::BIT_ORDER_MSB_
volatile bool data_ready_{false};
static void isr(ADS131M08Hub *arg);
void read_data_();
void write_register(uint8_t reg, uint16_t value);
};
} // namespace ads131m08