SideLaserTemp.c 8.9 KB
#include <stdio.h>
#include "JZsdkLib.h"
#include "BaseConfig.h"

#include "SideLaser.h"



static JZsdkSideLaserTemp g_LaserTemp;

static int SideLaserSetlumen(int lumen)
{
    UIcontrol_SideLaser_SetLumen(NO_SPECIFIED, JZ_FLAGCODE_OFF, lumen);
}


// 亮度范围限制函数 (0-100)
static int clamp_lumen(int lumen)
{
    if (lumen < 0) return 0;
    if (lumen > 100) return 100;
    return lumen;
}


// 计算温控调节亮度(线性调节,基于0-100范围)
static int calculate_throttled_lumen(int target_lumen, int current_temp)
{
    if (current_temp <= g_LaserTemp.mintemp) {
        return target_lumen;  // 温度正常,全亮度
    }

    if (current_temp >= g_LaserTemp.maxtemp) {
        return g_LaserTemp.SafeMinLumen;  // 超温,最低安全亮度
    }

    // 线性衰减:温度在mintemp到maxtemp之间时,亮度从100%降到SafeMinLumen
    float temp_range = (float)(g_LaserTemp.maxtemp - g_LaserTemp.mintemp);
    float temp_above_min = (float)(current_temp - g_LaserTemp.mintemp);

    // 计算衰减比例 (1.0到0.0)
    float throttle_ratio = 1.0f - (temp_above_min / temp_range);

    // 计算安全最小亮度比例 (0.0-1.0)
    float min_ratio = (float)g_LaserTemp.SafeMinLumen / 100.0f;

    // 确保衰减比例不低于最小比例
    if (throttle_ratio < min_ratio) {
        throttle_ratio = min_ratio;
    }

    // 计算最终亮度 (0-100)
    int throttled_lumen = (int)((float)target_lumen * throttle_ratio);

    // 确保不低于安全最小亮度
    if (throttled_lumen < g_LaserTemp.SafeMinLumen)
    {
        throttled_lumen = g_LaserTemp.SafeMinLumen;
    }

    // 确保不超过目标亮度
    if (throttled_lumen > target_lumen)
    {
        throttled_lumen = target_lumen;
    }

    JZSDK_LOG_DEBUG("温控计算: 温度=%d, 目标亮度=%d, 调节后=%d (比例=%.2f)",
        current_temp, target_lumen, throttled_lumen, throttle_ratio);

    return throttled_lumen;
}


// 根据状态计算输出亮度
static int calculate_output_lumen(int current_temp)
{
    int output_lumen = g_LaserTemp.TargetLumen;

    switch (g_LaserTemp.state) 
    {
        case THERMAL_STATE_NORMAL:
            // 正常状态,直接使用目标亮度
            output_lumen = g_LaserTemp.TargetLumen;
        break;

        case THERMAL_STATE_SHUTDOWN:
        {
            // 强制关停状态,使用最低安全亮度
            output_lumen = g_LaserTemp.SafeMinLumen;
        }
        break;

        // 温控调节状态
        case THERMAL_STATE_THROTTLING:
        {
            output_lumen = calculate_throttled_lumen(g_LaserTemp.TargetLumen, current_temp);
            g_LaserTemp.throttle_counter++;

            // 记录温控统计
            if (g_LaserTemp.throttle_counter % 10 == 0) 
            {
                JZSDK_LOG_INFO("温控中: 计数=%d, 温度=%d, 输出亮度=%d",
                    g_LaserTemp.throttle_counter, current_temp, output_lumen);
            }
        }
        break;

        case THERMAL_STATE_RECOVERING:
            // 温度敏感恢复:根据当前温度调整恢复速度
            if (g_LaserTemp.CurrentLumen < g_LaserTemp.TargetLumen)
            {
                // 计算温度安全余量
                int temp_margin = g_LaserTemp.mintemp - g_LaserTemp.hysteresis - current_temp;

                // 温度越安全,恢复越快
                if (temp_margin >= 5)  // 温度远低于阈值,快速恢复
                {
                    output_lumen = g_LaserTemp.CurrentLumen + 3;  // 快恢复步长
                    if (output_lumen > g_LaserTemp.TargetLumen)
                        output_lumen = g_LaserTemp.TargetLumen;
                }
                else if (temp_margin >= 2)  // 温度较安全,中速恢复
                {
                    output_lumen = g_LaserTemp.CurrentLumen + 2;   // 中恢复步长
                    if (output_lumen > g_LaserTemp.TargetLumen)
                        output_lumen = g_LaserTemp.TargetLumen;
                }
                else  // 温度接近阈值,慢速恢复
                {
                    output_lumen = g_LaserTemp.CurrentLumen + 1;   // 慢恢复步长
                    if (output_lumen > g_LaserTemp.TargetLumen)
                        output_lumen = g_LaserTemp.TargetLumen;
                }

                // 检查是否恢复完成
                if (output_lumen >= g_LaserTemp.TargetLumen)
                {
                    g_LaserTemp.state = THERMAL_STATE_NORMAL;
                    JZSDK_LOG_INFO("温度敏感恢复完成");
                }
            }
            else
            {
                output_lumen = g_LaserTemp.TargetLumen;
                g_LaserTemp.state = THERMAL_STATE_NORMAL;
            }
            break;
    }


    // 确保亮度在0-100范围内
    output_lumen = clamp_lumen(output_lumen);

    return output_lumen;
}


// 处理温度状态转换
static T_JZsdkReturnCode SideLaser_thermal_state_transition(int current_temp)
{
    ThermalState old_state = g_LaserTemp.state;
    int temp_with_hysteresis = g_LaserTemp.mintemp - g_LaserTemp.hysteresis;

    switch (g_LaserTemp.state)
    {
        case THERMAL_STATE_NORMAL:
        {
            if (current_temp >= g_LaserTemp.maxtemp)
            {
                // 超温关停
                g_LaserTemp.state = THERMAL_STATE_SHUTDOWN;
                JZSDK_LOG_INFO("温度超标! 进入强制关停状态 (温度=%d, 阈值=%d)",
                current_temp, g_LaserTemp.maxtemp);
            }
            else if (current_temp >= g_LaserTemp.mintemp)
            {
                // 开始温控调节
                g_LaserTemp.state = THERMAL_STATE_THROTTLING;
                g_LaserTemp.throttle_start_temp = current_temp;
                g_LaserTemp.throttle_counter = 0;
                JZSDK_LOG_INFO("开始温控调节 (温度=%d)", current_temp);
            }
        }
        break;

        case THERMAL_STATE_THROTTLING:
        {
            if (current_temp >= g_LaserTemp.maxtemp)
            {
                // 温控失败,温度继续上升
                g_LaserTemp.state = THERMAL_STATE_SHUTDOWN;
                JZSDK_LOG_INFO("温控失败! 进入强制关停状态");
            }
            else if (current_temp <= temp_with_hysteresis)
            {
                // 温度回落,开始恢复
                g_LaserTemp.state = THERMAL_STATE_RECOVERING;
                JZSDK_LOG_INFO("温度回落,开始恢复 (当前=%d, 回差阈值=%d)",
                    current_temp, temp_with_hysteresis);
            }
        }
        break;

        case THERMAL_STATE_SHUTDOWN:
        {
            if (current_temp <= temp_with_hysteresis) 
            {
                // 温度下降到安全范围
                g_LaserTemp.state = THERMAL_STATE_RECOVERING;
                JZSDK_LOG_INFO("温度安全,开始恢复");
            }
        }
        break;

        case THERMAL_STATE_RECOVERING:
        {
            if (current_temp <= temp_with_hysteresis) 
            {
                // 恢复完成
                g_LaserTemp.state = THERMAL_STATE_NORMAL;
                JZSDK_LOG_INFO("恢复完成,返回正常状态");
            }
            else if (current_temp >= g_LaserTemp.mintemp) 
            {
                // 恢复过程中温度又升高
                g_LaserTemp.state = THERMAL_STATE_THROTTLING;
                JZSDK_LOG_INFO("恢复中温度升高,重新温控");
            }
        }
        break;
    }

    // 记录状态变化
    if (old_state != g_LaserTemp.state) 
    {
        JZSDK_LOG_INFO("状态变更: %d -> %d", old_state, g_LaserTemp.state);
    }

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

static void* SidelaserTemp_Task(void* arg)
{
    int LasetTargetLumen = 0;
    int CurrentTem = 0;
    T_JzSideLaserInfo SideLaserInfo = { 0 };

    while (1)
    {
        SideLaser_GetInfo(&SideLaserInfo);

        //将数值注入
        g_LaserTemp.TargetLumen = SideLaserInfo.PowerAttribute.targetLumen;
        g_LaserTemp.CurrentLumen = SideLaserInfo.PowerAttribute.lumen;
        CurrentTem = SideLaserInfo.PowerAttribute.Tem;

        // 如果目标亮度发生变化,则更新
        if (LasetTargetLumen != g_LaserTemp.TargetLumen)
        {
            LasetTargetLumen = g_LaserTemp.TargetLumen;

            if (LasetTargetLumen == 0)
            {
                g_LaserTemp.state = THERMAL_STATE_NORMAL; // 重置状态
                delayMs(1000 / g_LaserTemp.frequency);
                continue;
            }
        }

        //转换出新的温控状态
        SideLaser_thermal_state_transition(CurrentTem);

        //计算输出的亮度
        int new_lumen = calculate_output_lumen(CurrentTem);

        // 如果亮度有变化,则更新
        if (new_lumen != g_LaserTemp.CurrentLumen)
        {
            //JZSDK_LOG_DEBUG(":%d current:%d",new_lumen, g_LaserTemp.CurrentLumen);

            // 设置实际亮度
            SideLaserSetlumen(new_lumen);
        }

        delayMs(1000 / g_LaserTemp.frequency);
    }
}

T_JZsdkReturnCode JZsdkSideLaserTemp_Init(JZsdkSideLaserTemp pLaserTemp)
{
    memcpy(&g_LaserTemp, &pLaserTemp, sizeof(JZsdkSideLaserTemp));

    T_JZsdkOsalHandler* osalHandle = JZsdk_Platform_GetOsalHandler();
    if (osalHandle == NULL)
    {
        JZSDK_LOG_ERROR("osal error");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    T_JZTaskHandle task;
    osalHandle->TaskCreate("SidelaserTemp", &SidelaserTemp_Task, 2048, NULL, &task);

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}