Skip to content
Snippets Groups Projects
temperatureRegulation.c 5.19 KiB
Newer Older
/*
 * temperatureRegulation.c
 *
 *  Created on: Apr 16, 2023
 *      Author: Flax
 *
 *      Prefix : REG
 */

// ==============
// Local includes
// ==============
#include "register.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 RegTempSPTStby_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 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;
	mREGAdcStopConversion();
	if (mREGAdcIsReady())
	{
		// Trigger conversion
		mREGAdcStartConversion();

		// Read ADC input
		RegTempMeasBuffer_U16A[1] = mREGAdcReadValue();

		if (RegTempMeasBuffer_U16A[1] >= cREGAdcErrorThres)
		{
			// Error
			RegErrorState_B = true;
		}
	}
	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;
		}
	{ // Shut the PWM down
		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;
	}

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)
{
	return RegTempDegFilt_U16;

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;
}

uint16_t REGTempPhysDeg (void)
{
	return (RegTempDeg_U16);
}