/** * @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 *********************************/