Post Go back to editing

issue with SPI COMMUNICATION WITH AD7173-8, controller ESP32

Category: Hardware
Product Number: AD7173-8

Hello everyone,

I am writing a driver to interface AD7173-8 to ESP32 Microcontroller. when I try to read the reset value of a particular register, it is giving different value.

here are the register reset values I tried to read 

the status register reset value as per the datasheet is 0x80. but the reset value I read is 0x81.

the ADCMODE  register reset value as per the datasheet is 0x2000. but the reset value I read is 0x201.

the IFMODE  register reset value as per the datasheet is 0x0000. but the reset value I read is 0x01.

please help to tackle this issue.

thank you



Moved & tagged
[edited by: emassa at 4:03 PM (GMT -5) on 2 Mar 2023]

Top Replies

    •  Analog Employees 
    •  Super User 
    in reply to SRISUS +1 verified

    HI  ,

    The ADC should be able to read +-2.5V. Note that the absolute input voltage of the ADC is AVSS-0.05 to AVDD1+0.05 for disabled input buffers and AVSS to AVDD1-1.1 for buffers enabled and ensure…

Parents
  • Hi  ,

    Is the reset value of the ADCMODE register really 0x201 and not 0x2001? 

    Can you provide a digital interface scope shot for this? 

    You may also want to refer to Digital Interface FAQ - Sigma Delta ADC - Q&A - Precision ADCs - EngineerZone (analog.com). The number 8 FAQ might be able to answer this query or maybe help you understand the data you are reading. Thank you.

    Regards,

    Rod

  • Hi RAdante,

    thanks for your response, 

    as per the datasheet ADCMODE reset value is 0x2000. but when I read that register it is giving 0x201

    here correct reset value is 0x2000

    so, what could be the issue?

    thanks & regards

    Srinivasa

  • Hi,

    Can you provide a digital interface scope shot for this? So that we can better understand the output you are reading. Thanks.

    Regards,

    Rod

  • Hi RAdante,

    sorry for the late response

    I have changed the frequency of the SPI protocol and now it reads the register reset value properly.

    I have configured all the required registers but conversion not happening.

    I am getting output as 000. here I have attached the code below,

    please let me know if anything is configured wrong or if any other issue

    -----------------------------------------------------------------------------------
    main code
    -----------------------------------------------------------------------------------
    
    #include "AD7173_8.h"
    
    void setup() {
    	/* initiate serial communication */
    	Serial.begin(230400);
    
    	/* initialize SPI connection to the ADC */
    	AD7173.init();
    
    	/* sync the ADC */
    	AD7173.sync();
    
    	/* reset the ADC registers to default */
    	AD7173.reset();
    
    	/* check if the ID register of the ADC is valid */
    	if (AD7173.is_valid_id()) Serial.println("AD7173 ID is valid");
    	else Serial.println("AD7173 ID is invalid");
    
    	/* set ADC input channel configuration */
    	/* enable channel 0 and channel 1 and connect each to 2 analog inputs for bipolar input */
    	/* CH0 - CH15 */
    	/* true/false to enable/disable channel */
    	/* SETUP0 - SETUP7 */
    	/* AIN0 - AIN16 */
    Serial.println("nexrt process");
    	AD7173.set_channel_config(CH3, true, SETUP0, AIN3, AIN2);
    	//AD7173.set_channel_config(CH1, true, SETUP0, AIN2, AIN3);
    
    	/* set the ADC SETUP0 coding mode to BIPLOAR output */
    	/* SETUP0 - SETUP7 */
    	/* BIPOLAR, UNIPOLAR */
    	/* AIN_BUF_DISABLE, AIN_BUF_ENABLE */
    	/* REF_EXT, REF_AIN, REF_INT, REF_PWR */
    	AD7173.set_setup_config(SETUP0, BIPOLAR, AIN_BUF_DISABLE, REF_EXT);
    
    	/* set ADC OFFSET0 offset value */
    	/* OFFSET0 - OFFSET7 */
    	AD7173.set_offset_config(OFFSET0, 0);
    
    	/* set the ADC FILTER0 ac_rejection to false and samplingrate to 1007 Hz */
    	/* FILTER0 - FILTER7 */
    	/* SPS_1, SPS_2, SPS_5, SPS_10, SPS_16, SPS_20, SPS_49, SPS_59, SPS_100, SPS_200 */
    	/* SPS_381, SPS_503, SPS_1007, SPS_2597, SPS_5208, SPS_10417, SPS_15625, SPS_31250 */
    	AD7173.set_filter_config(FILTER0,  SPS_5);
    
    	/* set the ADC data and clock mode */
    	/* CONTINUOUS_CONVERSION_MODE, SINGLE_CONVERSION_MODE */
    	/* in SINGLE_CONVERSION_MODE after all setup channels are sampled the ADC goes into STANDBY_MODE */
    	/* to exit STANDBY_MODE use this same function to go into CONTINUOUS or SINGLE_CONVERSION_MODE */
    	/* INTERNAL_CLOCK, INTERNAL_CLOCK_OUTPUT, EXTERNAL_CLOCK_INPUT, EXTERNAL_CRYSTAL */
    	/* REF_DISABLE, REF_ENABLE */
    	AD7173.set_adc_mode_config(CONTINUOUS_CONVERSION_MODE, INTERNAL_CLOCK, REF_DISABLE);
    
    	/* enable/disable CONTINUOUS_READ_MODE and appending STATUS register to data */
    	/* to exit CONTINUOUS_READ_MODE use AD7173.reset(); */
    	/* AD7173.reset(); returns all registers to default state, so everything has to be setup again */
    	/* true / false to enable / disable appending status register to data, 4th byte */
    	AD7173.set_interface_mode_config(false, true);
    Serial.println("nexrt process started");
    	/* wait for ADC */
    	delay(10);
    }
    
    /* ADC conversion data and STATUS register */
    byte data[4];
    
    void loop() {
    	/* when ADC conversion is finished */
    	if (DATA_READY) {
    		/* get ADC conversion result */
        Serial.println("DATA READY");
    		AD7173.get_data(data);
    
    		/* send result via serial */
    		Serial.print(data[0], HEX);
    		Serial.print(data[1], HEX);
    		Serial.println(data[2], HEX);
    		Serial.println(data[3], HEX);
    		delay(10);
    	}
    else
    {
         Serial.println("DATA not READY");
      
    }  
    		delay(1000);
    
    
    }
    
    -----------------------------------------------------------------------------------------------------------
    AD7173_8.CPP
    -----------------------------------------------------------------------------------------------------------
    #include "AD7173_8.h"
    
    AD7173Class AD7173;
    
    void AD7173Class::init() {
    	/* initiate SPI communication */
    	SPI.begin();
    	/* use SPI mode 3 */
      SPI.setFrequency(5000000);
    	SPI.setDataMode(SPI_MODE3);
    	/* allow the LDOs to power up */
    	delay(10);
    }
    
    void AD7173Class::reset() {
    	/* sending at least 64 high bits returns ADC to default state */
    	for (int i = 0; i < 8; i++) {
    		SPI.transfer(0xFF);
    	}
    	/* allow the LDOs to power up */
    	delay(10);
    }
    
    void AD7173Class::sync() {
    	/* toggle the chip select */
    	digitalWrite(SS, HIGH);
    	delay(10);
    	digitalWrite(SS, LOW);
    	/* allow the LDOs to power up */
    	delay(10);
    }
    
    void AD7173Class::print_byte(byte value) {
    	char format[10];
    	sprintf(format, "0x%.2X ", value);
    	Serial.print(format);
    }
    
    int AD7173Class::set_register(adc7173_register_t reg, byte *value, int value_len) {
    	/* send communication register id 0x00 */
      digitalWrite(SS, LOW);
    	SPI.transfer(0x00);
    	/* send write command to the desired register 0x00 - 0xFF */
    	SPI.transfer(0x00 | reg);
    	/* send the desired amount of bytes */
    	for (int i = 0; i < value_len; i++) {
    		SPI.transfer(value[i]);
    	}
      digitalWrite(SS, HIGH);
    	/* when debug enabled */
    	if (DEBUG_ENABLED) {
    		Serial.print("set_register: set [ ");
    		for (int i = 0; i < value_len; i++) {
    			this->print_byte(value[i]);
    		}
    		Serial.print("] to reg [ ");
    		this->print_byte(reg);
    		Serial.println("]");
    	}
    	/* TODO: find out correct delay */
    	delay(READ_WRITE_DELAY);
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::get_register(adc7173_register_t reg, byte *value, int value_len) {
    	/* send communication register id 0x00 */
       digitalWrite(SS, LOW);
    	SPI.transfer(0x00);
    	/* send read command to the desired register 0x00 - 0xFF */
    	SPI.transfer(0x40 | reg);
    	/* receive the desired amount of bytes */
    	for (int i = 0; i < value_len; i++) {
    		value[i] = SPI.transfer(0x00);
    	}
      digitalWrite(SS, HIGH);
    	/* when debug enabled */
    	if (DEBUG_ENABLED) {
    		Serial.print("get_register: got [ ");
    		for (int i = 0; i < value_len; i++) {
    			this->print_byte(value[i]);
    		}
    		Serial.print("] from reg [ ");
    		this->print_byte(reg);
    		Serial.println(" ]");
    	}
    	/* TODO: find out correct delay */
    	delay(READ_WRITE_DELAY);
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::get_current_data_channel(adc7173_register_t &channel) {
    	/* Address: 0x00, Reset: 0x80, Name: STATUS */
    
    	/* get ADC status register */
    	byte value[1];
    	this->get_register(STATUS_REG, value, 1);
    
    	/* assign to return channel register value */
    	channel = (adc7173_register_t) (value[0] & 0x0F);
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::set_adc_mode_config(data_mode_t data_mode, clock_mode_t clock_mode, ref_mode_t ref_mode) {
    	/* Address: 0x01, Reset: 0x2000, Name: ADCMODE */
    
    	/* prepare the configuration value */
    	/* REF_EN [15], RESERVED [14], SING_CYC [13], RESERVED [12:11], DELAY [10:8], RESERVED [7], MODE [6:4], CLOCKSEL [3:2], RESERED [1:0] */
    	byte value[2] = {0x00, 0x00};
    	value[1] = (data_mode << 4) | (clock_mode << 2);
    	value[0] = (ref_mode << 7)|(1<<5);
    
    	/* update the configuration value */
    	this->set_register(ADCMODE_REG, value, 2);
    
    	/* verify the updated configuration value */
    	this->get_register(ADCMODE_REG, value, 2);
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::set_interface_mode_config(bool continuous_read, bool append_status_reg) {
    	/* Address: 0x02, Reset: 0x0000, Name: IFMODE */
    
    	/* prepare the configuration value */
    	/* RESERVED [15:13], ALT_SYNC [12], IOSTRENGTH [11], HIDE_DELAY [10], RESERVED [9], DOUT_RESET [8], CONTREAD [7], DATA_STAT [6], REG_CHECK [5], RESERVED [4], CRC_EN [3:2], RESERVED [1], WL16 [0] */
    	byte value[2] = {0x00, 0x00};
    	value[1] = (continuous_read << 7) | (append_status_reg << 6);
    
    	/* update the configuration value */
    	this->set_register(IFMODE_REG, value, 2);
    
    	/* verify the updated configuration value */
    	this->get_register(IFMODE_REG, value, 2);
    
    	/* when continuous read mode */
    	if (continuous_read) {
    		/* update the data mode */
    		this->m_data_mode = CONTINUOUS_READ_MODE;
    	}
    
    	/* enable or disable appending status reg to data */
    	this->append_status_reg = append_status_reg;
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::get_data(byte *value) {
    	/* Address: 0x04, Reset: 0x000000, Name: DATA */
     digitalWrite(SS, LOW);
    	/* when not in continuous read mode, send the read command */
    	if (this->m_data_mode != CONTINUOUS_READ_MODE) {
    		/* send communication register id 0x00 */
    		SPI.transfer(0x00);
    		/* send read command 0x40 to the data register 0x04 */
    		SPI.transfer(0x40 | DATA_REG);
    	}
    	/* get the ADC conversion result (24 bits) */
    	value[0] = SPI.transfer(0x00);
    	value[1] = SPI.transfer(0x00);
    	value[2] = SPI.transfer(0x00);
    	/* when status register appending is enabled */
    	if (this->append_status_reg) {
    		value[3] = SPI.transfer(0x00);
    	}
    	// digitalWrite(SS, HIGH);
    	/* when debug enabled */
    	if (DEBUG_ENABLED) {
    		Serial.print("get_data: read [ ");
    		this->print_byte(value[0]);
    		this->print_byte(value[1]);
    		this->print_byte(value[2]);
    		/* when status register appending is enabled */
    		if (this->append_status_reg) {
    			this->print_byte(value[3]);;
    		}
    		Serial.println("] from reg [ 0x04 ]");
    	}
    	/* return error code */
    	return 0;
    }
    
    bool AD7173Class::is_valid_id() {
    	/* Address: 0x07, Reset: 0x30DX, Name: ID */
    
    	/* get the ADC device ID */
    	byte id[2];
    	this->get_register(ID_REG, id, 2);
    	/* check if the id matches 0x30DX, where X is don't care */
    	//id[1] &= 0xF0;
    	bool valid_id = id[0] == 0x30 && id[1] == 0xD5;
    Serial.print("init: ADC device ID is invalid :( [ ");
          	Serial.print(id[0],HEX);
            	Serial.print(id[1],HEX);
    	/* when debug enabled */
    	if (DEBUG_ENABLED) {
    		if (valid_id) {
    			Serial.println("init: ADC device ID is valid :)");
    		} else {
    			Serial.print("init: ADC device ID is invalid :( [ ");
          	Serial.print(id[0]);
            	Serial.print(id[1]);
    			this->print_byte(id[0]);
    			this->print_byte(id[1]);
    			Serial.print(" ]");
    			Serial.println();
    		}
    	}
    	/* return validity of ADC device ID */
    	return valid_id;
    }
    
    int AD7173Class::set_channel_config(adc7173_register_t channel, bool enable, adc7173_register_t setup, analog_input_t ain_pos, analog_input_t ain_neg) {
    	/* Address: 0x10, Reset: 0x8001, Name: CH0 */
    	/* Address Range: 0x11 to 0x1F, Reset: 0x0001, Name: CH1 to CH15 */
    
    	/* prepare the configuration value */
    	/* CH_EN0 [15], SETUP_SEL0 [14:12], RESERVED [11:10], AINPOS0 [9:5], AINNEG0 [4:0] */
    	byte value[2] = {0x00, 0x00};
    	value[0] = (enable << 7) | (setup << 4) | (ain_pos >> 3);
    	value[1] = (ain_pos << 5) | ain_neg;
    
    	/* update the configuration value */
    	this->set_register(channel, value, 2);
    
    	/* verify the updated configuration value */
    	this->get_register(channel, value, 2);
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::set_setup_config(adc7173_register_t setup, coding_mode_t coding_mode, ain_buf_mode_t ain_buf_mode, setup_ref_source_t setup_ref_source) {
    	/* Address Range: 0x20 to 0x27, Reset: 0x1000, Name: SETUPCON0 to SETUPCON7 */
    
    	/* prepare the configuration value */
    	byte value[2] = {0x00, 0x00};
    	value[0] = (coding_mode << 4) | ain_buf_mode;
    	value[1] = (setup_ref_source << 4);
    
    	/* update the configuration value */
    	this->set_register(setup, value, 2);
    
    	/* verify the updated configuration value */
    	this->get_register(setup, value, 2);
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::set_filter_config(adc7173_register_t filter, data_rate_t data_rate) {
    	/* Address Range: 0x28 to 0x2F, Reset: 0x0000, Name: FILTCON0 to FILTCON7 */
    
    	/* prepare the configuration value */
    	byte value[2] = {0x00, 0x00};
    	/* SINC3_MAP0 [15], RESERVED [14:12], ENHFILTEN0 [11], ENHFILT0 [10:8], RESERVED [7], ORDER0 [6:5], ORD0 [4:0] */
    	value[1] = data_rate;
    
    	/* update the configuration value */
    	this->set_register(filter, value, 2);
    
    	/* verify the updated configuration value */
    	this->get_register(filter, value, 2);
    
    	/* return error code */
    	return 0;
    }
    
    int AD7173Class::set_offset_config(adc7173_register_t offset, uint32_t offset_value) {
    	/* Address Range: 0x30 to 0x37, Reset: 0x0000, Name: OFFSET0 to OFFSET7 */
    
    	/* add the default offset value */
    	offset_value += 8388608;
    	/* prepare the configuration value */
    	byte value[3] = {0x00, 0x00, 0x00};
    	value[0] = offset_value >> 16;
    	value[1] = offset_value >> 8;
    	value[2] = offset_value;
    
    	/* update the configuration value */
    	this->set_register(offset, value, 3);
    
    	/* verify the updated configuration value */
    	this->get_register(offset, value, 3);
    
    	/* return error code */
    	return 0;
    }
    
    
    
    
    ----------------------------------------------------------------------------------------------------------------------------------
    AD7173_8.h file
    ----------------------------------------------------------------------------------------------------------------------------------
    #ifndef _AD7173_H_INCLUDED
    #define _AD7173_H_INCLUDED
    
    #if ARDUINO >= 100
    #include "Arduino.h"
    #else
    #include "WProgram.h"
    #endif
    
    #include "SPI.h"
    
    /* enable or disable debug */
    #define DEBUG_ENABLED 0
    
    /* delay for reading and writing registers  */
    #define READ_WRITE_DELAY 1
    
    /* registers */
    typedef enum {
    	/* other ADC registers */
    	COMMS_REG = 0x00,
    	STATUS_REG = 0x00,
    	ADCMODE_REG = 0x01,
    	IFMODE_REG = 0x02,
    	REGCHECK_REG = 0x03,
    	DATA_REG = 0x04,
    	GPIOCON_REG = 0x06,
    	ID_REG = 0x07,
    	/* ADC channel registers */
    	CH0 = 0x10,
    	CH1 = 0x11,
    	CH2 = 0x12,
    	CH3 = 0x13,
    	CH4 = 0x14,
    	CH5 = 0x15,
    	CH6 = 0x16,
    	CH7 = 0x17,
    	CH8 = 0x18,
    	CH9 = 0x19,
    	CH10 = 0x1A,
    	CH11 = 0x1B,
    	CH12 = 0x1C,
    	CH13 = 0x1D,
    	CH14 = 0x1E,
    	CH15 = 0x1F,
    	/* ADC setup config register */
    	SETUP0 = 0x20,
    	SETUP1 = 0x21,
    	SETUP2 = 0x22,
    	SETUP3 = 0x23,
    	SETUP4 = 0x24,
    	SETUP5 = 0x25,
    	SETUP6 = 0x26,
    	SETUP7 = 0x27,
    	/* ADC filter config registers */
    	FILTER0 = 0x28,
    	FILTER1 = 0x29,
    	FILTER2 = 0x2A,
    	FILTER3 = 0x2B,
    	FILTER4 = 0x2C,
    	FILTER5 = 0x2D,
    	FILTER6 = 0x2E,
    	FILTER7 = 0x2F,
    	/* ADC offset registers */
    	OFFSET0 = 0x30,
    	OFFSET1 = 0x31,
    	OFFSET2 = 0x32,
    	OFFSET3 = 0x33,
    	OFFSET4 = 0x34,
    	OFFSET5 = 0x35,
    	OFFSET6 = 0x36,
    	OFFSET7 = 0x37,
    	/* ADC gain registers */
    	GAIN0 = 0x38,
    	GAIN1 = 0x39,
    	GAIN2 = 0x3A,
    	GAIN3 = 0x3B,
    	GAIN4 = 0x3C,
    	GAIN5 = 0x3D,
    	GAIN6 = 0x3E,
    	GAIN7 = 0x3F
    } adc7173_register_t;
    
    /* ADC analog inputs */
    typedef enum {
    	AIN0 = 0x00,
    	AIN1 = 0x01,
    	AIN2 = 0x02,
    	AIN3 = 0x03,
    	AIN4 = 0x04,
    	AIN5 = 0x05,
    	AIN6 = 0x06,
    	AIN7 = 0x07,
    	AIN8 = 0x08,
    	AIN9 = 0x09,
    	AIN10 = 0x0A,
    	AIN11 = 0x0B,
    	AIN12 = 0x0C,
    	AIN13 = 0x0D,
    	AIN14 = 0x0E,
    	AIN15 = 0x0F,
    	AIN16 = 0x10,
    	/* other ADC analog inputs */
    	TEMP_SENSOR_POS = 0x11,
    	TEMP_SENSOR_NEG = 0x12,
    	REF_POS = 0x15,
    	REF_NEG = 0x16
    } analog_input_t;
    
    /* ADC filter data rates (samples per second) */
    /* some are are rounded down, the data rates are for sinc5 + sinc1 */
    typedef enum {
    	SPS_31250 = 0x00,
    	SPS_15625 = 0x06,
    	SPS_10417 = 0x07,
    	SPS_5208 = 0x08,
    	SPS_2597 = 0x09,
    	SPS_1007 = 0x0A,
    	SPS_503 = 0x0B,
    	SPS_381 = 0x0C,
    	SPS_200 = 0x0D,
    	SPS_100 = 0x0E,
    	SPS_59 = 0x0F,
    	SPS_49 = 0x10,
    	SPS_20 = 0x11,
    	SPS_16 = 0x12,
    	SPS_10 = 0x13,
    	SPS_5 = 0x14,
    	SPS_2 = 0x15,
    	SPS_1 = 0x16
    } data_rate_t;
    
    /* ADC setup coding modes */
    typedef enum {
    	UNIPOLAR = 0x00,
    	BIPOLAR = 0x01
    } coding_mode_t;
    
    /* ADC data conversion modes */
    typedef enum {
    	CONTINUOUS_CONVERSION_MODE = 0x00,
    	SINGLE_CONVERSION_MODE = 0x01,
    	CONTINUOUS_READ_MODE
    } data_mode_t;
    
    /* clock mode */
    /*
    	00 Internal oscillator
    	01 Internal oscillator output on XTAL2/CLKIO pin
    	10 External clock input on XTAL2/CLKIO pin
    	11 External crystal on XTAL1 and XTAL2/CLKIO pins
    */
    typedef enum {
    	INTERNAL_CLOCK = 0x00,
    	INTERNAL_CLOCK_OUTPUT = 0x01,
    	EXTERNAL_CLOCK_INPUT = 0x02,
    	EXTERNAL_CRYSTAL = 0x03
    } clock_mode_t;
    
    /* ADC internal reference modes */
    typedef enum {
    	REF_DISABLE = 0x00,
    	REF_ENABLE = 0x01
    } ref_mode_t;
    
    /* ADC channel buffer setting */
    typedef enum {
    	AIN_BUF_DISABLE = 0x00,
    	AIN_BUF_ENABLE = 0x03
    } ain_buf_mode_t;
    
    /* setup to select reference source */
    /*
    	00 External reference source
    	01 AIN1/REF2+ and AIN0/REF2−
    	10 Internal reference source
    	11 External AVDD1 – AVSS
    */
    typedef enum {
    	REF_EXT = 0x00,
    	REF_AIN = 0x01,
    	REF_INT = 0x02,
    	REF_PWR = 0x03
    } setup_ref_source_t;
    
    /* ADC data ready indicator */
    #define DATA_READY digitalRead(MISO) == LOW
    
    class AD7173Class {
    public:
    	/*
    	=====================================
    	constructor
    	set default ADC setup coding mode
    	set default ADC data conversion mode
    	=====================================
    	*/
    	AD7173Class() : m_data_mode(CONTINUOUS_CONVERSION_MODE), append_status_reg(false) {
    		/* ... */
    	}
    
    	/*
    	============================================
    	initializes the SPI connection with the ADC
    	============================================
    	*/
    	void init();
    
    	/*
    	==================================================
    	cancels the current transaction to resync the ADC
    	==================================================
    	*/
    	void sync();
    
    	/*
    	==============================================
    	resets the ADC registers to the default state
    	==============================================
    	*/
    	void reset();
    
    	/*
    	=============================================
    	gets the current conversion results channel
    	@param byte - current data channel
    	@return int - error code
    	=============================================
    	*/
    	int get_current_data_channel(adc7173_register_t &);
    
    	/*
    	================================
    	sets the ADC mode configuration
    	@param clock_mode_t - clock mode
    	@return int - error code
    	================================
    	*/
    	int set_adc_mode_config(data_mode_t, clock_mode_t, ref_mode_t);
    
    	/*
    	==================================================
    	sets the ADC interface mode configuration
    	@param bool - ensable/disable continuous read mode
    	@return int - error code
    	==================================================
    	*/
    	int set_interface_mode_config(bool, bool);
    
    	/*
    	==========================================
    	gets the ADC conversion result
    	@return byte[] - the ADC conversion result
    	==========================================
    	*/
    	int get_data(byte *);
    
    	/*
    	============================================
    	checks the ID register of the ADC
    	@return bool - true if the ADC ID valid
    	============================================
    	*/
    	bool is_valid_id();
    
    	/*
    	=====================================
    	configures ADC channels
    	@param byte - channel register
    	@param bool - enable/disable channel
    	@param byte - setup register
    	@param byte - analog input positive
    	@param byte - analog input negative
    	@return int - error code
    	=====================================
    	*/
    	int set_channel_config(adc7173_register_t, bool, adc7173_register_t, analog_input_t, analog_input_t);
    
    	/*
    	==================================
    	sets the ADC setups coding mode
    	@param byte - setup register
    	@param condig_mode_t - coding mode
    	@param ain_buf_t - analog input buffer
    	@return int - error code
    	==================================
    	*/
    	int set_setup_config(adc7173_register_t, coding_mode_t, ain_buf_mode_t, setup_ref_source_t);
    
    	/*
    	==========================================
    	sets the ADC filters data conversion rate
    	@param byte - filter register
    	@param byte - data rate
    	@return int - error code
    	==========================================
    	*/
    	int set_filter_config(adc7173_register_t, data_rate_t);
    
    	/*
    	======================================
    	sets the ADC offset compensation value
    	@param byte - offset register
    	@param uint32_t - offset value
    	@return int - error code
    	======================================
    	*/
    	int set_offset_config(adc7173_register_t, uint32_t);
    
    private:
    	/* ADC data mode */
    	data_mode_t m_data_mode;
    	
    	/* Append status register to data */
    	bool append_status_reg;
    
    	/*
    	===========================
    	print bytes in nice format
    	@param byte - byte to print
    	===========================
    	*/
    	void print_byte(byte);
    
    	/*
    	=======================================
    	set a desired ADC register value
    	@param byte - the register to set
    	@param  byte[] - the bytes to set
    	@param int - the length of bytes to set
    	=======================================
    	*/
    	int set_register(adc7173_register_t, byte *, int);
    
    	/*
    	=======================================
    	get a desired ADC register value
    	@param byte - the register to get
    	@param int - the length of bytes to get
    	@return byte[] - the ADC register value
    	=======================================
    	*/
    	int get_register(adc7173_register_t, byte *, int);
    };
    
    extern AD7173Class AD7173;
    
    #endif

    thanks&regards,

    srinivasa

  • Hi  ,

    To determine the end of conversion status in single conversion mode, could you try to poll the RDY[7] bit in the status register (Address:0x0)? 

    In Continuous conversion mode, could you try to source the MISO pin as a source of interrupt to determine the Low signal before the data is being read?

    Regards,

    Janani Sunil

  • Hi  ,

    Just to add a suggestion, can you also monitor the Status Register (0x00) to check if an error in case an undervoltage has occurred.

    Regards,

    JC

  • Hi JC

    as you suggested I have read the status register and its value are 0x80. 

    DOUT/RDY  pin not going LOW.

     thanks & regards

    Srinivasa

  • Hi Janani,

    as you said I did both. I have been monitoring the MISO pin it is not going LOW.

    thanks & regards

    Srinivasa

  • Hi,  

    When monitoring the MISO pin, can you confirm that you pull /CS low? 

    I would recommend to follow these steps for debugging purposes. 

    For example, upon power up when registers are all at default configuration. Stop reading the conversions, just monitor the DRDY pin (when /CS low). Do you see that the pin is pulsing at default ODR (i.e. 6.211ksps)? If yes, try to change the programmed ODR by writing to its appropriate register (FILTCON register). After that, try to readback the same register to see if it was successfully updated. If the readback is okay, try again to monitor the DRDY pin (when /CS is low) and check if the pin is now pulsing at the new programmed ODR. If everything is okay, you can start changing other register based on your target configuration. I would suggest to change it one at a time just to debug where the issue is coming from. 

    When DOUT/RDY stops pulsing at any time and it stays high or low (even though the ADC is configured for continuous conversion mode), this indicates that the serial interface has become asynchronous (incorrect number of SCLK pulses, glitches on the SCLK line). Ensure that the correct number of SCLK pulses are being used for each read/write operation. It is also recommended to tie DIN and SCLK high when they are not being used to prevent glitches affecting the SPI interface.

    Thanks,
    Jellenie

Reply
  • Hi,  

    When monitoring the MISO pin, can you confirm that you pull /CS low? 

    I would recommend to follow these steps for debugging purposes. 

    For example, upon power up when registers are all at default configuration. Stop reading the conversions, just monitor the DRDY pin (when /CS low). Do you see that the pin is pulsing at default ODR (i.e. 6.211ksps)? If yes, try to change the programmed ODR by writing to its appropriate register (FILTCON register). After that, try to readback the same register to see if it was successfully updated. If the readback is okay, try again to monitor the DRDY pin (when /CS is low) and check if the pin is now pulsing at the new programmed ODR. If everything is okay, you can start changing other register based on your target configuration. I would suggest to change it one at a time just to debug where the issue is coming from. 

    When DOUT/RDY stops pulsing at any time and it stays high or low (even though the ADC is configured for continuous conversion mode), this indicates that the serial interface has become asynchronous (incorrect number of SCLK pulses, glitches on the SCLK line). Ensure that the correct number of SCLK pulses are being used for each read/write operation. It is also recommended to tie DIN and SCLK high when they are not being used to prevent glitches affecting the SPI interface.

    Thanks,
    Jellenie

Children
  • Hi Jellenie,

    thanks for your response.

    happy to share that I can able to read when DOUT/RDY goes low and conversion is happening properly as expected for a single supply(i.e for 0v to 2.5 reference voltage). 

    now I am working on split supply(i.e for -2.5v to 2.5v reference) in this I am not able to read for the full range. in split supply, I can able to read from -1.99v to +1.99v.

    can you please suggest to me to solve this issue?

    thanks&regards

    Srinivasa

  • Hi  

    Can you share your input setup please? For example what is your input voltage at AVDD, AVSS, IOVDD, REFIN+, REFIN-, AIN+ and AIN-?

    Thanks,

    Jellenie

  • Hi  Jellenie

    AVDD= 2.5V

    AVSS= -2.5V

    IOVDD = 3.3V

    REFIN+ = 2.5V

    REFIN- = AVSS

    AIN+ =  positive i have supply given

    AIN- =  I have connected this pin to ground

    thanks& regards

    Srinivasa

  • Hi  ,

    Apologies for getting back late. Your inputs are within specification, you should be able to read -2.5V to 2.5V. May I know what the output of the ADC is when you try to have an input of beyond -1.99V and 1.99V or at least the -2.5V and 2.5V input. Also, could you try probing REFIN+ and REFIN- just to make sure that it is 2.5V and AVSS respectively. I am assuming that both AVDD1 and AVDD2 is 2.5V, am I correct? 

    Regards,

    JC

  • Hi JC,

    yes AVDD1 and AVDD2 is 2.5v.

    here AIN1 is connected to the ground and AIN0 is used to give an input signal.

    here input signal is -2.5v to 2.5v. 

    I have attached the schematic below. please have look at the schematic and let me know if

    the schematic full fill the requirement. 

    quick response is appreciated.

    thanks&regards,

    Srinivasa

  • Hi  ,

    I checked your schematic and noticed the voltage divider in AIN0. For inputs of -2.5V and 2.5V, this will be effectively halved by the voltage divider circuit. I am unsure why the data you are reading is above -1.25V and 1.25V unless there is a mismatch in the resistors in the voltage divider.

    It would also help if you could share the output code of the ADC for these inputs. Also, how are you converting the bipolar codes into voltage?

    Input voltage Output data code
    -2.5V
    2.5V
    -1.99V
    1.99V

    Regards,

    JC

  • Hi JC,

    in the above circuit, I have removed the voltage divider. 

    I have a doubt that I have a bipolar signal (+2.5 to -2.5) that I am feeding to AIN0 of ADC and here AIN1 is grounded. I have configured the ADC to BIPOLAR in the SETUPCON register.

    can ADC able to read that +-2.5v in AIN0 itself?

    as I understood that, a single-ended connection means if  I select channel0 with AIN0&AIN1, AIN1 is connected to the ground and AIN0 is used to feed the signal with respect to AIN1.  in a single-ended case, reference is given as REF+=2.5V & REF-=ground(AVSS=0V).

    Fully differential means, AIN0 is connected to the positive supply and AIN1 is connected to the negative supply. reference is given as REF+=2.5V & REF-=AVSS=-2.5.

    here above schematic is designed for a single-ended connection with  REF+=2.5V & REF-=AVSS=-2.5.

    can a single-ended connection able to read bipolar signals?

    formula I have used is Vout = data_code*2.5/(2^24).

    please help me out with this.

    thanks&regards.

    Srinivasa

  • HI  ,

    The ADC should be able to read +-2.5V. Note that the absolute input voltage of the ADC is AVSS-0.05 to AVDD1+0.05 for disabled input buffers and AVSS to AVDD1-1.1 for buffers enabled and ensure that the differential input voltage range of the selected positive and negative input pins is +/- Vref, wherein Vref = REF+ - REF-. In your case, for the split supply, Vref = 5V. This is also applicable when connected in single-ended configuration.

    Yes, single-ended connection is able to read bipolar signals. Single-ended configuration means that you only have one input while the other input is fixed to ground. When bipolar mode is set, the ADC is able to accept a differential voltage either positive or negative. 

    Please use this equation to convert the output code.

    Bipolar code:

    Vout = [(Code/2^23) -1] * Vref

    Unipolar code:

    Vout = (Code * Vref) / 2^24

    Regards,

    JC

  • Hi JC,

    Thank you very much.

    now the device is working fine as expected. but the only concern is the accuracy.

    The accuracy error is 10 mv. I need to achieve below 1mv. my end application is designed to read 1mv to 2.5v.

    could you please help me out with this?

    thanks&regards

    Srinivasa

  • Hi  ,

    The accuracy of the ADC is dependent on several key specs, which include the INL, offset and gain errors, and the accuracy of the voltage reference temperature effects and AC performance. You can compute for the total accuracy by performing RSS (Root Sum Square) of the maximum gain, offset, INL error and all error contributors. In RSS, larger errors dominate the smaller errors. Hence, the dominating errors are the gain, offset and INL error.

    Regards,

    JC