2018-07-12 16:29:32 +02:00
# ifndef TEMPERATURESENSOR_H_
# define TEMPERATURESENSOR_H_
2020-02-16 14:59:45 +01:00
# include <framework/thermal/AbstractTemperatureSensor.h>
2018-07-12 16:29:32 +02:00
# include <framework/datapool/DataSet.h>
# include <framework/monitoring/LimitMonitor.h>
2020-01-15 13:52:18 +01:00
/**
* @ brief This building block handles non - linear value conversion and
* range checks for analog temperature sensors .
2020-02-16 14:59:45 +01:00
* @ details This class can be used to perform all necessary tasks for temperature sensors .
* A sensor can be instantiated by calling the constructor .
* The temperature is calculated from an input value with
* the calculateOutputTemperature ( ) function . Range checking and
* limit monitoring is performed automatically .
2020-02-16 16:14:29 +01:00
* The inputType specifies the type of the raw input while the
* limitType specifies the type of the upper and lower limit to check against .
2020-02-16 14:59:45 +01:00
* @ ingroup thermal
2020-01-15 13:52:18 +01:00
*/
2020-02-16 16:14:29 +01:00
template < typename inputType , typename limitType = inputType >
2018-07-12 16:29:32 +02:00
class TemperatureSensor : public AbstractTemperatureSensor {
public :
2020-02-15 18:26:25 +01:00
/**
2020-02-16 14:59:45 +01:00
* This structure contains parameters required for range checking
* and the conversion from the input value to the output temperature .
* a , b and c can be any parameters required to calculate the output
2020-02-21 16:08:43 +01:00
* temperature from the input value , depending on the formula used .
2020-02-16 14:59:45 +01:00
*
* The parameters a , b and c are used in the calculateOutputTemperature ( ) call .
*
2020-04-28 18:58:55 +02:00
* The lower and upper limits can be specified in any type , for example float for C values
2020-02-16 16:14:29 +01:00
* or any other type for raw values .
2020-02-15 18:26:25 +01:00
*/
2018-07-12 16:29:32 +02:00
struct Parameters {
float a ;
float b ;
float c ;
2020-02-16 16:14:29 +01:00
limitType lowerLimit ;
limitType upperLimit ;
2020-02-16 14:59:45 +01:00
float maxGradient ;
2018-07-12 16:29:32 +02:00
} ;
2020-02-15 18:26:25 +01:00
/**
2020-02-16 14:59:45 +01:00
* Forward declaration for explicit instantiation of used parameters .
2020-02-15 18:26:25 +01:00
*/
2018-07-12 16:29:32 +02:00
struct UsedParameters {
UsedParameters ( Parameters parameters ) :
2020-02-15 18:26:25 +01:00
a ( parameters . a ) , b ( parameters . b ) , c ( parameters . c ) ,
2020-02-16 14:59:45 +01:00
gradient ( parameters . maxGradient ) { }
2018-07-12 16:29:32 +02:00
float a ;
float b ;
float c ;
float gradient ;
} ;
2020-02-16 14:59:45 +01:00
/**
2020-02-21 16:08:43 +01:00
* Instantiate Temperature Sensor Object .
2020-02-16 14:59:45 +01:00
* @ param setObjectid objectId of the sensor object
* @ param inputValue Input value which is converted to a temperature
* @ param poolVariable Pool Variable to store the temperature value
* @ param vectorIndex Vector Index for the sensor monitor
* @ param parameters Calculation parameters , temperature limits , gradient limit
* @ param datapoolId Datapool ID of the output temperature
* @ param outputSet Output dataset for the output temperature to fetch it with read ( )
* @ param thermalModule respective thermal module , if it has one
*/
TemperatureSensor ( object_id_t setObjectid ,
2020-02-16 16:14:29 +01:00
inputType * inputValue , PoolVariableIF * poolVariable ,
uint8_t vectorIndex , uint32_t datapoolId , Parameters parameters = { 0 , 0 , 0 , 0 , 0 , 0 } ,
2020-02-16 14:59:45 +01:00
DataSet * outputSet = NULL , ThermalModuleIF * thermalModule = NULL ) :
AbstractTemperatureSensor ( setObjectid , thermalModule ) , parameters ( parameters ) ,
inputValue ( inputValue ) , poolVariable ( poolVariable ) ,
outputTemperature ( datapoolId , outputSet , PoolVariableIF : : VAR_WRITE ) ,
2020-02-16 16:14:29 +01:00
sensorMonitor ( setObjectid , DOMAIN_ID_SENSOR ,
2020-02-16 14:59:45 +01:00
DataPool : : poolIdAndPositionToPid ( poolVariable - > getDataPoolId ( ) , vectorIndex ) ,
2020-02-16 16:14:29 +01:00
DEFAULT_CONFIRMATION_COUNT , parameters . lowerLimit , parameters . upperLimit ,
TEMP_SENSOR_LOW , TEMP_SENSOR_HIGH ) ,
oldTemperature ( 20 ) , uptimeOfOldTemperature ( { INVALID_TEMPERATURE , 0 } ) {
2020-02-16 14:59:45 +01:00
}
protected :
/**
* This formula is used to calculate the temperature from an input value
* with an arbitrary type .
* A default implementation is provided but can be replaced depending
* on the required calculation .
* @ param inputTemperature
* @ return
*/
2020-02-16 16:14:29 +01:00
virtual float calculateOutputTemperature ( inputType inputValue ) {
2020-02-16 14:59:45 +01:00
return parameters . a * inputValue * inputValue
+ parameters . b * inputValue + parameters . c ;
}
2018-07-12 16:29:32 +02:00
private :
void setInvalid ( ) {
outputTemperature = INVALID_TEMPERATURE ;
outputTemperature . setValid ( false ) ;
uptimeOfOldTemperature . tv_sec = INVALID_UPTIME ;
2020-02-16 16:14:29 +01:00
sensorMonitor . setToInvalid ( ) ;
2018-07-12 16:29:32 +02:00
}
protected :
static const int32_t INVALID_UPTIME = 0 ;
UsedParameters parameters ;
2020-02-16 16:14:29 +01:00
inputType * inputValue ;
2018-07-12 16:29:32 +02:00
PoolVariableIF * poolVariable ;
PoolVariable < float > outputTemperature ;
2020-02-16 16:14:29 +01:00
LimitMonitor < limitType > sensorMonitor ;
2018-07-12 16:29:32 +02:00
float oldTemperature ;
timeval uptimeOfOldTemperature ;
void doChildOperation ( ) {
if ( ! poolVariable - > isValid ( )
| | ! healthHelper . healthTable - > isHealthy ( getObjectId ( ) ) ) {
setInvalid ( ) ;
return ;
}
2020-02-16 14:59:45 +01:00
outputTemperature = calculateOutputTemperature ( * inputValue ) ;
2018-07-12 16:29:32 +02:00
outputTemperature . setValid ( PoolVariableIF : : VALID ) ;
timeval uptime ;
Clock : : getUptime ( & uptime ) ;
if ( uptimeOfOldTemperature . tv_sec ! = INVALID_UPTIME ) {
//In theory, we could use an AbsValueMonitor to monitor the gradient.
2020-02-16 14:59:45 +01:00
//But this would require storing the maxGradient in DP and quite some overhead.
2018-07-12 16:29:32 +02:00
//The concept of delta limits is a bit strange anyway.
float deltaTime ;
float deltaTemp ;
deltaTime = ( uptime . tv_sec + uptime . tv_usec / 1000000. )
- ( uptimeOfOldTemperature . tv_sec
+ uptimeOfOldTemperature . tv_usec / 1000000. ) ;
deltaTemp = oldTemperature - outputTemperature ;
if ( deltaTemp < 0 ) {
deltaTemp = - deltaTemp ;
}
if ( parameters . gradient < deltaTemp / deltaTime ) {
triggerEvent ( TEMP_SENSOR_GRADIENT ) ;
//Don't set invalid, as we did not recognize it as invalid with full authority, let FDIR handle it
}
}
2020-04-28 18:58:55 +02:00
//Check is done against raw limits. SHOULDDO: Why? Using <20> C would be more easy to handle.
2020-02-16 16:14:29 +01:00
sensorMonitor . doCheck ( outputTemperature . value ) ;
2018-07-12 16:29:32 +02:00
2020-02-16 16:14:29 +01:00
if ( sensorMonitor . isOutOfLimits ( ) ) {
2018-07-12 16:29:32 +02:00
uptimeOfOldTemperature . tv_sec = INVALID_UPTIME ;
outputTemperature . setValid ( PoolVariableIF : : INVALID ) ;
outputTemperature = INVALID_TEMPERATURE ;
} else {
oldTemperature = outputTemperature ;
uptimeOfOldTemperature = uptime ;
}
}
public :
float getTemperature ( ) {
return outputTemperature ;
}
bool isValid ( ) {
return outputTemperature . isValid ( ) ;
}
2020-02-16 14:59:45 +01:00
static const uint16_t ADDRESS_A = 0 ;
static const uint16_t ADDRESS_B = 1 ;
static const uint16_t ADDRESS_C = 2 ;
static const uint16_t ADDRESS_GRADIENT = 3 ;
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1 ; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.)
static const uint8_t DOMAIN_ID_SENSOR = 1 ;
2018-07-12 16:29:32 +02:00
virtual ReturnValue_t getParameter ( uint8_t domainId , uint16_t parameterId ,
ParameterWrapper * parameterWrapper ,
const ParameterWrapper * newValues , uint16_t startAtIndex ) {
2020-02-16 16:14:29 +01:00
ReturnValue_t result = sensorMonitor . getParameter ( domainId , parameterId ,
2018-07-12 16:29:32 +02:00
parameterWrapper , newValues , startAtIndex ) ;
if ( result ! = INVALID_DOMAIN_ID ) {
return result ;
}
if ( domainId ! = this - > DOMAIN_ID_BASE ) {
return INVALID_DOMAIN_ID ;
}
switch ( parameterId ) {
case ADDRESS_A :
parameterWrapper - > set ( parameters . a ) ;
break ;
case ADDRESS_B :
parameterWrapper - > set ( parameters . b ) ;
break ;
case ADDRESS_C :
parameterWrapper - > set ( parameters . c ) ;
break ;
case ADDRESS_GRADIENT :
parameterWrapper - > set ( parameters . gradient ) ;
break ;
default :
return INVALID_MATRIX_ID ;
}
return HasReturnvaluesIF : : RETURN_OK ;
}
virtual void resetOldState ( ) {
2020-02-16 16:14:29 +01:00
sensorMonitor . setToUnchecked ( ) ;
2018-07-12 16:29:32 +02:00
}
} ;
# endif /* TEMPERATURESENSOR_H_ */