Files
cm_heatsink_emulator/cm_heatsink_emulator.c
2025-10-14 14:25:20 +02:00

106 lines
2.7 KiB
C

/*
* cm_heatsink_emulator.c
*
* Created on: 14 Oct 2025
* Author: Christian L. V. Madsen (OZ1CM)
*/
#include "cm_heatsink_emulator.h"
#include "math.h"
#define EULER_NUM 2.7182818284590452353602
static int isStructOk(cm_heatsinkEmul_t *inst){
if(inst == NULL)return 0;
if(inst->thermalElements == NULL)return 0;
if(inst->thermalElements_Counts == 0)return 0;
return 1;
}
static float deltaTempElement(cm_heatsink_thermalElement_t *element, float temperature, float power, float fan_speed){
if((fan_speed > 0.0) && (fan_speed <= 1.0)){
float dtemp = element->R_th_MaxFan - element->R_th_MinFan;
return power * (element->R_th_MinFan + (dtemp * fan_speed));
}else{
// Kelvin = Watt * K/W
return (power * element->R_th);
}
}
static float updateCthFromFan(cm_heatsink_thermalElement_t *element, float fan_speed){
if((fan_speed > 0.0) && (fan_speed <= 1.0)){
float dc = element->C_th_MaxFan - element->C_th_MinFan;
return (element->C_th_MinFan + (dc * fan_speed));
}else{
return element->C_th;
}
}
int cm_heatsinkEmul_iterate(cm_heatsinkEmul_t *inst, float dtime){
if(!isStructOk(inst)) return 1;
float dtemp = inst->ambientTemp;
// We begin from ambient temperature and move up towards heat source.
for(int i = (inst->thermalElements_Counts-1); i >= 0; i--){
// Calculate temperature until we reach requested element!
dtemp += deltaTempElement(&inst->thermalElements[i], dtemp, inst->power, inst->fan_speed);
float C_th = updateCthFromFan(&inst->thermalElements[i], inst->fan_speed);
// Do so the temperature has the responsetime as the heatsink.
inst->thermalElements[i].temperature = inst->thermalElements[i].temperature + (1.0 / C_th) * (dtemp - inst->thermalElements[i].temperature) * dtime;
}
return 0;
}
float cm_heatsinkEmul_getElementTemp(cm_heatsinkEmul_t *inst, int element_idx){
if(!isStructOk(inst)) return 0.0;
if(element_idx > (inst->thermalElements_Counts-1)) return 0.0;
return inst->thermalElements[element_idx].temperature;
}
int cm_heatsinkEmul_setFan(cm_heatsinkEmul_t *inst, float fan_speed){
if(!isStructOk(inst)) return 1;
inst->fan_speed = fan_speed;
return 0;
}
int cm_heatsinkEmul_init(cm_heatsinkEmul_t *inst, cm_heatsink_thermalElement_t *elements, int elements_Count, float C_th, float power, float ambientTemp){
if(inst == NULL)return 1;
if(elements == NULL)return 1;
if(elements_Count == 0)return 1;
inst->thermalElements = elements;
inst->thermalElements_Counts = elements_Count;
inst->power = power;
inst->ambientTemp = ambientTemp;
// Dynamic values
inst->fan_speed = 0;
// Assume all elements is equal to ambient before we start!
for(int i = (inst->thermalElements_Counts-1); i >= 0; i--){
inst->thermalElements[i].temperature = inst->ambientTemp;
}
return 0;
}