This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1298: Inconsistent SPI readout of test signal from ADC

Part Number: ADS1298
Other Parts Discussed in Thread: ADS1296, ADS1294, , ADS1296R, , ADS1294R

Hi there,

Background
Following some changes made in this thread: https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1018492/ads1298-cannot-establish-spi-communications, we've made some progress with the SPI comms.

The voltage lines are stable now after tieing RESV1 to DGND, and we scoped the MOSI and MISO signals and they look ok.

However, we are seeing discrepancies in values for test signal on our design as compared to the dev kit.

The issue

We are trying to baseline the ADSx98 FE Rev C deg kit against our design which is almost identical with a few deviations.

We are attempting to perform an internally generated signal to read values from the internal registers. Below is a header file with more details of the register settings:

#ifndef ADS1298_H
#define ADS1298_H

#ifdef __cplusplus
extern "C" {
#endif


#include "../common.h"


typedef enum {
  // system commands
  ADS_CMND_WAKEUP    = 0x02,   // wake-up from standby mode
  ADS_CMND_STANDBY   = 0x04,   // enter standby mode
  ADS_CMND_RESET     = 0x06,   // reset the device registers
  ADS_CMND_START     = 0x08,   // start/restart (synchronize) conversions
  ADS_CMND_STOP      = 0x0A,   // stop conversion
  // data read commands
  ADS_CMND_RDATAC    = 0x10,   // enable Read Data Continuous mode. 
                               // - this mode is the default mode at power-up.
  ADS_CMND_SDATAC   = 0x11,   // stop Read Data Continuously mode
  ADS_CMND_RDATA    = 0x12,   // read data by command; supports multiple read back.
  // register read/write commands
  ADS_CMND_RREG     = 0x20,   // read n nnnn registers starting at address r rrrr
                               //  - first byte 001r rrrr (2xh)(2) - second byte 000n nnnn(2)
  ADS_CMND_WREG     = 0x40    // write n nnnn registers starting at address r rrrr
                               //  - first byte 010r rrrr (2xh)(2) - second byte 000n nnnn(2)
} ADS1298Command_t;


typedef enum {
  // device settings
  ADS_REG_ID        = 0x00,   // device ID information
  // global settings
  ADS_REG_CONFIG1     = 0x01,
  ADS_REG_CONFIG2     = 0x02,
  ADS_REG_CONFIG3     = 0x03,
  ADS_REG_LOFF        = 0x04,
  // channel specific settings
  ADS_REG_CH1SET      = 0x05,
  ADS_REG_CH2SET      = 0x06,
  ADS_REG_CH3SET      = 0x07,
  ADS_REG_CH4SET      = 0x08,
  ADS_REG_CH5SET      = 0x09,
  ADS_REG_CH6SET      = 0x0A,
  ADS_REG_CH7SET      = 0x0B,
  ADS_REG_CH8SET      = 0x0C,
  ADS_REG_RLD_SENSP   = 0x0D,
  ADS_REG_RLD_SENSN   = 0x0E,
  ADS_REG_LOFF_SENSP  = 0x0F,
  ADS_REG_LOFF_SENSN  = 0x10,
  ADS_REG_LOFF_FLIP   = 0x11,
  // lead off status
  ADS_REG_LOFF_STATP  = 0x12,
  ADS_REG_LOFF_STATN  = 0x13,
  // others
  ADS_REG_GPIO        = 0x14,
  ADS_REG_PACE        = 0x15,
  ADS_REG_RESP        = 0x16,
  ADS_REG_CONFIG4     = 0x17,
  ADS_REG_WCT1        = 0x18,
  ADS_REG_WCT2        = 0x19

} ADS1298Register_t;


typedef enum {
  // ID control register bits
  DEV_ID7 = 0x80,
  DEV_ID6 = 0x40,
  DEV_ID5 = 0x20,
  DEV_ID2 = 0x04,
  DEV_ID1 = 0x02,
  DEV_ID0 = 0x01,

  ID_ADS129x = DEV_ID7,
  ID_ADS129xR = (DEV_ID7 | DEV_ID6),

  ID_4CHAN = 0,
  ID_6CHAN = DEV_ID0,
  ID_8CHAN = DEV_ID1,

  ID_ADS1294 = (ID_ADS129x | ID_4CHAN),
  ID_ADS1296 = (ID_ADS129x | ID_6CHAN),
  ID_ADS1298 = (ID_ADS129x | ID_8CHAN),
  ID_ADS1294R = (ID_ADS129xR | ID_4CHAN),
  ID_ADS1296R = (ID_ADS129xR | ID_6CHAN),
  ID_ADS1298R = (ID_ADS129xR | ID_8CHAN),

  ID_const = ID_ADS1298

} ID_bits_t;


typedef enum {
  // config1 register bits
  HR = 0x80,
  DAISY_EN = 0x40,
  CLK_EN = 0x20,
  DR2 = 0x04,
  DR1 = 0x02,
  DR0 = 0x01,

  // ADS1298
  HIGH_RES_32k_SPS  = (HR),
  HIGH_RES_16k_SPS  = (HR | DR0),
  HIGH_RES_8k_SPS   = (HR | DR1),
  HIGH_RES_4k_SPS   = (HR | DR1 | DR0),
  HIGH_RES_2k_SPS   = (HR | DR2),
  HIGH_RES_1k_SPS   = (HR | DR2 | DR0),
  HIGH_RES_500_SPS  = (HR | DR2 | DR1),

  CONFIG1_const = HIGH_RES_500_SPS

} CONFIG1_bits_t;


typedef enum {
  // config2 register bits
  WCT_CHOP = 0x20,
  INT_TEST = 0x10,
  TEST_AMP = 0x04,
  TEST_FREQ1 = 0x02,
  TEST_FREQ0 = 0x01,

  // ADS1298
  INT_TEST_4HZ = INT_TEST,
  INT_TEST_8HZ = (INT_TEST | TEST_FREQ0),
  INT_TEST_DC = (INT_TEST | TEST_FREQ1 | TEST_FREQ0),  

  CONFIG2_const = INT_TEST_DC

} CONFIG2_bits_t;


typedef enum {
  // config3 register bits
  PD_REFBUF = 0x80,
  Bit7 = 0x40,
  VREF_4V = 0x20,
  RLD_MEAS = 0x10,
  RLDREF_INT = 0x08,
  PD_RLD = 0x04,
  RLD_LOFF_SENS = 0x02,
  RLD_STAT = 0x01,

  // ADS1298
  CONFIG3_const = PD_REFBUF | RLD_MEAS | RLDREF_INT | PD_RLD | Bit7

} CONFIG3_bits_t;


typedef enum {
  // Lead-off control register bits
  COMP_TH2 = 0x80,
  COMP_TH1 = 0x40,
  COMP_TH0 = 0x20,
  VLEAD_OFF_EN = 0x10,
  ILEAD_OFF1 = 0x08,
  ILEAD_OFF0 = 0x04,
  FLEAD_OFF1 = 0x02,
  FLEAD_OFF0 = 0x01,

  // ADS1298
  LOFF_const = FLEAD_OFF1 | FLEAD_OFF0

} LOFF_bits_t;


typedef enum {
  // n-th channel setting register bits
  PDn = 0x80,
  GAINn2 = 0x40,
  GAINn1 = 0x20,
  GAINn0 = 0x10,
  MUXn2 = 0x04,
  MUXn1 = 0x02,
  MUXn0 = 0x01,

  // ADS1298
  ADS1298_GAIN_1X = GAINn0,
  ADS1298_GAIN_2X = GAINn1,
  ADS1298_GAIN_3X = (GAINn1 | GAINn0),
  ADS1298_GAIN_4X = GAINn2,
  ADS1298_GAIN_6X = 0x00,
  ADS1298_GAIN_8X = (GAINn2 | GAINn0),
  ADS1298_GAIN_12X = (GAINn2 | GAINn1),
  
  ELECTRODE_INPUT = 0x00,
  SHORTED = MUXn0,
  RLD_INPUT = MUXn1,
  MVDD = (MUXn1 | MUXn0),
  TEMP = MUXn2,
  TEST_SIGNAL = (MUXn2 | MUXn0),
  RLD_DRP = (MUXn2 | MUXn1),
  RLD_DRN = (MUXn2 | MUXn1 | MUXn0),

  //CHnSET_const = ELECTRODE_INPUT
  CHnSET_const = MVDD | ADS1298_GAIN_1X

} CHnSET_bits_t;


typedef enum {
  // RLD positive signal derivation register bits
  RLD8P = 0x80,
  RLD7P = 0x40,
  RLD6P = 0x20,
  RLD5P = 0x10,
  RLD4P = 0x08,
  RLD3P = 0x04,
  RLD2P = 0x02,
  RLD1P = 0x01,

  // ADS1298
  RLD_SENSP_const = 0x00

} RLD_SENSP_bits_t;


typedef enum {
  // RLD negative signal derivation register bits
  RLD8N = 0x80,
  RLD7N = 0x40,
  RLD6N = 0x20,
  RLD5N = 0x10,
  RLD4N = 0x08,
  RLD3N = 0x04,
  RLD2N = 0x02,
  RLD1N = 0x01,

  // ADS1298
  RLD_SENSN_const = 0x00

} RLD_SENSN_bits_t;


typedef enum {
  // positive signal lead-off detection register bits
  LOFF8P = 0x80,
  LOFF7P = 0x40,
  LOFF6P = 0x20,
  LOFF5P = 0x10,
  LOFF4P = 0x08,
  LOFF3P = 0x04,
  LOFF2P = 0x02,
  LOFF1P = 0x01,

  // ADS1298
  LOFF_SENSP_const = 0xFF

} LOFF_SENSP_bits_t;


typedef enum {
  // negative signal lead-off detection register bits
  LOFF8N = 0x80,
  LOFF7N = 0x40,
  LOFF6N = 0x20,
  LOFF5N = 0x10,
  LOFF4N = 0x08,
  LOFF3N = 0x04,
  LOFF2N = 0x02,
  LOFF1N = 0x01,

  // ADS1298
  LOFF_SENSN_const = 0x02

} LOFF_SENSN_bits_t;


typedef enum {
  // lead-off flip register bits
  LOFF_FLIP8 = 0x80,
  LOFF_FLIP7 = 0x40,
  LOFF_FLIP6 = 0x20,
  LOFF_FLIP5 = 0x10,
  LOFF_FLIP4 = 0x08,
  LOFF_FLIP3 = 0x04,
  LOFF_FLIP2 = 0x02,
  LOFF_FLIP1 = 0x01,

  // ADS1298
  LOFF_FLIP_const = 0x00

} LOFF_FLIP_bits_t;


typedef enum {
  // lead-off positive signal status register bits
  IN8P_OFF = 0x80,
  IN7P_OFF = 0x40,
  IN6P_OFF = 0x20,
  IN5P_OFF = 0x10,
  IN4P_OFF = 0x08,
  IN3P_OFF = 0x04,
  IN2P_OFF = 0x02,
  IN1P_OFF = 0x01,

  // ADS1298
  LOFF_STATP_const = 0xFE

} LOFF_STATP_bits_t;


typedef enum {
  // lead-off negative signal status register bits
  IN8N_OFF = 0x80,
  IN7N_OFF = 0x40,
  IN6N_OFF = 0x20,
  IN5N_OFF = 0x10,
  IN4N_OFF = 0x08,
  IN3N_OFF = 0x04,
  IN2N_OFF = 0x02,
  IN1N_OFF = 0x01,

  // ADS1298
  LOFF_STATN_const = 0x06

} LOFF_STATN_bits_t;


typedef enum {
  // general-purpose I/O register bits
  GPIOD4 = 0x80,
  GPIOD3 = 0x40,
  GPIOD2 = 0x20,
  GPIOD1 = 0x10,
  GPIOC4 = 0x08,
  GPIOC3 = 0x04,
  GPIOC2 = 0x02,
  GPIOC1 = 0x01,

  // ADS1298
  GPIO_const = 0x00

} GPIO_bits_t;


typedef enum {
  // pace detect register bits
  PACEE1 = 0x10,
  PACEE0 = 0x08,
  PACEO1 = 0x04,
  PACEO0 = 0x02,
  PD_PACE = 0x01,

  PACEE_CHAN2 = 0x00,
  PACEE_CHAN4 = PACEE0,
  PACEE_CHAN6 = PACEE1,
  PACEE_CHAN8 = (PACEE1 | PACEE0),

  PACEO_CHAN1 = 0x00,
  PACEO_CHAN3 = PACEE0,
  PACEO_CHAN5 = PACEE1,
  PACEO_CHAN7 = (PACEE1 | PACEE0),

  // ADS1298
  PACE_const = 0x00

} PACE_bits_t;


typedef enum {
  // respiration control register bits
  RESP_DEMOD_EN1 = 0x80,
  RESP_MOD_EN1 = 0x40,
  RESP_PH2 = 0x10,
  RESP_PH1 = 0x08,
  RESP_PH0 = 0x04,
  RESP_CTRL1 = 0x02,
  RESP_CTRL0 = 0x01,

  RESP_PH_22_5 = 0x00,
  RESP_PH_45 = RESP_PH0,
  RESP_PH_67_5 = RESP_PH1,
  RESP_PH_90 = (RESP_PH1 | RESP_PH0),
  RESP_PH_112_5 = RESP_PH2,
  RESP_PH_135 = (RESP_PH2 | RESP_PH0),
  RESP_PH_157_5 = (RESP_PH2 | RESP_PH1),

  RESP_NONE = 0x00,
  RESP_EXT = RESP_CTRL0,
  RESP_INT_SIG_INT = RESP_CTRL1,
  RESP_INT_SIG_EXT = (RESP_CTRL1 | RESP_CTRL0),

  // ADS1298 (not support)
  RESP_const = 0x00

} RESP_bits_t;


typedef enum {
  // configuration register 4 bits
  RESP_FREQ2 = 0x80,
  RESP_FREQ1 = 0x40,
  RESP_FREQ0 = 0x20,
  SINGLE_SHOT = 0x08,
  WCT_TO_RLD = 0x04,
  PD_LOFF_COMP = 0x02,

  RESP_FREQ_64k_Hz = 0x00,
  RESP_FREQ_32k_Hz = RESP_FREQ0,
  RESP_FREQ_16k_Hz = RESP_FREQ1,
  RESP_FREQ_8k_Hz = (RESP_FREQ1 | RESP_FREQ0),
  RESP_FREQ_4k_Hz = RESP_FREQ2,
  RESP_FREQ_2k_Hz = (RESP_FREQ2 | RESP_FREQ0),
  RESP_FREQ_1k_Hz = (RESP_FREQ2 | RESP_FREQ1),
  RESP_FREQ_500_Hz = (RESP_FREQ2 | RESP_FREQ1 | RESP_FREQ0),

  // ADS1298
  CONFIG4_const = PD_LOFF_COMP

} CONFIG4_bits_t;


typedef enum {
  // WCT1: wilson central terminal and augmented lead control register bits
  aVF_CH6 = 0x80,
  aVL_CH5 = 0x40,
  aVR_CH7 = 0x20,
  avR_CH4 = 0x10,
  PD_WCTA = 0x08,
  WCTA2 = 0x04,
  WCTA1 = 0x02,
  WCTA0 = 0x01,

  WCTA_CH1P = 0x00,
  WCTA_CH1N = WCTA0,
  WCTA_CH2P = WCTA1,
  WCTA_CH2N = (WCTA1 | WCTA0),
  WCTA_CH3P = WCTA2,
  WCTA_CH3N = (WCTA2 | WCTA0),
  WCTA_CH4P = (WCTA2 | WCTA1),
  WCTA_CH4N = (WCTA2 | WCTA1 | WCTA0),

  // ADS1298
  WCT1_const = PD_WCTA | WCTA1

} WCT1_bits_t;


typedef enum {
  // WCT2: wilson central terminal control register bits
  PD_WCTC = 0x80,
  PD_WCTB = 0x40,
  WCTB2 = 0x20,
  WCTB1 = 0x10,
  WCTB0 = 0x08,
  WCTC2 = 0x04,
  WCTC1 = 0x02,
  WCTC0 = 0x01,

  WCTB_CH1P = 0x00,
  WCTB_CH1N = WCTB0,
  WCTB_CH2P = WCTB1,
  WCTB_CH2N = (WCTB1 | WCTB0),
  WCTB_CH3P = WCTB2,
  WCTB_CH3N = (WCTB2 | WCTB0),
  WCTB_CH4P = (WCTB2 | WCTB1),
  WCTB_CH4N = (WCTB2 | WCTB1 | WCTB0),

  WCTC_CH1P = 0x00,
  WCTC_CH1N = WCTC0,
  WCTC_CH2P = WCTC1,
  WCTC_CH2N = (WCTC1 | WCTC0),
  WCTC_CH3P = WCTC2,
  WCTC_CH3N = (WCTC2 | WCTC0),
  WCTC_CH4P = (WCTC2 | WCTC1),
  WCTC_CH4N = (WCTC2 | WCTC1 | WCTC0),

  // ADS1298
  WCT2_const = PD_WCTC | PD_WCTB | WCTB_CH3P | WCTC_CH2N

} WCT2_bits_t;



#ifdef __cplusplus
}
#endif

#endif // ADS1298_H

The issue is that there is a deviation in voltage measurements between the two setups in general. Below is a summary table of voltages measured between the two setups:

Channel No. ADS1298 DevKit & GUI SW (mV) Custom Design (mV)
1 -1.588392 -1.237154154
2 -0.723791122 -1.197433614
3 -1.223898 -1.365900203
4 -1.398134 -1.233053354
5 -1.174879 -0.781917665
6 -1.245832 350.5889834
7 -1.276207 -79.24800864
8 -0.989675522 -76.67232474

There also seems to be a large fluctuation in values read in our design when measuring the test data on channels 6, 7 and 8. All voltage measurements on all channels read on the dev kit via GUI are stable. Are there any hardware connection dependencies to perform this test?

Looking forward to some suggestions and/or troubleshooting steps.

Thank you in advance.

Best regards,

Eric

  • Hi Eric,

    There should not be hardware connection dependency for using the internal test signal. Can you verify all the channels are operating normally with the input-short test by setting MUXn[2:0] to 0b001? What does the ADC output waveform look like for CH6 to CH8 when using the internal test signal?

    Thanks

    -TC