/**
* @file ALGO_Temperature_ATY.c
*
* @param Project ALGO_Algorithm_ATY_LIB
*
* @author ATY
*
* @copyright
* - Copyright 2017 - 2026 MZ-ATY
* - This code follows:
* - MZ-ATY Various Contents Joint Statement -
*
* https://mengze.top/MZ-ATY_VCJS
* - CC 4.0 BY-NC-SA -
*
* https://creativecommons.org/licenses/by-nc-sa/4.0/
* - Your use will be deemed to have accepted the terms of this statement.
*
* @brief functions of NTC or others temperature calc
*
* @version
* - 1_01_230107 > ATY
* -# Preliminary version, first Release
* - 1_02_251120 > ATY
* -# Full test
********************************************************************************
*/
#ifndef __ALGO_Temperature_ATY_C
#define __ALGO_Temperature_ATY_C
#include "ALGO_Temperature_ATY.h"
#define ALGO_Temperature_ATY_TAG "\r\n[ALGO_Temperature_ATY] "
#define RTD_A 3.9083e-3
#define RTD_B -5.775e-7
#define RTD_C -4.183e-12
/******************************* For user *************************************/
#include
#define ALGO_LOG_DEF(v) log(v)
#define ALGO_Sqrt_DEF(v) sqrt(v)
// #include "ALGO_AlgorithmBase_ATY.h"
// #define ALGO_LOG_DEF(v) ALGO_MATH_LogLn(v)
// #define ALGO_Sqrt_DEF(v) ALGO_Sqrt_NewtonNumber(v)
/******************************************************************************/
// NTC -------------------------------------------------------------------------
/**
* @brief Calculate temperature from ntc resistance(Steinhart-Hart change)
* @param Rntc Current NTC resistance value
* @param R25 NTC standard resistance value at 25C
* @param B B value of NTC
* @return Current temperature in Celsius
* @note T25: Kelvin temperature at 25C = 298.15 = ALGO_TEMP_CtoT(25)
* R25: NTC standard resistance value at 25C like 10K,5K,100K...
* B: B value of NTC like 3435,3950...
* Rntc: Current NTC resistance value
* Tn: Actual Kelvin temperature(Cn = Tn-273.15)
* B = (lnR25 - lnRntc)/(1/T25 - 1/Tn)
*/
double ALGO_ResToKelvinTemp(double Rntc, double R25, double B){
if(Rntc <= 0) return 0;
if(R25 <= 0) return 0;
double Tn = 0.0;
double Cn = 0.0;
double temp_f[2];
temp_f[0] = (ALGO_LOG_DEF(R25) - ALGO_LOG_DEF(Rntc)) / B;
temp_f[1] = (1.0 / ALGO_TEMP_CtoT(25)) - temp_f[0];
Tn = 1.0 / temp_f[1];
Cn = ALGO_TEMP_TtoC(Tn);
return Cn;
}
/**
* @brief Calculate temperature from ntc resistance
* @param vADC ADC voltage in mV
* @param vRef NTC ref voltage in mV
* @param rRefK ref resistance in kOhm
* @param R25 NTC standard resistance value at 25C
* @param B B value of NTC
* @param rRefPos ref res psition, 1 for pull up, 0 for pull down(for ntc)
* @return Current temperature in Celsius
* @note T25: Kelvin temperature at 25C = 298.15 = ALGO_TEMP_CtoT(25)
* R25: NTC standard resistance value at 25C like 10K,5K,100K...
* B: B value of NTC like 3435,3950...
* Rntc: Current NTC resistance value
* Tn: Actual Kelvin temperature(Cn = Tn-273.15)
* B = (lnR25 - lnRntc)/(1/T25 - 1/Tn)
*/
double ALGO_VolToKelvinTemp(double vADC, double vRef, double rRefK, double R25, double B, uint8_t rRefPos){
if(rRefPos == 1){
return ALGO_ResToKelvinTemp(ALGO_VoltageToResDown(vADC, vRef, rRefK), R25, B);
}
else{
return ALGO_ResToKelvinTemp(ALGO_VoltageToResUp(vADC, vRef, rRefK), R25, B);
}
}
/**
* @brief Calculate temperature from ntc resistance(Steinhart-Hart)
* @param Rntc Current NTC resistance value
* @param A A value of NTC
* @param B B value of NTC
* @param C C value of NTC
* @return Current temperature in Celsius
*/
double ALGO_ResToKelvinTempABC(double Rntc, double A, double B, double C){
double Tn = 0.0;
double Cn = 0.0;
Tn = (A + (B * ALGO_LOG_DEF(Rntc)) + (C * ALGO_LOG_DEF(Rntc) * ALGO_LOG_DEF(Rntc) * ALGO_LOG_DEF(Rntc)));
Tn = 1.0 / Tn;
Cn = ALGO_TEMP_TtoC(Tn);
return Cn;
}
// RTD fast(PT100) -------------------------------------------------------------
/**
* @brief Calculate temperature from RTD resistance(PT100)
*
* @param T Temperature in Degrees Celsius
* @return double RTD resistance in ohms
*/
double ALGO_Temp_RTD_T(double T){
if(T >= -200 && T < 0){
return 100 * (1 + RTD_A * T + RTD_B * T * T + RTD_C * (T - 100) * T * T * T);
}
else if(T >= 0 && T <= 850){
return 100 * (1 + RTD_A * T + RTD_B * T * T);
}
return 0;
}
/**
* @brief Calculate temperature from RTD resistance(PT100)
*
* @param rtdRes RTD resistance in ohms
* @return double Temperature in Degrees Celsius
*/
double ALGO_Temp_RTD_Res_Fast(double rtdRes){
return (double)((rtdRes - 100.0) / 0.385);
}
/**
* @brief Calculate temperature from RTD resistance(PT100) above 0C
*
* @param rtdRes RTD resistance in ohms
* @return double Temperature in Degrees Celsius
*/
double ALGO_Temp_RTD_Res_Above(double rtdRes){
return (double)(((-1 * RTD_A) + ALGO_Sqrt_DEF((RTD_A * RTD_A)
- 4 * (RTD_B) * (1 - (rtdRes / 100.0))))
/ (2 * (RTD_B)));
}
/**
* @brief Calculate temperature from RTD resistance(PT100) below 0C
*
* @param rtdRes RTD resistance in ohms
* @return double Temperature in Degrees Celsius
*/
double ALGO_Temp_RTD_Res_Below(double rtdRes){
return (double)(-242.02
+ 2.2228 * rtdRes
+ (2.5859e-3) * rtdRes * rtdRes
- (4.826e-6) * rtdRes * rtdRes * rtdRes
- (2.8183e-8) * rtdRes * rtdRes * rtdRes * rtdRes
+ (1.5243e-10) * rtdRes * rtdRes * rtdRes * rtdRes * rtdRes);
}
// RTD precise -----------------------------------------------------------------
/**
* @brief PT100 temperature calculation using second-order tangent method
* @param[in] resist RTD resistance in ohms
* @param[out] temp Degrees Celsius
* @retval Temperature in Degrees Celsius
* @note Use a second-derivative tangent method. Depending on how close the resistance
* is to the zero-degree resistance, 1-3 iterations yield an accurate temperature:
* 1. Use a linear formula to get a rough temperature:
* t1 = (Rt / R0 - 1) / A
*
* Compute the resistance at t1:
* For t1 >= 0C: Rt1 = R0 * (1 + A * t1 + B * t1 * t1);
* For t1 < 0C: Rt1 = R0 * [1 + A * t1 + B * t1 * t1 + C * (t1 - 100) * t1 * t1 * t1];
*
* If |Rt1 - Rt| < 0.001, t1 is the desired temperature; otherwise continue:
*
* 2. Compute the first and second derivatives:
* If Rt >= R0
* t1' = 1 / [R0 * (A + 2 * B * t1)]
* t1'' = -2 * B * R0 * t1' * t1' * t1'
* If Rt < R0
* t1' = 1 / [R0 * (A + 2 * B * t1 - 300 * C * t1 * t1 + 4 * C * t1 * t1 * t1)]
* t1'' = - R0 * (2 * B - 600 * C * t1 + 12 * C * t1 * t1) * t1' * t1' * t1'
*
* 3. Compute the approximate temperature t2 based on Rt, t1, Rt1:
* t2 = t1 + t1' * (Rt - Rt1) + 0.5 * t1'' * (Rt - Rt1) * (Rt - Rt1);
* then compute the corresponding resistance Rt2.
*
* 4. If |Rt2 - Rt| < 0.001, t2 is the desired temperature; otherwise start from
* step 2 to compute derivatives again and obtain the accurate temperature.
*/
double ALGO_Temp_RTD_Res_PT100(double resist){
double fT, fT0;
short i;
/* 1. use a linear formula to get a rough temperature first */
fT0 = (resist / 100 - 1) / RTD_A;
/* -200C ~ 0C */
if(resist >= 18.52 && resist < 100){
for(i = 0; i < 50; i++){
fT = fT0 + (resist - 100 * (1 + RTD_A * fT0 + RTD_B * fT0 * fT0
- 100 * RTD_C * fT0 * fT0 * fT0 + RTD_C * fT0 * fT0 * fT0 * fT0)) /
(100 * (RTD_A + 2 * RTD_B * fT0 - 300 * RTD_C * fT0 * fT0 + 4 * RTD_C * fT0 * fT0 * fT0));
/* If | Rt1-Rt | < 0.001, t1 is the desired temperature */
if(fabs(fT - fT0) < 0.001){
return fT;
}
else{
fT0 = fT;
}
}
}
/* 0C ~ 850C */
else if(resist >= 100 && resist <= 390.481){
for(i = 0; i < 50; i++){
fT = fT0 + (resist - 100 * (1 + RTD_A * fT0 + RTD_B * fT0 * fT0)) / (100 * (RTD_A + 2 * RTD_B * fT0));
/* If | Rt1-Rt | < 0.001, t1 is the desired temperature */
if(fabs(fT - fT0) < 0.001){
return fT;
}
else{
fT0 = fT;
}
}
}
return 0;
}
/**
* @brief Calculate temperature from RTD resistance(PT1000)
*
* @param resist RTD resistance in ohms
* @return double Temperature in Degrees Celsius
*/
double ALGO_Temp_RTD_Res_PT1000(double resist){
return ALGO_Temp_RTD_Res_PT100(resist / 10.0);
}
// TC -------------------------------------------------------------------------
/**
* @brief Thermocouple Type
*
* @param type
* @param Temp in Degrees Celsius
* @return double in mV
* @note https://srdata.nist.gov/
*/
double ALGO_Temp_TC_TempToVol(uint8_t type, double Temp){
if(type == 'T'){
if(Temp == 0)
return 0;
else if(Temp > 0){
return (0
+ ((0.387481063640e-1) * Temp)
+ ((0.332922278800e-4) * Temp * Temp)
+ ((0.206182434040e-6) * Temp * Temp * Temp)
+ ((-0.218822568460e-8) * Temp * Temp * Temp * Temp)
+ ((0.109968809280e-10) * Temp * Temp * Temp * Temp * Temp)
+ ((-0.308157587720e-13) * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.454791352900e-16) * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((-0.275129016730e-19) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp));
}
else if(Temp < 0){
return (0
+ ((0.387481063640e-01) * Temp)
+ ((0.441944343470e-04) * Temp * Temp)
+ ((0.118443231050e-06) * Temp * Temp * Temp)
+ ((0.200329735540e-07) * Temp * Temp * Temp * Temp)
+ ((0.901380195590e-09) * Temp * Temp * Temp * Temp * Temp)
+ ((0.226511565930e-10) * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.360711542050e-12) * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.384939398830e-14) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.282135219250e-16) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.142515947790e-18) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.487686622860e-21) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.107955392700e-23) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.139450270620e-26) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp)
+ ((0.797951539270e-30) * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp * Temp));
}
}
return 0;
}
/**
* @brief Thermocouple Type
*
* @param type
* @param voltage in mV
* @return double in Degrees Celsius
* @note https://srdata.nist.gov/
*/
double ALGO_Temp_TC_VolToTemp(uint8_t type, double voltage){
if(type == 'T'){
if(voltage == 0)
return 0;
else if(voltage > 0){
return (0
+ ((2.592800e1) * voltage)
+ ((-7.602961e-1) * voltage * voltage)
+ ((4.637791e-2) * voltage * voltage * voltage)
+ ((-2.165394e-3) * voltage * voltage * voltage * voltage)
+ ((6.048144e-5) * voltage * voltage * voltage * voltage * voltage)
+ ((-7.293422e-7) * voltage * voltage * voltage * voltage * voltage * voltage));
}
else if(voltage < 0){
return (0
+ ((2.5949192e1) * voltage)
+ ((-2.1316967e-1) * voltage * voltage)
+ ((7.9018692e-1) * voltage * voltage * voltage)
+ ((4.2527777e-1) * voltage * voltage * voltage * voltage)
+ ((1.3304473e-1) * voltage * voltage * voltage * voltage * voltage)
+ ((2.0241446e-2) * voltage * voltage * voltage * voltage * voltage * voltage)
+ ((1.2668171e-3) * voltage * voltage * voltage * voltage * voltage * voltage * voltage));
}
}
return 0;
}
// Table -------------------------------------------------------------------
/**
* @brief Lookup temperature from resistance table
*
* @param R in ohms, or voltage to Thermocouple, follow tableR
* @param tableT in C
* @param tableR in R
* @param tableSize T/R table must be the same size
* @return double
* @note tableT must raise, like -10, 0, 10, 20, 30, ...
*/
double ALGO_RT_Table_R2T(double R, const double* tableT, const double* tableR, uint16_t tableSize){
// negative temperature coefficient, like ntc
if(tableR[0] > tableR[1]){
// check border
if(R < tableR[tableSize - 1] || R > tableR[0]){
return -273.15;
}
// cycle
for(uint16_t i = 0; i < tableSize - 1; i++){
if(R == tableR[i]){
return tableT[i];
}
if(R <= tableR[i] && R >= tableR[i + 1]){
double T1 = tableT[i];
double T2 = tableT[i + 1];
double R1 = tableR[i];
double R2 = tableR[i + 1];
return T1 + (R - R1) * (T2 - T1) / (R2 - R1);
}
}
}
// positive temperature coefficient, like rtd
else{
// check border
if(R > tableR[tableSize - 1] || R < tableR[0]){
return -273.15;
}
// cycle
for(uint16_t i = 0; i < tableSize - 1; i++){
if(R == tableR[i]){
return tableT[i];
}
if(R >= tableR[i] && R <= tableR[i + 1]){
double T1 = tableT[i];
double T2 = tableT[i + 1];
double R1 = tableR[i];
double R2 = tableR[i + 1];
return T1 + (R - R1) * (T2 - T1) / (R2 - R1);
}
}
}
return -273.15;
}
/**
* @brief Lookup resistance from temperature table
*
* @param T in C, just follow your tableT
* @param tableT in C
* @param tableR in R
* @param tableSize T/R table must be the same size
* @return double
* @note tableT must raise, like -10, 0, 10, 20, 30, ...
*/
double ALGO_RT_Table_T2R(double T, const double* tableT, const double* tableR, uint16_t tableSize){
// check border
if(T > tableT[tableSize - 1] || T < tableT[0]){
return 0;
}
// cycle
for(uint16_t i = 0; i < tableSize - 1; i++){
if(T == tableT[i]){
return tableR[i];
}
if(T >= tableT[i] && T <= tableT[i + 1]){
double T1 = tableT[i];
double T2 = tableT[i + 1];
double R1 = tableR[i];
double R2 = tableR[i + 1];
return R1 + (T - T1) * (R2 - R1) / (T2 - T1);
}
}
return 0;
}
// Test ------------------------------------------------------------------------
#ifdef ALGO_Temperature_ATY_Test_ATY
uint8_t ALGO_Temperature_ATY_Test_Pass;
uint8_t ALGO_Temperature_ATY_Test_Fail;
double ALGO_Temperature_ATY_Test_Out[74];
static int __aty_close(double a, double b, double tol){
return fabs(a - b) <= tol;
}
static double __aty_ntc_beta_res(double T, double R25, double B){
double Tk = ALGO_TEMP_CtoT(T);
double T25 = ALGO_TEMP_CtoT(25.0);
return R25 * exp(B * (1.0 / Tk - 1.0 / T25));
}
static double __aty_v_pu_from_res(double R, double vRef, double rRefK){
return vRef * R / (rRefK + R);
}
static double __aty_v_pd_from_res(double R, double vRef, double rRefK){
return vRef * rRefK / (rRefK + R);
}
uint32_t ALGO_Temperature_ATY_Test(void){
uint32_t idx = 0;
ALGO_Temperature_ATY_Test_Pass = 0;
ALGO_Temperature_ATY_Test_Fail = 0;
printf_ATY_D("%sSTART\r\n", ALGO_Temperature_ATY_TAG);
{
// [0..5] NTC Beta R->T (ALGO_ResToKelvinTemp), target temps: [100, 25, 0, -40, 150, -55] (C)
// Out[i] == targetTemps[i] (+-0.5C)
double R25 = 10.0;
double Bv = 3950.0;
double tv[6] = {100.0, 25.0, 0.0, -40.0, 150.0, -55.0};
printf_ATY_D("\r\n[NTC Beta R->T] R25 = %f, B = %f\r\n", R25, Bv);
for(int i = 0; i < 6; i++){
double R = __aty_ntc_beta_res(tv[i], R25, Bv);
double out = ALGO_ResToKelvinTemp(R, R25, Bv);
ALGO_Temperature_ATY_Test_Out[idx++] = out;
if(__aty_close(out, tv[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" TargetT = %fC, CalcR = %f, OutT = %fC, %s\r\n", tv[i], R, out, (__aty_close(out, tv[i], 0.01) ? "PASS" : "FAIL"));
}
}
{
// [6..17] NTC V->T (ALGO_VolToKelvinTemp), per target temps [100, 25, 0, -40, 150, -55]
// For temperature index j in 0..5:
// Out[12 + j*2] pull-up topology result == targetTemps[j] (+-0.5C)
// Out[12 + j*2 + 1] pull-down topology result == targetTemps[j] (+-0.5C)
double vRef = 2500.0;
double rRefK = 10.0;
double R25 = 10.0;
double Bv = 3950.0;
double tv[6] = {100.0, 25.0, 0.0, -40.0, 150.0, -55.0};
printf_ATY_D("\r\n[NTC V->T] vRef = %f mV, rRefK = %f kOhm, R25 = %f, B = %f\r\n", vRef, rRefK, R25, Bv);
for(int i = 0; i < 6; i++){
double R = __aty_ntc_beta_res(tv[i], R25, Bv);
double vpu = __aty_v_pu_from_res(R, vRef, rRefK);
double vpd = __aty_v_pd_from_res(R, vRef, rRefK);
double out_pu = ALGO_VolToKelvinTemp(vpu, vRef, rRefK, R25, Bv, 1);
double out_pd = ALGO_VolToKelvinTemp(vpd, vRef, rRefK, R25, Bv, 0);
ALGO_Temperature_ATY_Test_Out[idx++] = out_pu;
ALGO_Temperature_ATY_Test_Out[idx++] = out_pd;
if(__aty_close(out_pu, tv[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
if(__aty_close(out_pd, tv[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" PU: TargetT = %fC, vADC = %f mV, OutT = %fC, %s\r\n", tv[i], vpu, out_pu, (__aty_close(out_pu, tv[i], 0.01) ? "PASS" : "FAIL"));
printf_ATY_D(" PD: TargetT = %fC, vADC = %f mV, OutT = %fC, %s\r\n", tv[i], vpd, out_pd, (__aty_close(out_pd, tv[i], 0.01) ? "PASS" : "FAIL"));
}
}
{
// [18..23] NTC Steinhart-Hart ABC (ALGO_ResToKelvinTempABC) with resist list [2, 10, 32, 120, 0.5, 1e6] (KR/R)
// Out[18] high temp > 80C
// Out[19] room temp 15~35C
// Out[20] near zero -5~5C
// Out[21] below zero < 0C
// Out[22] very high > 120C
// Out[23] very low < -100C
// double A = 0.001129148;
// double Bc = 0.000234125;
// double Cc = 0.0000000876741;
double A = 2.681e-3;
double Bc = 2.886e-4;
double Cc = 7.275e-7;
double rv[6] = {1.2, 10.0, 30.0, 120.0, 0.5, 1000000.0};
printf_ATY_D("\r\n[NTC SH-ABC] A = %.3e, B = %.3e, C = %.3e\r\n", A, Bc, Cc);
double out0 = ALGO_ResToKelvinTempABC(rv[0], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out0;
if(out0 > 80.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, > 80 ? %s\r\n", rv[0], out0, ((out0 > 80.0) ? "PASS" : "FAIL"));
double out1 = ALGO_ResToKelvinTempABC(rv[1], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out1;
if(out1 > 15.0 && out1 < 35.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, 15.0 < T < 35.0 ? %s\r\n", rv[1], out1, ((out1 > 15.0 && out1 < 35.0) ? "PASS" : "FAIL"));
double out2 = ALGO_ResToKelvinTempABC(rv[2], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out2;
if(out2 > -5.0 && out2 < 5.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, -5.0 < T < 5.0 ? %s\r\n", rv[2], out2, ((out2 > -5.0 && out2 < 5.0) ? "PASS" : "FAIL"));
double out3 = ALGO_ResToKelvinTempABC(rv[3], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out3;
if(out3 < 0.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, < 0.0 ? %s\r\n", rv[3], out3, ((out3 < 0.0) ? "PASS" : "FAIL"));
double out4 = ALGO_ResToKelvinTempABC(rv[4], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out4;
if(out4 > 120.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, > 120.0 ? %s\r\n", rv[4], out4, ((out4 > 120.0) ? "PASS" : "FAIL"));
double out5 = ALGO_ResToKelvinTempABC(rv[5], A, Bc, Cc);
ALGO_Temperature_ATY_Test_Out[idx++] = out5;
if(out5 < -100.0) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" R = %f => T = %fC, < -100.0 ? %s\r\n", rv[5], out5, ((out5 < -100.0) ? "PASS" : "FAIL"));
}
{
// [24..33] RTD fast R->T group per temps [-40, 0, 25, 100, 850] (C)
// For index i in 0..4:
// Out[24 + i*2] fast approx (ALGO_Temp_RTD_Res_Fast) ≈ temp (+-3C for >=0, +-5C for <0)
// Out[24 + i*2 + 1] exact above/below (ALGO_Temp_RTD_Res_Above/Below) == temp
double tv[5] = {-40.0, 0.0, 25.0, 100.0, 850.0};
for(int i = 0; i < 5; i++){
double Rpt100 = ALGO_Temp_RTD_T(tv[i]);
double out_fast = ALGO_Temp_RTD_Res_Fast(Rpt100);
double out_above = 0.0;
double out_below = 0.0;
ALGO_Temperature_ATY_Test_Out[idx++] = out_fast;
if(__aty_close(out_fast, tv[i], (tv[i] > 100.0 ? 100.0 : 1.0))) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[RTD FAST] TargetT = %fC, R = %f Ohm, Fast = %fC, %s\r\n", tv[i], Rpt100, out_fast, (__aty_close(out_fast, tv[i], (tv[i] > 100.0 ? 100.0 : 1.0)) ? "PASS" : "FAIL"));
if(tv[i] >= 0.0){
out_above = ALGO_Temp_RTD_Res_Above(Rpt100);
ALGO_Temperature_ATY_Test_Out[idx++] = out_above;
if(__aty_close(out_above, tv[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" Above: R = %f Ohm, OutT = %fC, %s\r\n", Rpt100, out_above, (__aty_close(out_above, tv[i], 0.01) ? "PASS" : "FAIL"));
}
else{
out_below = ALGO_Temp_RTD_Res_Below(Rpt100);
ALGO_Temperature_ATY_Test_Out[idx++] = out_below;
if(__aty_close(out_below, tv[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" Below: R = %f Ohm, OutT = %fC, %s\r\n", Rpt100, out_below, (__aty_close(out_below, tv[i], 0.01) ? "PASS" : "FAIL"));
}
}
}
{
// [34..43] RTD fast R->T group per temps [-40, 0, 25, 100, 850] (C)
// For index i in 0..4:
// Out[34 + i*2] PT100 Newton (ALGO_Temp_RTD_Res_PT100) == temp (+-0.01C)
// Out[34 + i*2 + 1] PT1000 Newton (ALGO_Temp_RTD_Res_PT1000) == temp (+-0.01C)
double tv[5] = {-40.0, 0.0, 25.0, 100.0, 850.0};
double Rpt100[5] = {84.272, 100.0, 109.740, 138.506, 390.481};
for(int i = 0; i < 5; i++){
double out_pt100 = ALGO_Temp_RTD_Res_PT100(Rpt100[i]);
double out_pt1000 = ALGO_Temp_RTD_Res_PT1000(Rpt100[i] * 10.0);
ALGO_Temperature_ATY_Test_Out[idx++] = out_pt100;
ALGO_Temperature_ATY_Test_Out[idx++] = out_pt1000;
if(__aty_close(out_pt100, tv[i], 0.1)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
if(__aty_close(out_pt1000, tv[i], 0.1)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[RTD NEWTON] TargetT = %fC, R(PT100) = %f Ohm, OutT(PT100) = %fC, %s\r\n", tv[i], Rpt100[i], out_pt100, (__aty_close(out_pt100, tv[i], 0.1) ? "PASS" : "FAIL"));
printf_ATY_D(" R(PT1000) = %f Ohm, OutT(PT1000) = %fC, %s\r\n", Rpt100[i] * 10.0, out_pt1000, (__aty_close(out_pt1000, tv[i], 0.1) ? "PASS" : "FAIL"));
}
}
{
// [44..48] Thermocouple Type-T roundtrip: Out[i] == temps[-100, 0, 25, 300, 400] (+-1C)
double tv[5] = {-100.0, 0.0, 25.0, 300.0, 400.0};
for(int i = 0; i < 5; i++){
double v = ALGO_Temp_TC_TempToVol('T', tv[i]);
double out = ALGO_Temp_TC_VolToTemp('T', v);
ALGO_Temperature_ATY_Test_Out[idx++] = out;
if(__aty_close(out, tv[i], 0.1)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[TC-T Roundtrip] TargetT = %fC, CalcV = %f mV, OutT = %fC, %s\r\n", tv[i], v, out, (__aty_close(out, tv[i], 0.1) ? "PASS" : "FAIL"));
}
}
{
// [49..53] Table NTC R->T endpoints: equals tNTC[-40, 0, 25, 100, 150]
double tNTC[5] = {-40.0, 0.0, 25.0, 100.0, 150.0};
double rNTC[5] = {401.8597, 33.6206, 10.0, 0.6975, 0.19968};
for(int i = 0; i < 5; i++){
double out = ALGO_RT_Table_R2T(rNTC[i], tNTC, rNTC, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = out;
if(__aty_close(out, tNTC[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[Table NTC R->T] R = %f => T = %fC, %s\r\n", rNTC[i], out, (__aty_close(out, tNTC[i], 0.01) ? "PASS" : "FAIL"));
}
// [54..55] Table NTC R->T out-of-range: -273.15 (below/above bounds)
double out_low = ALGO_RT_Table_R2T(rNTC[4] * 0.5, tNTC, rNTC, 5);
double out_high = ALGO_RT_Table_R2T(rNTC[0] * 2.0, tNTC, rNTC, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = out_low;
ALGO_Temperature_ATY_Test_Out[idx++] = out_high;
if(__aty_close(out_low, -273.15, 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
if(__aty_close(out_high, -273.15, 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" OOR Low: R = %f => T = %fC, %s\r\n", rNTC[4] * 0.5, out_low, (__aty_close(out_low, -273.15, 0.01) ? "PASS" : "FAIL"));
printf_ATY_D(" OOR High: R = %f => T = %fC, %s\r\n", rNTC[0] * 2.0, out_high, (__aty_close(out_high, -273.15, 0.01) ? "PASS" : "FAIL"));
// [56..60] Table NTC T->R endpoints: equals rNTC{401.8597, 33.6206, 10.0, 0.6975, 0.19968} at tNTC[-40, 0, 25, 100, 150]
for(int i = 0; i < 5; i++){
double outR = ALGO_RT_Table_T2R(tNTC[i], tNTC, rNTC, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = outR;
if(__aty_close(outR, rNTC[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[Table NTC T->R] T = %fC => R = %f, %s\r\n", tNTC[i], outR, (__aty_close(outR, rNTC[i], 0.01) ? "PASS" : "FAIL"));
}
// [61..62] Table NTC T->R out-of-range: 0.0 (below/above bounds)
double outTlow = ALGO_RT_Table_T2R(tNTC[0] - 10.0, tNTC, rNTC, 5);
double outThigh = ALGO_RT_Table_T2R(tNTC[4] + 10.0, tNTC, rNTC, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = outTlow;
ALGO_Temperature_ATY_Test_Out[idx++] = outThigh;
if(__aty_close(outTlow, 0.0, 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
if(__aty_close(outThigh, 0.0, 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" OOR Low: T = %fC => R = %f, %s\r\n", tNTC[0] - 10.0, outTlow, (__aty_close(outTlow, 0.0, 0.01) ? "PASS" : "FAIL"));
printf_ATY_D(" OOR High: T = %fC => R = %f, %s\r\n", tNTC[4] + 10.0, outThigh, (__aty_close(outThigh, 0.0, 0.01) ? "PASS" : "FAIL"));
// [63..67] Table RTD R->T endpoints: equals tRTD[-40, 0, 25, 100]
// [68..72] Table RTD T->R endpoints: equals rRTD at tRTD[-40, 0, 25, 100]
double tRTD[5] = {-40.0, 0.0, 25.0, 100.0, 850.0};
// double rRTD[5] = {84.272, 100.0, 109.740, 138.506, 390.481};
double rRTD[4];
for(int i = 0; i < 5; i++) rRTD[i] = ALGO_Temp_RTD_T(tRTD[i]);
for(int i = 0; i < 5; i++){
double o1 = ALGO_RT_Table_R2T(rRTD[i], tRTD, rRTD, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = o1;
if(__aty_close(o1, tRTD[i], 0.01)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D("\r\n[Table RTD R->T] R = %f => T = %fC, %s\r\n", rRTD[i], o1, (__aty_close(o1, tRTD[i], 0.01) ? "PASS" : "FAIL"));
}
for(int i = 0; i < 5; i++){
double o2 = ALGO_RT_Table_T2R(tRTD[i], tRTD, rRTD, 5);
ALGO_Temperature_ATY_Test_Out[idx++] = o2;
if(__aty_close(o2, rRTD[i], 0.02)) ALGO_Temperature_ATY_Test_Pass++; else ALGO_Temperature_ATY_Test_Fail++;
printf_ATY_D(" [Table RTD T->R] T = %fC => R = %f, %s\r\n", tRTD[i], o2, (__aty_close(o2, rRTD[i], 0.02) ? "PASS" : "FAIL"));
}
}
printf_ATY_D("\r\n[ALGO_Temperature_ATY_Test] END: Pass = %d, Fail = %d\r\n", ALGO_Temperature_ATY_Test_Pass, ALGO_Temperature_ATY_Test_Fail);
return ALGO_Temperature_ATY_Test_Fail;
}
#endif /* ALGO_Temperature_ATY_Test_ATY */
/************************************ etc *************************************/
// T ---------------------------------------------------------------------------
// #include "ALGO_Temperature_ATY.h"
// void TempGet(void){
// float MCU_BASE_VOL_D = 1200;//VREFINT_MCU_ATY;
// float BOARD_TEMP = ALGO_VolToKelvinTemp((1000.0 *
// ADC_Get(&hadc1, ADC_CHANNEL_5) / MCU_BASE_VOL_D),
// 3300.0, 10.0, 10.0, 3950, 1);
// printf_ATY_D("\r\nT: %f\r\n", BOARD_TEMP);
// }
#endif /* __ALGO_Temperature_ATY_C */
/******************************** End Of File *********************************/