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 (65535)
#define cRegPIDProp (10)
#define cRegPIDInteg (10)
#define cRegPIDDeriv (10)
// 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 cREGAdcToTempFilter (200U)
// ===============
// 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;
// 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;
}
void REGStart (void)
{
mREDAdcEnable();
}
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;
}
// 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;
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 (RegPwmDyc_S32 > 0)
{// Only keep positive values
RegPwmDyc_U32 = RegPwmDyc_S32;
}
else if (RegPwmDyc_S32 > (int32_t)cREGPwmMax)
{
RegPwmDyc_U32 = (uint32_t)cREGPwmMax;
}
else
{
RegPwmDyc_U32 = 0U;
}
// Set PWM output duty cycle
mREGPwmSetCompareValue(RegPwmDyc_U32);
// Calculate physical temperature
// Transfer function
if (RegTempFiltCnt_U16 < cREGAdcToTempFilter)
{
RegTempFiltCnt_U16++;
}
else
{ // Sub-sampling for cleaner display
RegTempFiltCnt_U16 = 0U;
RegTempDegFilt_U16 = RegTempDeg_U16;
}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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;
}