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.

ADS1220: ADS1220: reading data without DRDY. RDATA problem

Part Number: ADS1220

Hi everyone.

I am trying to communicate with ADS1220 in standard mode but without DOUT/DRDY pin. I set registers and read their values, receiving valid result.

Now I am trying to read temperature and voltages. Registers looks like:

#define DEFAULT_CONFIG_REG0 0b00000000 // AINP=AIN0, AINN=AIN1, Gain 1, PGA enabled
#define DEFAULT_CONFIG_REG1 0b00000100 // Data rate: 20 SPS, Normal Operating mode, Continuous conversion mode, Temperature sensor disabled, Burn-out disabled
#define DEFAULT_CONFIG_REG2 0b00010000 // Internal 2.048-V reference, Simultaneous 50-Hz and 60-Hz rejection, Switch always open, IDAC Off
#define DEFAULT_CONFIG_REG3 0b00000000 // IDAC1 disabled, IDAC2 disabled, Only DRDY

General code looks like:

writeSingleRegister( 1, DEFAULT_CONFIG_REG1 & (1 << 1) );
int temp = readData();
writeSingleRegister( 1, DEFAULT_CONFIG_REG1 );
int voltage = readData();

void writeSingleRegister(uint8_t address, const uint8_t value) {
// set CS and other variables ...
SPI.transfer(WREG | (address<<2));
SPI.transfer(value);
}
int32_t readData() {
// set CS and other variables ...
SPI.transfer(RDATA);
// read 3 bytes
}

Unfortunately my code receive nothing. Variables temp and voltage are all bits high.

I have no possibility to test data lines with oscilloscope or LA now, but everything seems that there is some problem with such data reading.

  • Hi Michal,

    Welcome to the E2E forum! There are several things that need to be changed. The first thing I see is you are missing the START command. The ADS1220 powers up in Single-Shot mode and requires the START command to be issued after changing the register setting to Continuous conversion mode. After the START command is given the ADS1220 will begin conversions.

    Next issue I see is you write the configuration register and then immediately try to read the result. You must either monitor DRDY or delay the attempt to read the conversion result until the conversion completes. At 20sps this will be approximately 50ms (conversion times are listed in Table 11 of the ADS1220 datasheet). If you do not wait until the conversion has completed, your code will keep changing the register settings which will restart the ongoing conversion. If this is in a loop, the conversion will never complete and there will never be a conversion result available.

    Third issue is the 'readData' function. It appears that you are sending the RDATA command, but the SPI communication requires that the SPI master send three more bytes of 'dummy' data (0xFF for example) to initiate the SPI clocks to clock out the data. Also CS must be held low throughout the entire communication transaction.

    Best regards,
    Bob B
  • I am still facing some major problem and cant read any valid data.
    In a loop I am setting REG1 to measure temperature, wait about 60ms and try to read values. Received buffer looks randomly- eg. 0x04 13 2B and is constant. Like it would have something in common with measurement but measurement is done one time and than I am reading same and same value from the internal register. At the end of the loop, I am again waiting, this time 1s before loop repeating.
    Below I am posting some arduino code that shows that process:

    #include <SPI.h>

    #define DEFAULT_CONFIG_REG0 0b00000000 // AINP=AIN0, AINN=AIN1, Gain 1, PGA enabled
    #define DEFAULT_CONFIG_REG1 0b00000100 // Data rate: 20 SPS, Normal Operating mode, Continuous conversion mode, Temperature sensor disabled, Burn-out disabled
    #define DEFAULT_CONFIG_REG2 0b00010000 // Internal 2.048-V reference, Simultaneous 50-Hz and 60-Hz rejection, Switch always open, IDAC Off
    #define DEFAULT_CONFIG_REG3 0b00000000 // IDAC1 disabled, IDAC2 disabled, Only DRDY

    #define ADS1220_CS_PIN 1
    #define PIN_NUM_ADC_PWR 2
    #define WREG 0x40
    #define RREG 0x20
    #define RDATA 0x10
    #define START 0x08
    #define SPI_MASTER_DUMMY 0xFF

    void setup() {
    Serial.begin(115200);
    pinMode(ADS1220_CS_PIN, OUTPUT);
    pinMode(PIN_NUM_ADC_PWR, OUTPUT);
    digitalWrite(PIN_NUM_ADC_PWR, LOW);
    delay(100);
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode (SPI_MODE1);
    SPI.setClockDivider(SPI_CLOCK_DIV128);

    Serial.println("DEFAULT_CONFIG Write");
    writeSingleRegister( 0, DEFAULT_CONFIG_REG0 );
    writeSingleRegister( 1, DEFAULT_CONFIG_REG1 );
    writeSingleRegister( 2, DEFAULT_CONFIG_REG2 );
    writeSingleRegister( 3, DEFAULT_CONFIG_REG3 );
    delay(100);
    Serial.println("DEFAULT_CONFIG Read");
    Serial.println(readRegister(0),HEX);
    Serial.println(readRegister(1),HEX);
    Serial.println(readRegister(2),HEX);
    Serial.println(readRegister(3),HEX);
    Serial.println(" ");
    // OK: read what I have written

    writeCommand( START );
    delay(1000);
    readData();
    }
    void loop() {
    while(1) {
    writeSingleRegister( 1, DEFAULT_CONFIG_REG1 & (1 << 1)); // Enable temperature sensor
    // if I add START command here, values starts changing but still looks random like "0x4 4-14-3A", "0x4 4-13-66". It is not temp value
    // delay(1); writeCommand( START );
    delay(60);
    readData();
    delay(1000);
    }
    }

     

    void writeSingleRegister(uint8_t address, const uint8_t value) {
    digitalWrite(ADS1220_CS_PIN, LOW);
    SPI.transfer(WREG | (address<<2));
    SPI.transfer(value);
    digitalWrite(ADS1220_CS_PIN,HIGH);
    }


    uint8_t readRegister(uint8_t address) {
    uint8_t data;
    digitalWrite(ADS1220_CS_PIN,LOW);
    SPI.transfer(RREG|(address<<2));
    data = SPI.transfer(SPI_MASTER_DUMMY);
    digitalWrite(ADS1220_CS_PIN,HIGH);
    return data;
    }


    void readData() {
    digitalWrite(ADS1220_CS_PIN,LOW);
    Serial.print("\n0x");
    Serial.print(SPI.transfer(RDATA), HEX);
    Serial.print(" ");
    for (int i = 0; i < 3; i++, Serial.print("-")) {
    uint8_t data = SPI.transfer(SPI_MASTER_DUMMY);
    Serial.print(data, HEX);
    }


    digitalWrite(ADS1220_CS_PIN,HIGH);
    }
    void writeCommand(uint8_t cmd) {
    digitalWrite(ADS1220_CS_PIN, LOW);
    SPI.transfer(cmd);
    digitalWrite(ADS1220_CS_PIN,HIGH);
    }

    void setup() {
    Serial.begin(115200);
    pinMode(ADS1220_CS_PIN, OUTPUT);
    pinMode(PIN_NUM_ADC_PWR, OUTPUT);
    digitalWrite(PIN_NUM_ADC_PWR, LOW);
    delay(100);
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode (SPI_MODE1);
    SPI.setClockDivider(SPI_CLOCK_DIV128);

    Serial.println("DEFAULT_CONFIG Write");
    writeSingleRegister( 0, DEFAULT_CONFIG_REG0 );
    writeSingleRegister( 1, DEFAULT_CONFIG_REG1 );
    writeSingleRegister( 2, DEFAULT_CONFIG_REG2 );
    writeSingleRegister( 3, DEFAULT_CONFIG_REG3 );
    delay(100);
    Serial.println("DEFAULT_CONFIG Read");
    Serial.println(readRegister(0),HEX);
    Serial.println(readRegister(1),HEX);
    Serial.println(readRegister(2),HEX);
    Serial.println(readRegister(3),HEX);
    Serial.println(" ");
    // OK: I read what I have written

    writeCommand( START );
    delay(1000);
    readData();
    }


    void loop() {
    while(1) {
    writeSingleRegister( 1, DEFAULT_CONFIG_REG1 & (1 << 1)); // Enable temperature sensor
    // if I add START command here, values starts changing but still looks random like "0x4 4-14-3A", "0x4 4-13-66". It is not temp value
    // delay(1); writeCommand( START );
    delay(60);
    readData();
    delay(1000);
    }
    }


    Unfortunately, I have no easy access to Logic Analyzer and cant test real values on MOSI, MISO.

    Could you also point me a difference when I read data after conversation is ready, just ticking with clock, and when I am sending RDATA command. How does ADS1220 know that it should send me data now or after one byte (because I am sending RDATA), when there isn't any time delay?

  • Just read my code one more time and understood what I have done: setting REG1 there is missprint & not |. I was clearing this register. Will check it later
  • Hi Michal,

    The & instead of | will write 0x00 to Register 1 as you stated. That is definitely an issue.

    The very first conversion after power-up will require the START command to be issued to start conversions, even if you place the ADS1220 into continuous conversion mode. In single-shot mode you would be required to issue the START command to start each conversion.

    The RDATA command will always send out the last completed conversion. You should add the CS high at the end of your readData function. If you monitor DRDY, you can just send out the SCLKs instead of issuing the RDATA command. The end of conversion is signaled by a transition of of high to low on DRDY. If you have any question regarding the timing of your loop or end of conversion I would suggest using the RDATA command.

    Best regards,
    Bob B