Newer
Older
/*
* temperatureRegulation.c
*
* Created on: Apr 16, 2023
* Author: Flax
*
* Prefix : REG
*/
// ==============
// Local includes
// ==============
#include "temperatureRegulation.h"
// ==============
// Local typedefs
// ==============
typedef enum {
REG_MODE_OFF,
REG_MODE_REGUL,
REG_MODE_ADC_PRE,
REG_MODE_ADC_START,
REG_MODE_ADC_WAIT,
}e_REGMode;
// ===============
// 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)
#define cREGAdcAcqCycle (100U)
#define mREGSetPwm(val) (mREGPwmSetCompareValue(cREGPwmMax - val))
// ===============
// Local variables
// ===============
static e_REGMode RegModeCurrent_E;
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;
// ADC
static uint16_t RegAdcCycleCnt_U16;
static bool RegAdcOngoing_B;
// 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;
RegModeCurrent_E = REG_MODE_OFF;
// 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);
RegModeCurrent_E = REG_MODE_ADC_PRE;
}
void REGStop (void)
{
}
void REGCyclicTask (void)
{
case REG_MODE_OFF:
break;
case REG_MODE_REGUL:
if (RegAdcCycleCnt_U16 < cREGAdcAcqCycle)
if (mREGAdcIsReady())
{
RegAdcOngoing_B = true;
RegModeCurrent_E = REG_MODE_ADC_PRE;
}
else
{
// ADC not ready
RegTempMeasBuffer_U16A[1] = 0xFFFF;
RegAdcCycleCnt_U16 = 0;
}
break;
case REG_MODE_ADC_PRE:
RegModeCurrent_E = REG_MODE_ADC_START;
break;
case REG_MODE_ADC_START:
mREGAdcStartConversion();
RegModeCurrent_E = REG_MODE_ADC_WAIT;
break;
case REG_MODE_ADC_WAIT:
if (mREGAdcEndOfConversion() == true)
// Read ADC input
RegTempMeasBuffer_U16A[1] = mREGAdcReadValue();
// 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];
if (RegTempMeasBuffer_U16A[1] >= cREGAdcErrorThres)
{
// Error
RegErrorState_B = true;
}
RegAdcCycleCnt_U16 = 0;
RegAdcOngoing_B = false;
RegModeCurrent_E = REG_MODE_REGUL;
break;
default:
break;
}
// 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;
}
if (RegAdcOngoing_B == false)
{
// mREGSetPwm(cREGPwmMax);
mREGSetPwm(RegPwmDyc_U32);
//mREGPwmSetCompareValue(cREGPwmMax / 32);
}
else
{
// No switching during ADC acquisition
mREGSetPwm(0U);
}
// 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;
}
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
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;
}