计算斜率,判断斜率


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>

// 定义常量
#define LOW_COOK_WINDOW_SIZE 20                        // 滑动窗口大小,10个样本点(10秒)
#define LOW_COOK_SLOPE_THRESHOLD 0.12f                 // 斜率平缓的阈值
#define LOW_COOK_SAMPLE_INTERVAL 10                    // 采样间隔,单位为100ms
#define LOW_COOK_DEFAULT_TIME_DIFFERENCE 10.0f         // 默认时间间隔为10秒
#define MIN_TIME_DIFFERENCE 1.0f                       // 最小时间间隔为1秒
#define MAX_TIME_DIFFERENCE (LOW_COOK_WINDOW_SIZE - 1) // 最大时间间隔为窗口大小减1

// 定义加热系统结构
typedef struct
{
    float slope;
    float data[LOW_COOK_WINDOW_SIZE]; // 滑动窗口数据
    unsigned char count;              // 当前样本数量
    bool slope_event;                 // 斜率事件
    unsigned char tim_count;          // 时间片计数器
    unsigned char state;              // 状态机
    unsigned char slope_status;       // 状态
} low_cook_heating_system_t;

// 全局变量
low_cook_heating_system_t low_cooksystem;

// 初始化加热系统
void low_cook_init_heating_system(low_cook_heating_system_t *system)
{

    system->slope = 0.0f;
    system->tim_count = 0;
    system->state = 0;
    system->count = 0;
    system->slope_event = false;
    system->slope_status = 1; // 样本不足
    for (unsigned char i = 0; i < LOW_COOK_WINDOW_SIZE; i++)
    {
        system->data[i] = 0.0f;
    }
}

// 添加样本点到滑动窗口,100ms调用一次,1S存数据一次
void low_cook_add_sample(low_cook_heating_system_t *system, float temperature)
{
    if (++system->tim_count < LOW_COOK_SAMPLE_INTERVAL)
    {
        return;
    }
    system->tim_count = 0;

    if (system->count < LOW_COOK_WINDOW_SIZE)
    {
        // 如果窗口未满,直接添加到末尾
        system->data[system->count++] = temperature;
    }
    else
    {
        // 如果窗口已满,丢弃最旧的数据,将最新的数据添加到最后的位置
        for (unsigned char i = 1; i < LOW_COOK_WINDOW_SIZE; i++)
        {
            system->data[i - 1] = system->data[i];
        }
        system->data[LOW_COOK_WINDOW_SIZE - 1] = temperature;
    }
}

// 计算温度斜率
float low_cook_calculate_slope(low_cook_heating_system_t *system, float time_difference)
{
    // 限制 time_difference 在合理范围内
    if (time_difference < MIN_TIME_DIFFERENCE || time_difference > MAX_TIME_DIFFERENCE)
    {
        system->slope_status = 2; // 时间间隔超出范围
        return 0.0f;
    }

    unsigned char interval_samples = (unsigned char)(time_difference); // 计算需要的样本间隔
    if (system->count < LOW_COOK_WINDOW_SIZE || interval_samples >= system->count)
    {
        system->slope_status = 1; // 样本不足
        return 0.0f;
    }

    // 获取最新样本点和 interval_samples 前的样本点
    float current = system->data[system->count - 1];
    float previous = system->data[system->count - 1 - interval_samples];

    system->slope_status = 0; // 成功计算斜率
    // 计算并返回斜率
    return (current - previous) / time_difference;
}

void low_cook_update_slope(float time_difference)
{
    // 添加新的温度数据到系统中
    low_cook_add_sample(&low_cooksystem, stheat.temperature);

    // 计算斜率
    low_cooksystem.slope = low_cook_calculate_slope(&low_cooksystem, time_difference);
    if ((low_cooksystem.slope_status == 0) && (stheat.temperature > 35))
    {
        // 判断斜率是否平缓
        low_cooksystem.slope_event = (fabsf(low_cooksystem.slope) < LOW_COOK_SLOPE_THRESHOLD);
    }
}

        // 更新斜率
        // if (low_cooksystem.state == 0)
        // {
        // low_cook_update_slope(18);
        //     if (low_cooksystem.slope_event)
        //     {
        //         pid.setpointOuter = stheat.setTemp;
        //         low_cooksystem.state = 1;
        //     }
        //     else
        //     {
        //         pid.setpointOuter = 165;
        //     }
        // }

#include <stdio.h>
#include <stdbool.h>

// 定义一个用于表示斜坡发生器状态的结构体
typedef struct RampGenerator
{
    float currentValue; // 当前值
    float targetValue;  // 目标值
    float step;         // 每个控制周期应当改变的数值大小
    bool isBusy;        // 指示斜坡发生器是否正在调整中
} RampGenerator;

// 一个周期内对斜坡发生器状态的更新
void rampIterate(RampGenerator *ramp)
{

    // printf("Current Value Updated: %f\n", ramp->currentValue); // 添加此行代码以在每次迭代后打印当前值

    if (ramp->currentValue < ramp->targetValue)
    {                                     // 如果当前值小于目标值
        ramp->currentValue += ramp->step; // 增大当前值
        if (ramp->currentValue > ramp->targetValue)
        { // 避免超调
            ramp->currentValue = ramp->targetValue;
        }
    }
    else if (ramp->currentValue > ramp->targetValue)
    {                                     // 如果当前值大于目标值
        ramp->currentValue -= ramp->step; // 减小当前值
        if (ramp->currentValue < ramp->targetValue)
        { // 避免超调
            ramp->currentValue = ramp->targetValue;
        }
    }
}

// 初始化斜坡发生器
void rampInit(RampGenerator *ramp, float startValue, float targetValue, float time, float cycleTime)
{
    ramp->currentValue = startValue;
    ramp->targetValue = targetValue;
    if (time != 0 && cycleTime != 0)
    {
        ramp->step = (targetValue - startValue) * (cycleTime / time);
        if (ramp->step < 0)
        {
            ramp->step = -ramp->step; // 确保 step 为正
        }
    }
    else
    {
        ramp->step = 0; // 出错情况下设置为0,避免非法操作
    }
}

 rampInit(&myRamp, stheat.setTemp * 2, stheat.setTemp, val, 0.1f); //
  rampIterate(&myRamp);

#if low_temp_cook_1
            // 算法1
            Temp_error = stheat.setTemp - stheat.temperature;
            if (Temp_error > 0)
            {
                val = Temp_error * 10; // 1度10秒
            }

            rampInit(&myRamp, stheat.setTemp * 2, stheat.setTemp, val, 0.1f); //
#endif

#if low_temp_cook_2
            // 将stheat.temperature的值从90到0的范围映射到20到360的范围,6分钟
            // val = map(stheat.temperature, 90, 0, 20, 360);
            rampInit(&myRamp, stheat.setTemp * 2, stheat.setTemp, val, 0.1f); //
#endif


#if low_temp_cook_1
        rampIterate(&myRamp);
        if (myRamp.currentValue > 162)
        {
            tempValue = 162;
        }
        else
        {
            tempValue = myRamp.currentValue;
        }
        pid.setpointOuter = tempValue;

        if (myRamp.currentValue != stheat.setTemp)
        {

            pid.KpOuter = 33;
            pid.KiOuter = 0.2;

            pid.KpInner = 33;
            pid.KiInner = 0.1;
        }
        else
        {
            Temp_error = stheat.setTemp - stheat.temperature;
            //  根据误差模糊调整PID参数
            if (Temp_error > 10)
            {
                pid.KpOuter = 33;
                pid.KiOuter = 0.2;

                pid.KpInner = 33;
                pid.KiInner = 0.1;
            }
            else if (Temp_error > 5)
            {
                pid.KpOuter = 28;
                pid.KiOuter = 0.2;

                pid.KpInner = 33;
                pid.KiInner = 0.1;
            }
            else
            {
                pid.KpOuter = 10;
                pid.KiOuter = 0.15;

                pid.KpInner = 15;
                pid.KiInner = 0.1;
            }
            pid.KdInner = 0;
        }
#endif
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值