No announcement yet.

RTD PT100 thermo measurement with ADS1248 and GEN4-43DCT-CLB

  • Filter
  • Time
  • Show
Clear All
new posts

  • RTD PT100 thermo measurement with ADS1248 and GEN4-43DCT-CLB


    I would like to use the SK-GEN4-43DCT-CLB display with the ADS1248 analog to digital converter and PT100 resistors to measure temperature.
    I set up the Display with the 4D-Systems Workshop in Designer mode.
    As a connection from the display to the GPIO-Pins i am using the Gen4-PA.

    I have problems by recieving the data correct from the ADC and displaying the correctly in the display.
    The ADS1248 works in continously conversion mode and the latest completed conversion is signaled on a high to low transition on the DRDY pin.
    The ADC sends 24bit data over the SPI to the display.
    The ADC works CPOL = 0 and CPHA = 1 for the SPI communication so i assume that the Display needs to work in SPI_MODE 0.

    I set up the SPI config and the DRDY following:

    ChipSelect PA6 //GPIO8
    SerialClock PA3 //GPIO1
    SDIPin PA0 //GPIO4
    SDOPin PA1 //GPIO3
    DRDY PA2 //GPIO2 PA8
    //set input and output pins
        pin_Set(PIN_OUT, PA5);                        //set pin PA5 GPIO9 to be used as an output
        pin_Set(PIN_OUT, PA8);                        //set pin PA8 GPIO6 to be used as an output
        pin_Set(PIN_INP, PA2);                        //set pin PA2 GPIO2 to be used as an input
        //Set the PWM to 50% duty cycle at startup
        pwm_Init(PA4,PWM_PLAIN,500); //PWM1 out on gen4-PA GPIO10
        pwm_Init(PA9,PWM_PLAIN,500); //PWM2 out on gen4-PA GPIO5
        //Configure the serial interface to SPI-Mode 1
        if (! SPI1_SDI_pin(SDIPin))
            print("SDI Pin Invalid\n") ;
            err := 1 ;
        if (! SPI1_SCK_pin(SerialClock))
        print("SCK Pin Invalid\n") ;
        err := 1 ;
        if (! SPI1_SDO_pin(SDOPin))
            print("SDO Pin Invalid\n") ;
            err := 1 ;
        if (! SPI1_Init(SPI_SPEED0,SPI8_MODE_0))     //Setup SPI0 mit 4,375Mhz und SPI_Mode1
            print("INIT parameter Invalid\n") ;
            err := 1 ;
         repeat forever
    I can correctly setup the internal registers of the ADS1248 with the display over SPI. I can also correctly read out the register setting of the ADS1248 with the Display.

    I am using the bus_SetChangeInterrupt command to trigger the readout of the data with a interrupt function called spi_dataread(). I am using this command in the repeat forever loop.

    bus_SetChangeInterrupt(spi_dataread,PA2); //reads the SPI by change of DRDY on PA8

    To read out the data and convert the data I am using the spi_dataread() function which i wrote:

    func spi_dataread()
        var voltage32[2];                   //32bit voltage result
        var temp32[2];                      //32bit temperature result
        var temp32_zero[2];                 //Zero temperature Kelvin constant
        var voltage_const[2];
        var rawdata[3];         //24bit Ergebnis von ADC => res array mit 2 int 16 => 32 bit => 4 byte
        var rawfloat[2];                    //32bit raw float data
        var result1[2],result2[2];
        var powres[2], const100[2];
        var state_PA2;
        state_PA2 := pin_Read(PA2);
        if(state_PA2 == 0)
        //If DRDY == 0
        flt_VAL(powres, "8388607");
        flt_VAL(voltage_const, "3.3");      //Convert a string ("3.3") to a result2
        flt_VAL(temp32_zero, "273.15");     //Convert a string ("3.3") to a temp32_zero
        flt_VAL(const100, "100");           //Convert a string ("3.3") to a temp32_zero
        spi1_ReadBlock(str_Ptr(rawdata), 3);//read 3 bytes from SPI and store it in the array rawdata
        flt_LTOF(rawfloat, rawdata);        //Converts a 32bit signed integer value to a signed floating point number.
        flt_DIV(result1, rawfloat, powres); //Performs floating point Division
        flt_MUL(voltage32, result1, voltage_const);//Performs floating point Multiplication  voltage := 1.0*V/(pow(2,23)-1)*3.3;
        flt_MUL(result2, voltage32, const100);
        flt_SUB(temp32, result2, temp32_zero); //temp := voltage*100-273.15;
        str_Printf(rawdata, "%3X");
        flt_PRINTxy(0,20,rawfloat, "<rawfloat> %+6.2f <");
        flt_PRINTxy(0,30,result1, "<result1> %+6.2f <");
        flt_PRINTxy(0,40,result2, "<result2> %+6.2f <");
        flt_PRINTxy(0,50,voltage32, "<voltage32> %+6.2f <");
        flt_PRINTxy(0,60,temp32, "<temp32> %+6.2f <");
        flt_PRINTxy(0,70,powres, "<powres> %+6.2f <");
    Since the display can only handle uint16 i try to convert the 24 bit data into float to calculate the temperature. I am not sure if i am correct here with the array sizes.

    I try to check if the state of the DRDY pin at change was from High to Low by using pin_Read(PA2) and check if the state is 0. Actually i want to trigger the spi_dataread() function on the falling edge of the PA2 input. It appears to me that the interrupt is triggered on a Low to High change of DRDY or all in the end of the Low period of DRDY. I added a picture of the communication:

    Click image for larger version

Name:	SPI1.jpg
Views:	180
Size:	83.4 KB
ID:	66801

    Click image for larger version

Name:	SPI2.jpg
Views:	39
Size:	76.7 KB
ID:	66802

    On the Display I get out wrong data unfourtenatly. The rawdata readout is stable but when i touch the RTD the data starts to display wrong data. Somehow the results also change in magnitudes. I believe that i am reading wrong data.

    Another thing is when i set the PA5 pin high my interrupt function on PA2 gets triggered i wonder why.
    Also when i connect a logic analyzer my interrupt function stops to trigger.

    Is there another posibility to trigger a function on a change of a input channel ?

    Thanks a lot for your help

    Best Regards


  • #2

    I have had a look though the datasheet and the data comes in as MSB,MidByte,LSB so this maybe just the way it is loaded into rawdata that needs changing. Looking at the way rawdata is loaded it looks like it will be in the order of MSB, MidByte, LSB, then 0 meaning that the result possibly wouldn't be correct as it should be in the order of 0, MSB, MidByte, LSB

    I haven't been able to test but this may work

    rawdata[0] := SPI1_Read();
    rawdata[1] := SPI1_Read() << 8;
    rawdata[1] := rawdata[1] + SPI1Read();

    instead of the SPI1_Readblock command This would mean that the MMSB is at 0 always and the 24 bit data is in the right place

    I hope this helps

    Best regards



    • #3
      Hi Paul,

      you where right, I changed the SPI1_Readblock command to:

      rawdata[0] := MSB;
      rawdata[1] := MB;
      rawdata[2] := LSB;

      carry := rawdata[0];

      powerold:= MB<<8;
      powerold:= powerold + rawdata[2];

      LongInt[0] := powerold;
      LongInt[1] := carry;

      which is actually the same what you suggested. Thanks a lot for you help

      One thing i wonder is that i am using the bus_SetChangeInterrupt(spi_dataread,PA2) to trigger the SPI readings.
      I need to place a resistor about 1MegOhm to the SDI pin to ground so that the function gets triggered. I dont know why i need to do that. Maybe it is because of capacities in my ADC layout and with the resistor the time constant gets long enough so the display can trigger the interrupt function.

      Best regards



      • #4

        Great, glad that worked out

        I am not really sure on the best way to trigger without having the device but if it works that way and triggers reliably then I would say it is a good solution, quite a neat workaround.