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.

ADS1158: Shared SPI bus

Part Number: ADS1158

Dear TI forum,

I have 3 x ADS1158 on a shared SPI bus. Let's call them ADC A, B and C. I am using 2 GPIOs for toggling a MUX in order to properly set the chip select pins for each ADC. The MUX is SNx4HC139. Each DRDY pins are connected to 3x GPIOs, one for each ADC. Both ADC A and B are configured identically (let's ignore ADC C for now):

Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] ADC 0 reset.
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] ADC 1 reset.
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] ADCs configured succesfully. ADCs configuration:
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x0 Value 0x5e
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x1 Value 0x31
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x2 Value 0x0
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x3 Value 0xf
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x4 Value 0x0
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x5 Value 0x0
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x6 Value 0x0
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x7 Value 0x7f
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x8 Value 0x0
Nov 28 13:21:42 raspberrypi acquisition[163587]: [INFO] Register 0x9 Value 0x9b

I am trying to sample the ADCs in the following sequence (I will ignore ADC C for simplicity below):

1. Toggle MUX to select ADC A.

2. Send start sampling pulse to ADC A (see code below).

3. Toggle MUX to select ADC B.

4. Send start sampling pulse to ADC B.

5. Toggle MUX to select ADC A.

6. Poll its DRDY gpio and if it becomes 0 then read data from ADC A with Channel Data Read Command (see code below).

7. Toggle MUX to select ADC B.

8. Poll its DRDY gpio and if it becomes 0 then tead data from ADC B with Channel Data Read Command.

Start sampling pulse:

char pulse = 0b10000000;
spi_send(handle, &pulse, NULL, sizeof(pulse));

Channel Data Read Command:

char tx[] = { 0b00110000, 0x00, 0x00, 0x00 };
spi_send(handle, tx, rx, sizeof(tx));

The whole read channel command with timeout:

bool adc_read_channel(int ready, int handle, char* rx) {
    uint8_t gpio = 0;
    uint32_t start = gpioTick();
    uint32_t current = gpioTick();
    int diff = current - start;
    while (gpio == 1 && diff < TIMEOUT) {
       gpio = gpioRead(ready);
       current = gpioTick();
       diff = current - start;
    }

    if (diff >= TIMEOUT) {
       return false;
    }

    // Read sample
    char tx[] = { 0b00110000, 0x00, 0x00, 0x00 };
    spi_send(handle, tx, rx, sizeof(tx));

    return true;
}

Very often I get a timeout on ADC B (meaning its DRDY pin does not go low within 100ms or something resets it while handling SPI transfers for ADC A). I've added some logs:

Nov 28 13:13:52 raspberrypi acquisition[162518]: [INFO] adc a channel 0 start sampling drdy a 1 b 1 c 1 cs 0 cs 1 (mux 0b01 selects ADC A)
Nov 28 13:13:52 raspberrypi acquisition[162518]: [INFO] adc b channel 0 start sampling drdy a 1 b 1 c 1 cs 0 cs 0 (mux 0b00 selects ADC B)
Nov 28 13:13:52 raspberrypi acquisition[162518]: [INFO] before channel read drdy a 0 b 1 c 1 cs 0 cs 1
Nov 28 13:13:52 raspberrypi acquisition[162518]: [INFO] after channel read drdy a 1 b 1 c 1 cs 0 cs 1 (DRDY for ADC A toggles from low to high, as expected)
Nov 28 13:13:52 raspberrypi acquisition[162518]: [ERROR] adc timeout on DRDY pin 26 gpio value (active low) 1 diff 100000 (100ms).
Nov 28 13:13:52 raspberrypi acquisition[162518]: [ERROR] drdy a 1 b 1 c 1 (DRDY pin for ADC B never toggled during the while loop)
Nov 28 13:13:52 raspberrypi acquisition[162518]: [ERROR] cs 1 0 cs 2 0 (mux selected 0b00 ADC B)

It works ok for ADC A but DRDY from ADC B was not detected to go low. Or maybe it went low and then high again before getting to that loop but I'm not so sure what could possibly reset DRDY.

Questions:

1. Does DRDY reset when SCLK runs for another ADC even though its CS is high? It's a shared SPI SCLK and datasheet says that DRDY goes back high on the first falling edge of the SCLK.

2. Could ADC B also get the commands from ADC A and react on those even though its CS is high?

3. Sometimes it works, sometimes it doesn't. It works if I add some artificial delays here and there but it's not consistent. What else could cause DRDY to reset?

4. Should I completely ignore DRDY and rely only on the NEW bit from the STATUS byte?

Many thanks!

  • One more thing I would like to add is that it works stable with the following sequence:


    1. Start sampling on ADC A

    2. Readout sample from ADC A

    3. Toggle MUX and start sampling on ADC B

    4. Readout sample from ADC B

  • Hi Remus Mihail Prunescu,

    Is the second sequence you described in your last post acceptable as a solution? Is there any reason you need to start the sampling the devices sequentially, as opposed to just tying the START pins for each device together and toggling them at the same time?

    It is certainly possible that if you are multiplexing through the DRDY signals that you might miss one of the high low transitions. You can see from Figure 43 in the datasheet that the DRDY pulse is very short. Generally you would want to use an interrupt-driven GPIO to detect this transition and let your data readback routine know that new data is ready to be sampled

    -Bryan

  • Hi Bryan,

    Thanks for replying. This is actually something I needed confirmation for, i.e. the DRDY signal is a pulse and it won't stay high forever until the sample is read out (even though CS is not selecting the ADC). The datasheet says on page 23 at the top that DRDY goes high on the first SCLK falling edge and I thought that since CS is not selecting the ADC then DRDY will just stay low until I run SCLK on that ADC.

    I'll rethink the firmware and use an interrupt.

    Thank you!

  • Hi Remus Mihail Prunescu,

    The DRDY output is independent of CS - see the CS section on page 27 of the datasheet. So DRDY will indicate new data is ready whether CS is low or high, assuming the ADC is converting

    As you noted, the behavior of DRDY changes depending on if you issue SCLKs or not. This is shown in Figure 39 on page 23. In either case however, you are looking for that transition from high to low on DRDY - this is what indicates data are new. The difference is that if you issue SCLKs, DRDY will be forced high, whereas if you do not issue SCLKs, DRDY will stay low except for a low-high-low pulse whose duration is given by Figure 2 and its subsequent table.

    -Bryan

  • Hello again,

    I have decided to try polling the NEW bit from the Status byte because the interrupt has a large latency on my platform (pi running linux). However, I am reading out garbage sometimes when the NEW bit is set. Is there any danger that I could actually read out data while it's being written by the ADC? I don't issue any other pulse commands to start conversion (only 1 pulse command and then I poll the status byte). Here is my polling loop:

    uint32_t start = gpioTick();
    uint32_t current = gpioTick();
    int diff = current - start;
    char tx[] = { 0b00110000, 0x00, 0x00, 0x00 };
    bool new = false;

    while (!new && diff < TIMEOUT) {
       current = gpioTick();
       diff = current - start;
       spi_send(handle, tx, rx, sizeof(tx));
       new = (rx[1] & (1 << 7)) > 0;
    }

    The data in rx is very noisy. But if I do a re-read after detecting the NEW bit set:

    while (!new && diff < TIMEOUT) {
       current = gpioTick();
       diff = current - start;
       spi_send(handle, tx, rx, sizeof(tx));
       new = (rx[1] & (1 << 7)) > 0;
       if (new) {
         gpioDelay(20);
         spi_send(handle, tx, rx, sizeof(tx));
         rx[1] |= (1 << 7);
       }
    }

    Data looks cleaner in this case.

    When the NEW bit is set by the ADC is the whole register written or is it being written to at the same time I'm reading from it?

  • Nevermind. I found the issue. I was not using channel ID in a place in code and data was swapped. It looks great now.

  • Hi Remus Mihail Prunescu,

    I am glad you were able to resolve this issue, we will consider it closed for now

    If you had additional questions you may always start a new thread

    -Bryan