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.

ADS1256: Fast read and write

Part Number: ADS1256
Other Parts Discussed in Thread: DAC8532

Hi, 

I bought a high-precision AD/DA board form Waveshare that uses the ADS1256 as ADC. They provide an example program to read the analog values but this goes rather slow. 

Can someone help me with this, I'm using a Raspberry Pi in combination with the board. 

Chip select is connected to pin 15 and when low it will select the ADS1256. Data ready is connected to pin 11. Want to receive an incoming signal with the ADS1256 24-bit and set the outcome as the variable for the ouput DAC 16-bit and at least 8kHz.

Hope someone can help or set me in the right direction.

  • Hi Luc,

    You have us at a slight disadvantage here - none of us are familiar with the hardware you have using the ADS1256. Can you perhaps provide a part number for the board you bought or point us to the schematics for it?
  • Hi Tom,

    Sorry I was very unclear.
    The board that I'm using can be found here www.waveshare.com/.../DA_Board
    It uses the ADS1256 for ADC: www.ti.com/.../ads1256.pdf
    and the DAC8532 ad DAC: www.ti.com/.../dac8552.pdf

    While running the sample code they provided here: www.waveshare.com/.../File:High-Precision-AD-DA-Board-Code.7z
    I tested the ADS1256_test and made some modifications to it, to only look at one poort (one ADC input). While reading a sinus fluctuating between 0 - 5 [V] I expected the program to print a lot of values between, lets say a step of 0.1[V] or even smaller. I think it has something to do with the DRDY of the ADS1256.
    I could get better results by changing the configuration settings. Those are the SPI divider and the Samples per second (SPs). I got the best results by changing the Sps from 30000 to 1000 and the SPI fom 1024 to 256. Lowering the SPs for a better result was not what I expected. I tough more samples means better resolution.

    Would it maybe help if I use one SPI bus for writing(DAC) and the other one for reading(ADC) on my Raspberry Pi.

    Best regards,

    Luc

  • I'm currently running this loop(see below). Right now the outer loop which waits for the DRDY to become available runs around 60 times before entering once. If I would be able to decrease the wait time, I could check the ADC input more often then in this case.

    Best regards,


    int main()
    {
    uint8_t id;
    int32_t adc[8];
    int32_t volt[8];
    uint8_t i;
    //uint8_t ch_num;
    int32_t iTemp;
    //uint8_t buf[3];
    //uint32_t DACVAL;
    //uint16_t _D_;
    //uint16_t newvar;
    uint8_t _ch;
    int8_t counter;


    if (!bcm2835_init())
    return 1;

    bcm2835_spi_begin();
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST ); // The default
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); // The default
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256); // The default
    bcm2835_gpio_fsel(SPICS, BCM2835_GPIO_FSEL_OUTP);//
    bcm2835_gpio_write(SPICS, HIGH);
    bcm2835_gpio_fsel(DRDY, BCM2835_GPIO_FSEL_INPT);
    bcm2835_gpio_set_pud(DRDY, BCM2835_GPIO_PUD_UP);
    //ADS1256_WriteReg(REG_MUX,0x01);
    //ADS1256_WriteReg(REG_ADCON,0x20);
    // ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS);

    //~ struct timespec tstart = {0,0}, tend = {0,0};
    //~ clock_gettime(CLOCK_MONOTONIC, &tstart);

    //~ clock_gettime(CLOCK_MONOTONIC, &tend);
    //~ printf("computation took about %.5f seconds\n",((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec));


    id = ADS1256_ReadChipID();
    printf("\r\n");
    printf("ID=\r\n");

    if (id != 3)
    {
    printf("Error, ASD1256 Chip ID = 0x%d\r\n", (int)id);
    }
    else
    {
    printf("Ok, ASD1256 Chip ID = 0x%d\r\n", (int)id);
    }
    /*
    11110000 = 30,000SPS (default)
    11100000 = 15,000SPS
    11010000 = 7,500SPS
    11000000 = 3,750SPS
    10110000 = 2,000SPS
    10100001 = 1,000SPS
    10010010 = 500SPS
    10000010 = 100SPS
    01110010 = 60SPS
    01100011 = 50SPS
    01010011 = 30SPS
    01000011 = 25SPS
    00110011 = 15SPS
    00100011 = 10SPS
    00010011 = 5SPS
    00000011 = 2.5SPS
    */


    ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_1000SPS);
    ADS1256_StartScan(0);
    g_tADS1256.ScanMode = 0; //channel mode 0 = single, 1 = differential
    //ADS1256_SetChannal(0); //channel mode 0 = single, 1 = differential

    //ch_num = 8;
    i = 2;
    counter = 0;


    while(1) //outer loop
    {
    // time sampe outer loop
    struct timespec tstart = {0,0}, tend = {0,0};
    clock_gettime(CLOCK_MONOTONIC, &tstart);

    //Count loop times before entering innerloop
    counter = counter +1;
    printf("%d counter \r\n",counter);


    while (DRDY_IS_LOW()) //inner loop
    {
    //ADS1256_ISR();
    //return 1;

    struct timespec tstart = {0,0}, tend = {0,0};
    clock_gettime(CLOCK_MONOTONIC, &tstart);

    /*running ADS1256_ISR inside loop */
    //ADS1256_SetChannal(g_tADS1256.Channel); /*Switch channel mode */
    _ch = g_tADS1256.Channel; //instead of ADS1256_SetChannal function

    ADS1256_WriteReg(REG_MUX, (_ch << 4) | (1 << 3)); //instead of ADS1256_SetChannal function

    bsp_DelayUS(5);

    ADS1256_WriteCmd(CMD_SYNC);
    bsp_DelayUS(5);

    ADS1256_WriteCmd(CMD_WAKEUP);
    bsp_DelayUS(5);



    if (g_tADS1256.Channel == 0)
    {
    g_tADS1256.AdcNow[7] = ADS1256_ReadData();
    }
    else
    {
    g_tADS1256.AdcNow[g_tADS1256.Channel-1] = ADS1256_ReadData();
    }

    if (++g_tADS1256.Channel >= 8)
    {
    g_tADS1256.Channel = 0;
    }

    printf("%d DRADY low \r\n",DRDY);


    adc[i] = ADS1256_GetAdc(i);
    volt[i] = (adc[i] * 100) / 167;

    printf("%d volt \r\n",volt[i]);

    iTemp = volt[i];
    printf("%d iTemp \r\n",iTemp);


    //~ iTemp = volt[i]; /* uV */
    //~ if (iTemp < 0)
    //~ {
    //~ iTemp = -iTemp;
    //~ printf(" (-%ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
    //~ }
    //~ else
    //~ {
    //~ printf(" ( %ld.%03ld %03ld V) \r\n", iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000);
    //~ }

    counter = 0;
    clock_gettime(CLOCK_MONOTONIC, &tend);
    printf("computation innerloop took about %.5f seconds\n",((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec));


    } //end DRDY while loop

    clock_gettime(CLOCK_MONOTONIC, &tend);
    printf("computation outerloop took about %.5f seconds\n",((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec));

    } //end while(1) loop

    } //end int main
  • Hi Luc,

    How is the "ADS1256_ReadData()" function implemented? Perhaps the implementation of that function could be sped up.

    Also, I notice that you have some "printf()" statements in your data collection loop. Please note that "printf()" calls can be very slow and might be the reason you're not reading data faster.

    As to why performance improves when you change the clock divider, there are a couple of things that could be happening. In general a faster clock will fetch the data faster so that you don't miss any many samples. Also, if you are readying data while /DRDY goes low you could be getting corrupted data that is a combination of old and new data. Therefore, you might need to pay attention to the timing of when you read that data and also try using the RDATA command to clock out the data, as that command will buffer the output data and help prevent it from being overwritten as a new conversion completes.

    Best regards,
    Chris