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.

CC1310: Crystal drift with wide temperature swings (0C to 80C)

Part Number: CC1310

Hi, we have several boards as temperature sensors where there temperature can go from 0C to 80C and the receiver temperature is only between 10C and 40C.

We are using the same crystal as the Launchpad (EPSON). The frequency varies a lot with the temperature (drift) and we are using the LRM so the bandwith is small. I have a couple questions:

1. What can I do to make this more robust (maybe there is a firmware based solution)?

2. Do you have any crystal recommendation where tempeatures can have big changes? I know the CC1310 doesn't support a TCXO so that's not an option. 

Any suggestions?

Thanks!

  • Hello Dorse,

    If TXCO is not an option, one thing you can do is to create a crystal frequency error table (typically called an "S" curve) by measuring the error in the frequency through the temperature range. You can then use the reading from temp sensor and adjust for this offset  in firmware to obtain a more accurate output frequency. It is possible that the crystal manufacturer provides you with this "S" curve.  

    We did this on one of our applications, below is a code snippet. It also does interpolation to obtain a more accurate error from the S curve.

    #include "aon_batmon.h"
    
    #define SCURVE_ARRAY_SIZE 25
    
    int16_t freqTempCurve[SCURVE_ARRAY_SIZE] = {
    -12901, //-40
    -9295, //-35
    -5689, //-30
    -2788, //-25
    -64, //-20
    1607, //-15
    2564, //-10
    3259, //-5
    3279, //0
    2948, //5
    2416, //10
    1532, //15
    310, //20
    -967, //25
    -2244, //30
    -3357, //35
    -4167, //40
    -4777, //45
    -5309, //50
    -5408, //55
    -5008, //60
    -4167, //65
    -2724, //70
    -1182, //75
    321, //80
    };
    
    
    
    #ifdef FREQ_TEMP_COMPENSATION
    tempDegC = AONBatMonTemperatureGetDegC(); // Read temperature
    #ifdef FREQ_TEMP_INTERPOLATE
    tempDegC_floor = tempDegC - (tempDegC % 5);
    freqTempCurveIndex = (int)(tempDegC_floor + 40) / 5;
    
    if (tempDegC >= 0)
    freqError = (freqTempCurve[freqTempCurveIndex + 1] - freqTempCurve[freqTempCurveIndex]) * ((float)( tempDegC - tempDegC_floor)/5);
    else
    freqError = (freqTempCurve[freqTempCurveIndex - 1] - freqTempCurve[freqTempCurveIndex]) * ((float)( tempDegC - tempDegC_floor)/5);
    
    freqError = freqTempCurve[freqTempCurveIndex] + freqError;
    
    ul_Freq = (ul_Freq - freqError);
    
    #else
    if (tempDegC >= 0) // Round by 5 degrees
    tempDegC = ((int)((tempDegC + 2.5) / 5)) * 5;
    else
    tempDegC = ((int)((tempDegC - 2.5) / 5)) * 5;
    
    freqTempCurveIndex = (int)(tempDegC + 40) / 5;
    
    ul_Freq = (ul_Freq - freqTempCurve[freqTempCurveIndex]); // Compensate for error from the curve.
    #endif
    #endif
    
       tempDegC = ((int)((tempDegC - 2.5) / 5)) * 5;
    
    freqTempCurveIndex = (int)(tempDegC + 40) / 5;
    
    ul_Freq = (ul_Freq - freqTempCurve[freqTempCurveIndex]); // Compensate for error from the curve.
    
    #endif