| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- /**
- * @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 -
- * <a href="https://mengze.top/MZ-ATY_VCJS">
- * https://mengze.top/MZ-ATY_VCJS</a>
- * - CC 4.0 BY-NC-SA -
- * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
- * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
- * - 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 <math.h>
- #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 *********************************/
|