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