#ifndef __ADCMEAS_H__ #define __ADCMEAS_H__ #include #include #include /** * @brief Moving average filter coefficient for PT1000 measurement */ #define ADC_PT1000_FILTER_WEIGHT 0.005f /** * @brief ADC channel number of PT1000 sensor input */ #define ADC_PT1000_CHANNEL 2U #define ADC_PT1000_PORT GPIOA #define ADC_PT1000_PORT_RCC_MASK RCC_AHB1ENR_GPIOAEN #define ADC_PT1000_PIN 2U #define ADC_FILTER_STARTUP_CYCLES 800U #define ADC_PT1000_SAMPLE_CNT_DELAY 1000U #define ADC_PT1000_DMA_AVG_SAMPLES 6U /** * @brief Lower value for valid input range for PT1000 measurement * * If the input of the PT1000 sensor is below this value, an error is thrown. This is used to disable the temperature control loop */ #define ADC_PT1000_LOWER_WATCHDOG 200U /** * @brief Upper value for valid input range for PT1000 measurement * * If the input of the PT1000 sensor is above this value, an error is thrown. This is used to disable the temperature control loop */ #define ADC_PT1000_UPPER_WATCHDOG 4000U enum adc_pt1000_error {ADC_PT1000_NO_ERR= 0, ADC_PT1000_WATCHDOG_ERROR=(1UL<<0), ADC_PT1000_OVERFLOW=(1UL<<1)}; /** * @brief This function sets up the ADC measurement fo the external PT1000 temperature sensor * * Used peripherals: * - Timer 2 for sampling control * - ADC1 * * The filter weight \f$\alpha\f$ is configured for @ref ADC_PT1000_FILTER_WEIGHT * */ void adc_pt1000_setup_meas(); /** * @brief Set moving average filter parameters * * The sampled resistance value is filtered with an exponential average filter * specified by following difference equation: * * \f$ y[n] = (1-\alpha)y[n-1] + \alpha x[n] \f$ * * @param alpha */ void adc_pt1000_set_moving_average_filter_param(float alpha); /** * @brief Set the calibration data for the PT1000 measurement * * The resulting resistance reading is * \f$R_{corrected} = (1 + \sigma) R_{raw} + O\f$ * * @param offset Offset \f$O\f$ * @param sensitivity_deviation Sensitivity Deviation \f$\sigma\f$ after offset correction */ void adc_pt1000_set_resistance_calibration(float offset, float sensitivity_deviation, bool active); /** * @brief Get the state and values of the resistance calibration * @param offset Offset * @param sensitivity_deviation Sensitivity deviation * @param active Active state of the correction */ void adc_pt1000_get_resistance_calibration(float *offset, float *sensitivity_deviation, bool *active); /** * @brief Get the current reistance value * * If the reistance calibration is enabled, this function applies the calculations of the raw reistance reading and * returns the corrected value. * * If an ADC error is set, the status is negative. The status is 2 during the first measurements with a given filter setting. Technically, the resistance value is * correct but the filter is not stable yet. * Use adc_pt1000_check_error to check the error and reinitialize the ADC. * * * @param[out] resistance Resistance output in Ohms * @return Status */ int adc_pt1000_get_current_resistance(float *resistance); /** * @brief Stream the raw ADC data to an array in memory. * * Streaming is done using DMA2 Stream0. * This function is used for gathering fullspeed sampling data for external interfaces or calibration * * @param adc_array Array to stream data to * @param length Amount of data points to be measured * @param flag_to_set This flag is set to 1 once the data has been measured and is transferred. A negative value indicates an error * @return 0 if measurement could be started */ int adc_pt1000_stream_raw_value_to_memory(float *adc_array, uint32_t length, volatile uint8_t *flag_to_set); void adc_pt1000_convert_raw_value_array_to_resistance(float *resistance_dest, float *raw_source, uint32_t count); /** * @brief Check if the ADC measurement experienced any kind of error (DMA, Analog Watchdog, etc...) * * In case of an error, it may be necessary to call adc_pt1000_setup_meas() again in order to recover from the error */ enum adc_pt1000_error adc_pt1000_check_error(); void adc_pt1000_clear_error(); void adc_pt1000_disable(); #endif // __ADCMEAS_H__