NTCtsensor.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "stm32l1xx_hal.h"
  2. #include "app/thermo/NTCtsensor.h"
  3. #include "core/csect.h"
  4. #include "core/config.h"
  5. #include "core/config_pins.h"
  6. #include "drivers/adc/adc.h"
  7. #include "app/nfm/nfm_base.h"
  8. #include "math.h"
  9. // THERMO_SENSOR_KEEP_INITIALIZED
  10. // Do not turn off (=1) the sensor periferal driver btw measures
  11. #define NTC_THERMO_SENSOR_KEEP_INITIALIZED 1
  12. // THERMO_SENSOR_AVG_WINDOW
  13. // Digital exp-filter window size
  14. #define NTC_THERMO_SENSOR_AVG_WINDOW 8
  15. // THERMO_SENSOR_INTERVAL
  16. // Temperature measuring interval, ms
  17. #define NTC_DETECTION_HIGH_LEVEL 3970 // (3.2v) Value that indicates existance of sensor on line
  18. #define NTC_DETECTION_LOW_LEVEL 15 // (0.012v) Value that indicates existance of sensor on line
  19. #define NTC_THERMO_SENSOR_INTERVAL CONFIG_NTC_TSENSOR_INTERVAL
  20. #define NTC_LOW_RESISTANCE 1e3
  21. #define NTC_HIGH_RESISTANCE 35e4
  22. #define NTC_DEFAULT_TEMP_COEFF 3988
  23. static tNTCSensorTemp vNtcThermoSensor_AVGTemp = THERMO_SENSOR_INVALID_TEMP_VALUE;
  24. static size_t vNtcThermoSensor_AVGPoints = 0;
  25. static uint32_t vNtcThermoSensor_LastTick = 0;
  26. static uint32_t vNtcThermoSensor_Interval = NTC_THERMO_SENSOR_INTERVAL;
  27. static bool vNtcThermoSensor_bInitialized = false;
  28. static bool NtcThermoSensor_Init();
  29. static void NtcThermoSensor_UpdateAVGTemp( tNTCSensorTemp new_value ) ;
  30. static void NtcThermoSensor_ResetAvgTemp();
  31. static bool NtcThermoSensor_Serve();
  32. static bool NtcThermoSensor_GetReady();
  33. static tNTCSensorTemp NtcThermoSensor_GetAvgTemp();
  34. static void NtcThermoSensor_SetInterval(size_t ms);
  35. static bool NtcThermoSensor_GetAdcValue( tNTCSensorTemp * temp );
  36. static void NtcUpdateCurrentTempCoeff(uint16_t temp_coeff);
  37. const sNtcThermoSensorHandle_t NtcThermoSensor = {
  38. .Init = NtcThermoSensor_Init,
  39. .GetReady = NtcThermoSensor_GetReady,
  40. .ResetTempAVG = NtcThermoSensor_ResetAvgTemp,
  41. .ServeSensor = NtcThermoSensor_Serve,
  42. .GetTempAVG = NtcThermoSensor_GetAvgTemp,
  43. .SetSensorInterval = NtcThermoSensor_SetInterval,
  44. .UpdateCurrentTempCoeff = NtcUpdateCurrentTempCoeff
  45. };
  46. static uint16_t B_coeff = 0;
  47. static bool NtcThermoSensor_Init()
  48. {
  49. GPIO_InitTypeDef GPIO_NTC = {0};
  50. GPIO_NTC.Pin = CONFIG_PIN__NTC_TSENS_PWR;
  51. GPIO_NTC.Mode = GPIO_MODE_ANALOG;
  52. GPIO_NTC.Pull = GPIO_NOPULL;
  53. HAL_GPIO_Init(CONFIG_PORT__NTC_TSENS_PWR, &GPIO_NTC);
  54. if(!NFMClass->methods.tempCoefficient.getTempCoeff(&B_coeff))
  55. {
  56. B_coeff = NTC_DEFAULT_TEMP_COEFF;
  57. }
  58. return true;
  59. }
  60. static bool NtcThermoSensor_GetReady()
  61. {
  62. bool bReady = false;
  63. __DI__
  64. bReady = ( vNtcThermoSensor_AVGPoints > 0 )
  65. && ( vNtcThermoSensor_AVGTemp != THERMO_SENSOR_INVALID_TEMP_VALUE );
  66. __EI__
  67. return bReady;
  68. }
  69. static void NtcThermoSensor_SetInterval(uint32_t ms)
  70. {
  71. __DI__ vNtcThermoSensor_Interval = ms; __EI__
  72. }
  73. static void NtcThermoSensor_ResetAvgTemp()
  74. {
  75. DI();
  76. vNtcThermoSensor_AVGTemp = THERMO_SENSOR_INVALID_TEMP_VALUE;
  77. vNtcThermoSensor_AVGPoints = 0;
  78. EI();
  79. }
  80. static tNTCSensorTemp NtcThermoSensor_GetAvgTemp()
  81. {
  82. tNTCSensorTemp value;
  83. __DI__ value = vNtcThermoSensor_AVGTemp; __EI__
  84. return value;
  85. }
  86. static int NtcThermoSensor_GetTempFromVoltage( tADCValue_t * adc_code )
  87. {
  88. uint16_t voltage = *adc_code * 3300 / 4095;
  89. float T1 = 298;
  90. double R1 = 10e3;
  91. double R2 = R1 * voltage / (3300 - voltage); // Resistance of NTC
  92. if(R2 <= NTC_LOW_RESISTANCE) R2 = NTC_LOW_RESISTANCE;
  93. if(R2 >= NTC_HIGH_RESISTANCE) R2 = NTC_HIGH_RESISTANCE;
  94. float b_value = ((log(R1)) - (log(R2))) / B_coeff;
  95. float temperature = (1 / ( (1 / T1) - b_value)) - 273;
  96. return (int)(temperature * 100); // in °C
  97. }
  98. static bool NtcThermoSensor_GetAdcValue( tNTCSensorTemp * temp )
  99. {
  100. tADCValue_t value;
  101. if(ADC1Handle.Start(CONFIG_ADC_CHANNEL_NTC_TSENS))
  102. {
  103. if(ADC1Handle.Measure(100, &value))
  104. {
  105. if(value <= NTC_DETECTION_HIGH_LEVEL && value >= NTC_DETECTION_LOW_LEVEL)
  106. {
  107. *temp = NtcThermoSensor_GetTempFromVoltage(&value); //Debug
  108. return true;
  109. }
  110. }
  111. }
  112. return false;
  113. }
  114. static void NtcUpdateCurrentTempCoeff(uint16_t temp_coeff)
  115. {
  116. B_coeff = temp_coeff;
  117. }
  118. static bool NtcThermoSensor_Serve()
  119. {
  120. bool bServe = false;
  121. __DI__ bServe = (HAL_GetTick() - vNtcThermoSensor_LastTick > vNtcThermoSensor_Interval); __EI__
  122. if( bServe )
  123. {
  124. if( !vNtcThermoSensor_bInitialized )
  125. {
  126. vNtcThermoSensor_bInitialized = NtcThermoSensor_Init();
  127. }
  128. if( vNtcThermoSensor_bInitialized )
  129. {
  130. tNTCSensorTemp temp_value;
  131. if( NtcThermoSensor_GetAdcValue( &temp_value ) )
  132. {
  133. NtcThermoSensor_UpdateAVGTemp( temp_value );
  134. }
  135. else
  136. {
  137. NtcThermoSensor_ResetAvgTemp();
  138. }
  139. }
  140. __DI__ vNtcThermoSensor_LastTick = HAL_GetTick(); __EI__
  141. }
  142. return bServe;
  143. }
  144. // ThermoSensor_UpdateAVGTemp
  145. // Performs averaging with exponential digital filter
  146. static void NtcThermoSensor_UpdateAVGTemp( tNTCSensorTemp new_value )
  147. {
  148. DI();
  149. if( (THERMO_SENSOR_INVALID_TEMP_VALUE) == vNtcThermoSensor_AVGTemp )
  150. {
  151. vNtcThermoSensor_AVGTemp = new_value;
  152. vNtcThermoSensor_AVGPoints = 1;
  153. }
  154. else
  155. {
  156. vNtcThermoSensor_AVGTemp = ( new_value + (tNTCSensorTemp)( vNtcThermoSensor_AVGTemp * vNtcThermoSensor_AVGPoints ) ) / (tNTCSensorTemp)( vNtcThermoSensor_AVGPoints + 1 );
  157. if( vNtcThermoSensor_AVGPoints < (NTC_THERMO_SENSOR_AVG_WINDOW) )
  158. vNtcThermoSensor_AVGPoints++;
  159. // Now @tmp is 16-bit value: [BBBBBBBBBB000000]
  160. // So, lets perform averaging:
  161. // n * AVG[i-1] + tmp
  162. // AVG[i] = -------------------
  163. // n+1
  164. // where
  165. // @AVG[i-1] is averaged temperature before operation,
  166. // @AVG[i] is averaged temperature after operation,
  167. // @n is the filter window size (=24),
  168. // @tmp is momentary measured temperature, [BBBBBBBBBB000000].
  169. //
  170. // So after averaging, bits 5..0 will be filled up.
  171. // Since the sensor has a 0.25*C accuracy, the @tmp should be divided
  172. // by 4 to get the value in degrees. But after averaging the whole accuracy
  173. // is changed due to the bits 5..0 are filled up. So, we need to divide
  174. // the value not 4, but 256 times to get value in degrees:
  175. // /4 - sensor accuracy
  176. // /64 - averaging accuracy (6 bits, 2^6=64)
  177. // So, 4*64 = /256 of degree.
  178. }
  179. EI();
  180. }