tsensor.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "stm32l1xx_hal.h"
  2. #include "app/thermo/tsensor_ll.h"
  3. #include "app/thermo/tsensor.h"
  4. #include "core/csect.h"
  5. #include "core/config.h"
  6. // THERMO_SENSOR_KEEP_INITIALIZED
  7. // Do not turn off (=1) the sensor periferal driver btw measures
  8. #define THERMO_SENSOR_KEEP_INITIALIZED 1
  9. // THERMO_SENSOR_AVG_WINDOW
  10. // Digital exp-filter window size
  11. #define THERMO_SENSOR_AVG_WINDOW 24
  12. // THERMO_SENSOR_INTERVAL
  13. // Temperature measuring interval, ms
  14. #define THERMO_SENSOR_INTERVAL CONFIG_TSENSOR_INTERVAL
  15. static tTSensorTemp vThermoSensor_AVGTemp = THERMO_SENSOR_INVALID_TEMP_VALUE;
  16. static size_t vThermoSensor_AVGPoints = 0;
  17. static uint32_t vThermoSensor_LastTick = 0;
  18. static uint32_t vThermoSensor_Interval = THERMO_SENSOR_INTERVAL;
  19. #if THERMO_SENSOR_KEEP_INITIALIZED
  20. static bool vThermoSensor_bPowered = false;
  21. #endif
  22. static void ThermoSensor_UpdateAVGTemp( tTSensorTemp new_value ) ;
  23. static void ThermoSensor_ResetAvgTemp();
  24. static bool ThermoSensor_Serve();
  25. static bool ThermoSensor_GetReady();
  26. static tTSensorTemp ThermoSensor_GetAvgTemp();
  27. static void ThermoSensor_SetInterval(size_t ms);
  28. const sThermoSensorHandle_t ThermoSensor = {
  29. .GetReady = ThermoSensor_GetReady,
  30. .ResetTempAVG = ThermoSensor_ResetAvgTemp,
  31. .ServeSensor = ThermoSensor_Serve,
  32. .GetTempAVG = ThermoSensor_GetAvgTemp,
  33. .SetSensorInterval = ThermoSensor_SetInterval
  34. };
  35. static bool ThermoSensor_GetReady()
  36. {
  37. bool bReady = false;
  38. __DI__
  39. bReady = ( vThermoSensor_AVGPoints > 0 )
  40. && ( vThermoSensor_AVGTemp != THERMO_SENSOR_INVALID_TEMP_VALUE );
  41. __EI__
  42. return bReady;
  43. }
  44. static void ThermoSensor_SetInterval(uint32_t ms)
  45. {
  46. __DI__ vThermoSensor_Interval = ms; __EI__
  47. }
  48. static void ThermoSensor_ResetAvgTemp()
  49. {
  50. DI();
  51. vThermoSensor_AVGTemp = THERMO_SENSOR_INVALID_TEMP_VALUE;
  52. vThermoSensor_AVGPoints = 0;
  53. EI();
  54. }
  55. static tTSensorTemp ThermoSensor_GetAvgTemp()
  56. {
  57. tTSensorTemp value;
  58. __DI__ value = vThermoSensor_AVGTemp; __EI__
  59. return value;
  60. }
  61. static bool ThermoSensor_Serve()
  62. {
  63. bool bServe = false;
  64. __DI__ bServe = (HAL_GetTick() - vThermoSensor_LastTick > vThermoSensor_Interval); __EI__
  65. if( bServe )
  66. {
  67. #if THERMO_SENSOR_KEEP_INITIALIZED
  68. if( !vThermoSensor_bPowered )
  69. {
  70. vThermoSensor_bPowered = I2CTempSensor.Init();
  71. }
  72. if( vThermoSensor_bPowered )
  73. {
  74. tTSensorTemp temp_value;
  75. if( I2CTempSensor.GetTemp( &temp_value ) )
  76. {
  77. ThermoSensor_UpdateAVGTemp( temp_value );
  78. }
  79. else
  80. {
  81. ThermoSensor_ResetAvgTemp();
  82. }
  83. }
  84. #else
  85. if( I2CTempSensor.Init() )
  86. {
  87. tTSensorTemp temp_value;
  88. if( I2CTempSensor.GetTemp( &temp_value ) )
  89. {
  90. ThermoSensor_UpdateAVGTemp( temp_value );
  91. }
  92. else
  93. {
  94. ThermoSensor_ResetAvgTemp();
  95. }
  96. I2CTempSensor.DeInit();
  97. }
  98. else
  99. {
  100. ThermoSensor_ResetAvgTemp();
  101. }
  102. #endif
  103. __DI__ vThermoSensor_LastTick = HAL_GetTick(); __EI__
  104. }
  105. return bServe;
  106. }
  107. // ThermoSensor_UpdateAVGTemp
  108. // Performs averaging with exponential digital filter
  109. static void ThermoSensor_UpdateAVGTemp( tTSensorTemp new_value )
  110. {
  111. DI();
  112. if( (THERMO_SENSOR_INVALID_TEMP_VALUE) == vThermoSensor_AVGTemp )
  113. {
  114. vThermoSensor_AVGTemp = new_value;
  115. vThermoSensor_AVGPoints = 1;
  116. }
  117. else
  118. {
  119. vThermoSensor_AVGTemp = ( new_value + ( vThermoSensor_AVGTemp * vThermoSensor_AVGPoints ) ) / ( vThermoSensor_AVGPoints + 1 );
  120. if( vThermoSensor_AVGPoints < (THERMO_SENSOR_AVG_WINDOW) )
  121. vThermoSensor_AVGPoints++;
  122. // Now @tmp is 16-bit value: [BBBBBBBBBB000000]
  123. // So, lets perform averaging:
  124. // n * AVG[i-1] + tmp
  125. // AVG[i] = -------------------
  126. // n+1
  127. // where
  128. // @AVG[i-1] is averaged temperature before operation,
  129. // @AVG[i] is averaged temperature after operation,
  130. // @n is the filter window size (=24),
  131. // @tmp is momentary measured temperature, [BBBBBBBBBB000000].
  132. //
  133. // So after averaging, bits 5..0 will be filled up.
  134. // Since the sensor has a 0.25*C accuracy, the @tmp should be divided
  135. // by 4 to get the value in degrees. But after averaging the whole accuracy
  136. // is changed due to the bits 5..0 are filled up. So, we need to divide
  137. // the value not 4, but 256 times to get value in degrees:
  138. // /4 - sensor accuracy
  139. // /64 - averaging accuracy (6 bits, 2^6=64)
  140. // So, 4*64 = /256 of degree.
  141. }
  142. EI();
  143. }