Newer
Older
/*
* temperatureRegulation.c
*
* Created on: Apr 16, 2023
* Author: Flax
*
* Prefix : REG
*/
// ==============
// Local includes
// ==============
#include "temperatureRegulation.h"
// ===============
// Local constants
// ===============
#define cREGTempSPTMax (400U)
#define cREGTempSPTMin (50U)
#define cREGTempSPTDft (250U)
#define cREGTempSPTStbyDft (100U)
#define cREGPwmMax (1023)
#define cREGErrorTempThres (50)
#define cREGErrorTimeout (5000)
#define cRegPIDInteg (5)
#define cRegPIDDeriv (5)
// Temperature measure transfer function parameters
// OPA gain : 681
// Input divider bridge gain : 100k / (100k + 5k6) = 0.946969
// On legacy Arduino code : gain = 0.39, offset = 23.9, resolution 10 bits
// Translated to 12 bits : 0.0975 ~= 100 / 1024
#define ADC_TO_TEMP_GAIN_NUM (100U)
#define ADC_TO_TEMP_GAIN_DEN (1024U)
#define ADC_TO_TEMP_OFFSET (24U)
#define cREGAdcErrorThres (4090U)
// ===============
// Local variables
// ===============
static bool RegOffState_B;
static bool RegStandbyState_B;
static bool RegErrorState_B;
static uint16_t RegTempSPT_U16;
static uint16_t RegTempMeas_U16[2U];
static uint16_t RegTempMeasBuffer_U16A[2U];
static int32_t RegPwmDyc_S32;
static uint32_t RegPwmDyc_U32;
static uint16_t RegTempDeg_U16;
static uint16_t RegTempDegFilt_U16;
static uint16_t RegTempFiltCnt_U16;
static uint32_t RegErrorTimeoutCnt_U32;
// PID
static int32_t RegEpsilon_S32A[2U];
// ==========================
// Local functions prototypes
// ==========================
// ===========================
// Local functions definitions
// ===========================
// ============================
// Shared functions definitions
// ============================
void REGInit (void)
{
RegOffState_B = true;
RegStandbyState_B = false;
// TODO : load NVM values
RegTempSPT_U16 = cREGTempSPTDft;
RegTempSPTStby_U16 = cREGTempSPTStbyDft;
RegErrorTimeoutCnt_U32 = cREGErrorTimeout;
}
void REGStart (void)
{
mREDAdcEnable();
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
LL_TIM_EnableCounter(TIM2);
}
void REGStop (void)
{
}
void REGCyclicTask (void)
{
if (mREGAdcIsReady())
{
// Trigger conversion
mREGAdcStartConversion();
// Read ADC input
RegTempMeasBuffer_U16A[1] = mREGAdcReadValue();
if (RegTempMeasBuffer_U16A[1] >= cREGAdcErrorThres)
{
// Error
}
}
else
{
// ADC not ready
RegTempMeasBuffer_U16A[1] = 0xFFFF;
}
if (RegTempFiltCnt_U16 < cREGAdcToTempFilter)
{
// RegTempFiltCnt_U16++;
}
else
{
// Calculate average
RegTempMeasBuffer_U16A[0] += RegTempMeasBuffer_U16A[1];
RegTempMeasBuffer_U16A[0] = RegTempMeasBuffer_U16A[0] >> 1U;
RegTempMeas_U16[1] = RegTempMeas_U16[0]; // Memorise previous value
RegTempMeas_U16[0] = RegTempMeasBuffer_U16A[0];
// Convert to degrees
RegTempDeg_U16 = (uint16_t)(((((uint32_t)ADC_TO_TEMP_GAIN_NUM * (uint32_t)(RegTempMeas_U16[0])) / (uint32_t)ADC_TO_TEMP_GAIN_DEN) + (uint32_t)ADC_TO_TEMP_OFFSET) & (uint32_t)0x0000FFFF);
// PID
RegEpsilon_S32A[1] = RegEpsilon_S32A[0]; // Memorise previous value
RegEpsilon_S32A[0] = RegTempSPT_U16 - RegTempDeg_U16;
// Check error - Overheat
if (RegEpsilon_S32A[0] > cREGErrorTempThres)
{
if (RegErrorTimeoutCnt_U32 > 0)
{
RegErrorTimeoutCnt_U32--;
}
else
{
// Error - Too much temperature error for too long
RegErrorState_B = true;
}
}
else
{
RegErrorTimeoutCnt_U32 = cREGErrorTimeout;
}
// Process PID output
RegPwmDyc_S32 = (RegEpsilon_S32A[0] * cRegPIDProp)
+ ((RegEpsilon_S32A[0] - RegEpsilon_S32A[1]) * cRegPIDDeriv)
+ ((RegEpsilon_S32A[0] + RegEpsilon_S32A[1]) * cRegPIDInteg);
// Check regulation state before processing the output PWM
// if ((RegErrorState_B == false) && (RegOffState_B == false))
if ((RegOffState_B == false))
{
RegPwmDyc_U32 = (uint32_t)cREGPwmMax;
}
else if (RegPwmDyc_S32 > 0)
{// Only keep positive values
RegPwmDyc_U32 = RegPwmDyc_S32;
}
else
{
RegPwmDyc_U32 = 0U;
}
// Output is reversed
mREGPwmSetCompareValue(cREGPwmMax - RegPwmDyc_U32);
// Filter physical temperature - for cleaner display
if (RegTempFiltCnt_U16 < cREGAdcToTempFilter)
{
RegTempFiltCnt_U16++;
}
else
{ // Sub-sampling for cleaner display
RegTempFiltCnt_U16 = 0U;
RegTempDegFilt_U16 = RegTempDeg_U16;
}
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
bool REGIsError (void)
{
return RegErrorState_B;
}
bool REGIsStandby(void)
{
return RegStandbyState_B;
}
bool REGIsOff(void)
{
return RegOffState_B;
}
void REGErrorReset (void)
{
RegOffState_B = false;
}
void REGStandbySet(void)
{
RegStandbyState_B = true;
}
void REGStandbyReset(void)
{
RegStandbyState_B = false;
}
void REGOffSet(void)
{
RegOffState_B = true;
}
void REGOffReset(void)
{
RegOffState_B = false;
}
bool REGSPTSet (uint16_t temp_spt_u16)
{
bool ret_B = false;
if ((temp_spt_u16 <= (uint16_t)cREGTempSPTMax) && (temp_spt_u16 >= (uint16_t)cREGTempSPTMin))
{
RegTempSPT_U16 = temp_spt_u16;
ret_B = true;
}
return (ret_B);
}
uint16_t REGSPTGet (void)
{
return RegTempSPT_U16;
}
uint16_t REGTempGet (void)
{
bool REGSPTStbySet (uint16_t temp_spt_u16)
{
bool ret_B = false;
if ((temp_spt_u16 <= (uint16_t)cREGTempSPTMax) && (temp_spt_u16 >= (uint16_t)cREGTempSPTMin))
{
RegTempSPTStby_U16 = temp_spt_u16;
ret_B = true;
}
return (ret_B);
}
uint16_t REGSPTStbyGet (void)
{
return RegTempSPTStby_U16;
}