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.

ADS1255. Spontaneous resets while data receiving

Other Parts Discussed in Thread: ADS1255

Hello!

Currently I am studying ADC ADS1255 using stm32 with chibios. I have developed a prototyping board for the ADC . Board contains the power supplies of analog and digital parts ( 5 V, as the reference 2.5V and 3.3V ). XTAL 8 MHz 10ppm. Scheme is represented below


I have carefully studied the datasheet and wrote a minimally functional program that performs the following tasks:

1) Power up sequence;

2) Reset sequence;

3) ADC configuration;

4) Data receiving.

Here is the code:

// Sending command to ADC
void ads_command(uint8_t command) {
    CsLo();                              // Chip select low
    uint8_t temp = command;
    spiSend(SPI_Driver, 1, &temp);       // spiSend is chibiOS's function, that send n bytes (1 in this function) from the variable "temp"
    CsHi();                              // Chip select high
  }

// Reset ADC
void ads_reset(void) {
  ads_command(ADS125X_RESET);
  chThdSleepMilliseconds(MS2ST(4));      // 4 ms delay
  ads_command(ADS125X_SELFCAL);
  chThdSleepMilliseconds(MS2ST(10));     // 10 ms delay
}

// Wakeup ADC from Standby
void ads_wakeup(void) {
  ads_command(ADS125X_WAKEUP);
}

// Write data to ADC's register
void ads_wreg(uint8_t firstreg, uint8_t numreg) {
  uint8_t temp = ADS125X_WREG + firstreg;
  CsLo();
  spiSend(SPI_Driver, 1, &temp);
  temp = numreg-1;
  spiSend(SPI_Driver, 1, &temp);
  spiSend(SPI_Driver, numreg, &regstack);         // regstack - is a global array (length 0x0A) for ADC's reg data collection
  CsHi();
}

//Read data from ADC's register
void ads_rreg(uint8_t firstreg, uint8_t numreg) {
  uint8_t temp = ADS125X_RREG + firstreg;
  CsLo();
  spiSend(SPI_Driver, 1, &temp);
  temp = numreg-1;
  spiSend(SPI_Driver, 1, &temp);
  chThdSleepMilliseconds(MS2ST(2));
  spiReceive(SPI_Driver, numreg, &regstack);
  CsHi();
}

void ads_rdatac() {
  PWaitingThread = chThdGetSelfX();
  chSchGoSleepS(CH_STATE_SUSPENDED);
  ads_command(ADS125X_RDATAC);
}

void ads_sdatac() {                         
  PWaitingThread = chThdGetSelfX();        
  chSchGoSleepS(CH_STATE_SUSPENDED);       
  ads_command(ADS125X_SDATAC);
}

// Read ADC's conversion data in continuous mode
void read_data(uint8_t numdata, void *pbuff) {
  CsLo();
  for (uint8_t i=1; i < numdata+1; i++) {
    PWaitingThread = chThdGetSelfX();              // Here is a routine that wainting for external event (DRDY changing from high to low)
    chSchGoSleepS(CH_STATE_SUSPENDED);             // to perform read operation 
    spiReceive(SPI_Driver, 3, pbuff);
    pbuff = pbuff + 3;
  }
  CsHi();
}

// One shot mode
void read_data_oneshot(uint8_t numdata, void *pbuff) {
  ads_sdatac();
  for (uint8_t i=1; i < numdata+1; i++) {
    PWaitingThread = chThdGetSelfX();
    chSchGoSleepS(CH_STATE_SUSPENDED);
    ads_command(ADS125X_RDATA);
    CsLo();
    spiReceive(SPI_Driver, 3, pbuff);
    pbuff = pbuff + 3;
    CsHi();
  }
}

void ads_conf() {
  ads_rreg(0,1);                                   // read status
  regstack[0] = regstack[0] | ADS125X_BUFON;       // Change reg value
  ads_wreg(0,1);                                   // Buff on

  regstack[0] = 0x01;                              // Positive - AIN0
  ads_wreg(0x01, 1);                               // Negative - AIN1 differential mode

  regstack[0] = 0xB0;
  ads_wreg(0x03,1);                                // Sampling speed 2 kSPS

  ads_rreg(0x02,1);
  regstack[0] = regstack[0] | 0x00;                //  PGA = 1
  ads_wreg(0x02,1);

  ads_command(ADS125X_SELFCAL);                    // Self calibration
  chThdSleepMilliseconds(MS2ST(2));
}

/*
 * Threads
 */

int main(void) {


  halInit();
  chSysInit();
/*
 * GPIO configuration
 */

  palSetPadMode(GPIOSPI, CS, PAL_MODE_OUTPUT_PUSHPULL);   /*  CS  */
  palSetPadMode(GPIOSPI, SCK, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST |GPIO_MODER_MODER5_1);  /*   SCK */
  palSetPadMode(GPIOSPI, SO, PAL_MODE_ALTERNATE(5) | GPIO_MODER_MODER6_1);  /*  MISO    */
  palSetPadMode(GPIOSPI, SI, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST | GPIO_MODER_MODER7_1);  /*   MOSI    */

  palSetPadMode(GPIOC, 10, PAL_MODE_ALTERNATE(7));       // TX
  palSetPadMode(GPIOC, 11, PAL_MODE_ALTERNATE(7));      // RX

 /*
  * Drivers starting
  */
  uartStart(&UARTD3, &uart_cfg);
  spiStart(SPI_Driver, &spicnfg);
  extStart(&EXTD1, &extcfg);


  ads_reset();                                 // ADC reset
  ads_conf();                                  // Configure 
  //ads_rdatac();                              // Dont used in one shot mode

  while (true) {
    //read_data(30, &inbuff);                  // Donnt used in one shot mode
    read_data_oneshot(30, &inbuff);            // Perform data receiving
    uartStartSend(&UARTD3, 90, &inbuff);       // Sending data to computer for debug purpose
  }
}

Here is logic oscillogram, that shows properly configuration o SPI and ADC (its saleae logic oscillogram with 10 sec length. Its difficult to make screenshot, that provide detailed information about signals). If there is no possibility to open then I'll send a screenshot.

16 MHz, 160 M Samples [22].rar

PROBLEM.

If you look at the trace, you may notice that after 360 ms there is a spontaneous reset. It occurs in different times, and only when reading data. If you configure the ADC and read the data, this is not a problem. The following waveform data without reading.

16 MHz, 160 M Samples [23].rar 

On the last waveform reset does not occure.

As this problem occurs when any attempt to change source at the input. I have suggested that it may be either a defense mechanism within the ADC from the ESD or any another overvoltage, but I did not find anything in the datasheet.

Please any help in solving the mystery. Thank you!

With respect,

Maslov Artem






  • Hi Maslov,

    Welcome to the TI E2E Forums!

    I looked at your Saleae logic analyzer screenshots and I see the "reset" that your referring to at 360 ms, where /DRDY is held high and then returns to its default 30 kSPS cycle period.

    Have you tried looking at the SPI bus using an oscilloscope (to see the analog voltages)?

    I believe you might have some ringing on the digital signals that the Saleae logic analyzer is not able to capture. The Saleae logic analyzer only shows the digital logic levels, and if it is not connected directly at the ADS1255 digital input pins, you may not be observing the exact same signal as seen by the ADC. Also, you could have some signal integrity issues if you're jumper wiring to the headers on your board. If the jumper wires are long or not tied together with a ground wire, they create large loop areas which can add significant inductance to the signal path.

    Also, since the RESET command is "0xFE", iI would recommend keeping DIN low (clocking out data using the 0x00 command) to avoid accidentally sending the RESET command.

    Aside: I also noticed that /CS is going high after the RDATA command. This is likely preventing you from reading the data. Make sure to keep /CS low until you've finished clocking out the data.

    Best Regards,
    Chris

  • Sry for delay!
    Thank you for your answer and support.
    Problem was found in digital supply voltage. I set 3.3 V LDO and with my oscilloscope i found, that it has 3.8 - 4.2 V oscillations that exceed maximum input voltage. I think this led to the fact that the input protection diodes enabled and the circuit was powered down for short period (reset).
    I have designed new scheme and PCB without cables and i hope it works.

    Best Regards,
    Artem
  • Hi Artem,

    Thanks for the update! Let me know if you run into any other issues or questions about the ADS1255 that I can help with.

    Best Regards,
    Chris