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.

ADS1247 - conversion problem

Other Parts Discussed in Thread: ADS1247

Hi,

I'm using a ADS1247  with a PT100 temperture probe in 3-wire configuration.

I'm using the suggested configuration in slau520a application note,  but with some variation:

- Rref 1,2kohm (0.02% precision);

- Idac1 and Idac2 750uA;

- PGA 16;

With this configuration, I have a Vref of 1.8V (2 x Idac x Rref).

I configurated ADS1247 like follows:

- MUX0: 0x0A. AIN2 Negative input, AIN1 positive input, Burnout current source off (default);

- VBIAS: 0x00. Bias voltage not enabled (default)

- MUX1: 0x20. Normal Operation, REF0 input pair selected (default), Internal reference is always on, Internal oscillator in use.

- SYS0: 0x42. 20SPS, PGA 16.

- IDAC0: 0x05. 750uA, DOUT/DRDY pin functions only as Data Out (default)

- IDAC1: 0x30. I2DIR AIN0, I1DIR AIN3.

My source code for ADS1247 configure is the follow (START AND RESET PIN IS ALWAYS HIGH):

CS_ADS1=0;
while(DRDY_ADS1==1);
WriteSPI(0x16); // SDATAC
CS_ADS1=1;

__delay_ms(200);


CS_ADS1=0;

__delay_us(1);
WriteSPI(WREG);
WriteSPI(3); // write 3 register
WriteSPI(0xa); // mux0 register
WriteSPI(0); // vbias register
WriteSPI(0x20); //mux1 register //0x20
WriteSPI(0x42); //sys0 register
__delay_us(2);
CS_ADS1=1;

__delay_us(2);


CS_ADS1=0;
__delay_us(1);
WriteSPI(WREG|10);
WriteSPI(1); // write 2 register
WriteSPI(0x5); // idac0 register
WriteSPI(0x30); // idac1 register
__delay_us(2);
CS_ADS1=1;


__delay_ms(2);


CS_ADS1=0;
__delay_us(1);
WriteSPI(0x62); //self offset calibration
__delay_us(2);

CS_ADS1=1;

__delay_ms(100);
while(DRDY_ADS1);



CS_ADS1=0;

while(DRDY_ADS1==1);
WriteSPI(0x14); //Read data continuously
CS_ADS1=1;
__delay_ms(100);

For read the ADS1247 result my source code is:

CS_ADS1=0;


rtd_temperature=0;
ads_result=0;


while(DRDY_ADS1==1);
WriteSPI(NOP);
ads_result=ReadSPI();
rtd_temperature=ads_result;
rtd_temperature=rtd_temperature<<8;
WriteSPI(NOP);
ads_result=0;
ads_result=ReadSPI();
rtd_temperature=rtd_temperature|ads_result;
rtd_temperature=rtd_temperature<<8;
WriteSPI(NOP);
ads_result=0;
ads_result=ReadSPI();
rtd_temperature=rtd_temperature|ads_result;

__delay_us(2);
CS_ADS1=1;

Reading  and writing on the registers is OK, and I have across Rref 1.8V 

The problem is when I read the conversion result which is, according to me, wrong.

In fact at room temperature (25 °C) the ADC conversion result is 14090240.

If I use thw follow formula for RTD value calculate, I obtain:

RTD_VALUE = ADC_VALUE * Vref  / PGA / (2^23-1) /  EXCITATION_CURRENT= 14090240 * 1.8 / 16 / (2^23-1) / 0.00075= 251,95 Ohm 

This value would translate to a temperature of about 414 °C.

Someone can help me?

Thank's for your help!

Best regards,

Michela

Michela

  • Michela,


    I don't see anything wrong with the general way that you have the circuit set up. However, what are value are the resistors used for R41 and R43? If these values are too large, then the input bias current may react with the series resistance to give an error.

    You say the output reads 14090240. This gives a value of D70000h. With the twos complement notation, this becomes -290000h, or -2686976. Calculating this out, this is the equivalent of -.32 value of the full scale value (reference/PGA). In your example. that would be -0.36V (starting with a full scale of 1.8V/16). If the polarity isn't a problem, I would check the exact voltage measured with a DMM at the input pins. Then I'd check the voltage across the reference resistor, just to be sure.

    If the voltages seem to be correct. I would also read back the registers to make sure the configuration registers are set as expected and then I'd check the communication by looking at a scope shot of the digital lines to make sure that they are clean and reading what you thing they should read.


    Joseph Wu
  • Hi Joseph,

    the value of R41 and R43 is 9,09 kOhm, that is suggested by application note. Do you think that I should put a smallest value?  what value do you suggest?

    The voltage across the input pins is 82.9 mV while across the reference resistor is  1.808V. 

    So, the voltage seem to be ok. 

    I'd also check the register value and it are ok.

    Attached you can find an example of my SPI communication with ADS1247.

    In particular this communication  regards the read of one register at the address 0x03 (SYS0).

    My code is:

    CS_ADS1=0;
    while(DRDY_ADS1==1);
    WriteSPI(RREG|0x03); //read SYS0 register
    WriteSPI(0); // read one register
    __delay_us(10);
    ads_result=ReadSPI(); //ads1247 reply
    __delay_us(2);

    CS_ADS1=1;

    Thank you for your help,

    Michela

  • Michela,


    For input series resistance, I like to use 5k or less, but anything 10k or less should be fine. Actually, I saw the value on the schematic, but it didn't sink in for me.

    One problem that I see right now is that your MOSI is set up incorrectly, which means that you also might be reading it incorrectly. The SPI should be set up so that the SCLK idles low (which is correct now), and that the data is clocked in on the falling edge of SCLK. From the scope photo, it looks like the data is set up with the master thinking the data will be clocked out on the rising edge of SCLK.

    Check the code to makes sure how you have this set up. If the write to the device is set up wrong, then the read may be set up wrong as well. Once you have this checked, then take another data. Make sure you get the data read transaction on the scope as well. With the scope confirm that the data you read through the microcontroller matches what you see on the scope.


    Joseph Wu
  • Hi Joseph,

    I don't think that there are problem on SPI bacause, for example, if I set a current value of 750 uA, I measure across Rref (1200 Ohm) a voltage of 1.8V (Vref=2*750uA*1200) that is correct.

    if I write incorrectly on ADS1247, I would not have measured this voltage... Right?

    I think also that there is a fluctuation problem because if I do multiple read (for example every second), the result of ads1247 is much variable. These are some ADC conversion result:

    4259840

    4128768

    4587520

    4259840

    4653056

    Thank you,

    best regards

    Michela

  • I Joseph,
    I just solved the problem.
    The error was in the command for read the ADS1247 result.

    You have to consider that in the previous configuration of the chip, I used the command RDATAC.
    So, my code for read ADS result was:

    CS_ADS1=0;


    rtd_temperature=0;
    ads_result=0;


    while(DRDY_ADS1==1);
    WriteSPI(NOP);
    ads_result=ReadSPI();
    rtd_temperature=ads_result;
    rtd_temperature=rtd_temperature<<8;
    WriteSPI(NOP);
    ads_result=0;
    ads_result=ReadSPI();
    rtd_temperature=rtd_temperature|ads_result;
    rtd_temperature=rtd_temperature<<8;
    WriteSPI(NOP);
    ads_result=0;
    ads_result=ReadSPI();
    rtd_temperature=rtd_temperature|ads_result;

    __delay_us(2);
    CS_ADS1=1;



    Now, in this new modify, I don't use RDATAC but every times that I have to read the ADS conversion result I send the command RDATA.
    So, my code modified is:

    CS_ADS1=0;
    rtd_temperature=0;
    ads_result=0;
    while(DRDY_ADS1==1);
    WriteSPI(0x12); // COMMAND RDATA
    ads_result=ReadSPI();
    rtd_temperature=ads_result;
    rtd_temperature=rtd_temperature<<8;

    WriteSPI(NOP);
    ads_result=0;
    ads_result=ReadSPI();
    rtd_temperature=rtd_temperature|ads_result;
    rtd_temperature=rtd_temperature<<8;

    WriteSPI(NOP);
    ads_result=0;
    ads_result=ReadSPI();
    rtd_temperature=rtd_temperature|ads_result;

    WriteSPI(NOP);


    __delay_us(2);
    CS_ADS1=1;


    Anyway, thank you for your help.
    Best regards,
    Michela
  • Michela,


    I'm glad you were able to solve your problem. If you have any other questions, please feel free to post back to the forum.


    Joseph Wu
  • Michela,


    One thing I want to check is do you use the /DRDY indicator as an interrupt to read data?

    If you don't then there is a potential for read errors. In RDATAC mode, when there is a new data available, the DOUT register is automatically updated. If you are in the middle of clocking out data and a new data becomes available, the data coming out will start with one data, not finish it and start clocking out the new available data.

    To prevent this you can use a SDATAC command to prevent the ADC from updating the DOUT register automatically. You only need to do this once when you initialize the ADC. Then the DOUT register is updated when the RDATA command is used to retrieve data.



    Joseph Wu
  • Hi Joseph,

    thank's for your suggest. Yes, I check the DRDY pin interrupt because I read the ADS result convertion only when this pin go low.

    Anyway, I will try what you suggested!

    Thank you again,

    Michela

  • Joseph,
    I suppose that I have another problem.
    This time the problem is about fluctuation.
    For example in 1 second of distance between one reading and the next, the ADS conversion result is:
    2289664
    2269952
    2266368
    2275072

    What is the reason of this fluctuation?

    Thank you
    Michela
  • Hi Michela,

    Joseph is currently out of the office so let me jump in for him.

    The fluctuation you are seeing is pretty large.
    Could you do a few experiments to figure out where this could be coming from:

    • Could you take data in continuous conversion mode (maybe even at higher data rates) so we could see if you have any 50/60Hz noise or anything else disturbing your measurement? Plot the data to see if you have any characteristic waveform in your measurement.
    • Could you short the RTD and run similar measurements?
    • Could you short the ADS1247 inputs internally (set MUXCAL[2:0]=001) and use the internal VREF for the measurement and take readings?


    There are two additional things I would like to point out:

    • The series filter resistors on the reference input pins are pretty large. I would recommend reducing them.
      You could also try it without them and also remove C34 and C38. You probably need to play around to see what works best for your application.
      Regarding the series resistors on the inputs. Most customers use values up to 10k because they use the resistors also to protect the inputs of the ADC in an overvoltage event. The resistors will then limit the currents into the ADC to save levels. If your system will not encounter any overvoltage events on the inputs it is best to make the series resistors as small as possible to reduce measurement errors.
    • Your RTD calculation works, however you are not leveraging the ratiometric circuit implementation when you use the absolute excitation current value in your equation.The reason why we implement the circuit as you have done is, that we are not dependent on the absolute value of the excitation current anymore. A better approach might be to use something like this:

      R_RTD*PGA*IDAC / R_REF*2*IDAC = Code/2^23
      R_RTD = (Code * 2 * R_REF) / (2^23 * PGA)

      You should probably also run a system offset and gain calibration to further improve your measurement accuracy. The exact value of the R_REF will have the biggest effect on your gain error. Shorting the RTD could be used to calibrate for offset and connecting a precision 100 or 200Ohm resistor instead of the RTD could for example be used to calibrate the gain error.

    Regards,

  • Hi Michela,

    I would like to also add a comment.  You may wish to verify that the data you are receiving is the actual data being sent from the ADS1247.  You can do this by monitoring the SCLK, DIN and DOUT signals with an oscilloscope or logic analyzer.  I suggest this as in each case you have given, when converting back to the hex value it is always showing the least significant byte as 0x00.  You may be incorrectly reading, shifting or interpreting the data.  Notice the values you have given in hex format:

    0x22F000

    0x22A300

    0x229500

    0x22B700

    These values would be highly unusual.

    Best regards,

    Bob B