/*
 * mppt_control.c
 *
 *  Created on: 2024年6月29日
 *      Author: psx
 */

#include "mppt_control.h"
#include "collect_Conversion.h"
#include "pwm.h"
#include "inflash.h"
#include "gpio.h"
#include "sl_protocol.h"
#include "task.h"
#include "uart_dev.h"
#include "parameter.h"


static void ConstantCurrentCharge(void);
static void ConstantVoltageCharge(void);
static void FloatingCharge(void);


/**
  * @brief  恒定输入电压
  * @param
  * @retval
  *
  */
void mppt_constantVoltage(float InVoltage)
{
    static float_t kp = 0.005;
    static float_t ki = 0.00001;

    float_t pv1Volt = g_otherParameter.Solar_In_Circuit_Voltage;
    float_t error = pv1Volt - InVoltage;
    float_t stepPwm = kp * error + ki * pv1Volt;

    g_controlParameter.dutyRatio += stepPwm;

    Set_duty_ratio(&g_controlParameter.dutyRatio);
}

/**
  * @brief  恒定输出电压(电池)
  * @param
  * @retval
  *
  */
void mppt_constantVoltageB(float OutVoltage)
{
    static float_t kp = 0.005;
    static float_t ki = 0.00001;

    float_t outVolt = g_otherParameter.Battery_Voltage;

    float_t error = OutVoltage - outVolt;
    float_t stepPwm = kp * error + ki * outVolt;
    g_controlParameter.dutyRatio += stepPwm;

    Set_duty_ratio(&g_controlParameter.dutyRatio);
}

/**
  * @brief  恒定输出电压（输出检测端,没有电池时）
  * @param
  * @retval
  *
  */
void mppt_constantVoltageNoBatteryO(float OutVoltage)
{
    static float_t kp = 0.005;
    static float_t ki = 0.00001;

    float_t outVolt = g_otherParameter.Output_Voltage;

    float_t error = OutVoltage - outVolt;
    float_t stepPwm = kp * error + ki * outVolt;
    g_controlParameter.dutyRatio += stepPwm;

    Set_duty_ratio(&g_controlParameter.dutyRatio);
}

/**
  * @brief  恒定输出电压（输出检测端）
  * @param
  * @retval
  *
  */
float_t lastVolt = 0;
float_t lastStepPwm = 0;
float_t lastDutyRatio = 0;
void mppt_constantVoltageO(float OutVoltage)
{
    static float_t kp = 0.005;
    static float_t ki = 0.00001;
//    static uint8_t flag = 0;

    float_t outVolt = g_otherParameter.Output_Voltage;

    float_t error = OutVoltage - outVolt;
    float_t StepPwm = kp * error + ki * outVolt;

    /* 当有电池时，输出电压的曲线是先上升后下降 */
    if (lastDutyRatio >= g_controlParameter.dutyRatio) {
//        if (lastVolt >= outVolt) {
            g_controlParameter.dutyRatio += StepPwm;
//        } else {
//            g_controlParameter.dutyRatio -= StepPwm;
//        }
    } else {
//        if (lastVolt >= outVolt) {
//            g_controlParameter.dutyRatio -= StepPwm;
//        } else {
//            g_controlParameter.dutyRatio += StepPwm;
//        }
        g_controlParameter.dutyRatio -= StepPwm;
    }

    /* 过温保护 */
    if (g_otherParameter.overTemperature == 0) {

    } else if (g_otherParameter.overTemperature == 1) {
        g_controlParameter.dutyRatio -= 0.1;
    } else if (g_otherParameter.overTemperature == 2) {
        g_controlParameter.dutyRatio -= 0.2;
    } else if (g_otherParameter.overTemperature == 3) {
        g_controlParameter.dutyRatio -= 0.3;
    }

    lastVolt = outVolt;
    lastStepPwm = StepPwm;
    lastDutyRatio = g_controlParameter.dutyRatio;

    Set_duty_ratio(&g_controlParameter.dutyRatio);
}

/**
  * @brief  通过扰动干扰法追踪最大功率点
  * @param
  * @retval
  *
  */
float_t lastPower = 0;
float_t lastSolarInCircuitVoltage = 0;
void mppt_readJust(void)
{
    static float_t step1 = 0.005;
    static float_t step2 = 0.001;
    static float_t tempV = 0.2;

    static uint16_t flag = 0;
    flag++;
    if (flag < 1000) {
        return;
    }
    flag = 0;

    float_t SolarInCircuitVoltage = get_PV1_VOLT_IN();
    float_t power = g_otherParameter.Output_Voltage * g_otherParameter.Charg_Current;

    float_t voltageDifference = SolarInCircuitVoltage - lastSolarInCircuitVoltage;

    /* 输出电压随占空比增加电压减小 */
    if (power <= lastPower) {
        if (lastSolarInCircuitVoltage <= SolarInCircuitVoltage) {
            if (voltageDifference > tempV) {
                g_controlParameter.dutyRatio += step2;
            } else {
                g_controlParameter.dutyRatio += step1;
            }
        } else {
            if (voltageDifference > tempV) {
                g_controlParameter.dutyRatio -= step2;
            } else {
                g_controlParameter.dutyRatio -= step1;
            }
        }
    } else {
        if (lastSolarInCircuitVoltage <= SolarInCircuitVoltage) {
            if (voltageDifference > tempV) {
                g_controlParameter.dutyRatio -= step2;
            } else {
                g_controlParameter.dutyRatio -= step1;
            }
        } else {
            if (voltageDifference > tempV) {
                g_controlParameter.dutyRatio += step2;
            } else {
                g_controlParameter.dutyRatio += step1;
            }
        }
    }

    lastPower = power;
    lastSolarInCircuitVoltage = SolarInCircuitVoltage;

    /* 过温保护 */
    if (g_otherParameter.overTemperature == 0) {

    } else if (g_otherParameter.overTemperature == 1) {
        g_controlParameter.dutyRatio -= 0.1;
    } else if (g_otherParameter.overTemperature == 2) {
        g_controlParameter.dutyRatio -= 0.2;
    } else if (g_otherParameter.overTemperature == 3) {
        g_controlParameter.dutyRatio -= 0.3;
    }

    Set_duty_ratio(&g_controlParameter.dutyRatio);
}


/**
  * @brief  恒流充电（大电流充电），mppt最大功率充电
  * @param
  * @retval
  *
  */
void ConstantCurrentCharge(void)
{
//    mppt_constantVoltage(18);
    mppt_readJust();
}

/**
  * @brief  恒压充电
  * @param
  * @retval
  *
  */
void ConstantVoltageCharge(void)
{
    mppt_constantVoltageO(g_controlParameter.constantVoltageChargeV);
}

/**
  * @brief  浮充充电
  * @param
  * @retval
  *
  */
void FloatingCharge(void)
{
    mppt_constantVoltageO(g_controlParameter.FloatV);
}

/**
  * @brief  mppt控制模式的确定
  * @param
  * @retval
  *
  */
void MpptContorlChoice(void)
{
    switch(g_otherParameter.MPPT_Mode) {

    case CONSTANTCURRENT:
        ConstantCurrentCharge();
        break;

    case CONSTANTVOLTAGE:
        ConstantVoltageCharge();
        break;

    case FLOAT:
        FloatingCharge();
        break;

    default:
        break;
    }
}

/**
  * @brief  mppt模式的确定
  * @param
  * @retval
  *
  */
void MpptModeChoice(void)
{
    /* 太阳能板输出电压小于一定值且充电电流也小于一定值时mppt停止工作 */
    if ((g_otherParameter.Input_Voltage < g_controlParameter.stopSolarOpenCircuitV
            && g_otherParameter.Charg_Current < 0.1) ){
//            && g_otherParameter.MPPT_Mode != NoWork) {
        g_otherParameter.MPPT_Mode = NoWork;

        TIM_Cmd(TIM3, DISABLE);
        TIM_SetCompare4(TIM4, 0);
        g_controlParameter.dutyRatio = 0;

        TimeSliceOffset_Register(&g_startMpptControl, Task_startMpptControl
                , startMpptControl_reloadVal, startMpptControl_offset);
        TimeSliceOffset_Unregister(&g_collectOpenCircuitVoltage);
        return;
    }

//    /* 流向电池的电流小于一定值或者电压过大或者过小判定无电池采用浮充输出 */
//    if ((g_otherParameter.Charg_BatteryCurrent < 0.05 && g_otherParameter.Charg_BatteryCurrent > -0.05)
//            || g_otherParameter.Battery_Voltage > 16 || g_otherParameter.Battery_Voltage < 8) {
//        g_otherParameter.MPPT_Mode = FLOAT;
//        g_otherParameter.batteryState = 0;
//        return;
//    }
    if (g_otherParameter.Battery_Voltage > 16 || g_otherParameter.Battery_Voltage < 8) {
        g_otherParameter.MPPT_Mode = FLOAT;
        g_otherParameter.batteryState = 0;
        return;
    }

    /* 当电压低于恒压充电阈值电压（-0.2V）且充电电流大于0.1A时采用恒流输出 */
    if ((g_controlParameter.constantVoltageV - 0.2) >= g_otherParameter.Battery_Voltage
            && g_otherParameter.Charg_Current > 0.1) {
        g_otherParameter.MPPT_Mode = CONSTANTCURRENT;
        return;
    }

    /* 当电压高于恒压充电阈值电压且充电电流大于浮充充电阈值（+0.1A）电流时采用恒压输出 */
    if ((g_controlParameter.constantVoltageV < g_otherParameter.Battery_Voltage)
//            && (g_controlParameter.floatI + 0.1 <= g_otherParameter.Charg_Current)) {
            && ((g_controlParameter.floatI + 0.1 <= g_otherParameter.Charg_BatteryCurrent) || (g_controlParameter.floatI + 0.1 <= -g_otherParameter.Charg_Current))) {
        g_otherParameter.MPPT_Mode = CONSTANTVOLTAGE;
        return;
    }

    /* 当电压高于恒压充电阈值电压且充电电流小于浮充充电阈值电流时采用恒压输出 */
    if ((((g_controlParameter.constantVoltageV < g_otherParameter.Battery_Voltage)
            && (g_controlParameter.floatI > g_otherParameter.Charg_Current))
            && (g_controlParameter.floatI > g_otherParameter.Discharg_Current))) {
        g_otherParameter.MPPT_Mode = FLOAT;
        return;
    }

}

/**
  * @brief  mppt的控制
  * @param
  * @retval
  *
  */
void MpptContorl(void)
{
    g_otherParameter.Output_Voltage = get_PV_VOLT_OUT();
    g_otherParameter.Solar_In_Circuit_Voltage  = get_PV1_VOLT_IN();

//    /* 出现adc采集出错全为0,退出本次中断 */
//    if (g_otherParameter.Discharg_Current == 0 && g_otherParameter.Charg_Current == 0) {
//        return;
//    }

    g_otherParameter.Charg_BatteryCurrent = g_otherParameter.Charg_Current - g_otherParameter.Discharg_Current;

    MpptModeChoice();

    /* 无电池时，恒压输出 */
    if (!g_otherParameter.batteryState) {
        if (!g_otherParameter.overTemperature) {
//            mppt_constantVoltageNoBatteryO(g_controlParameter.FloatV);

            mppt_constantVoltageO(g_controlParameter.FloatV);
        }
        return;
    }

//    /* 有电池时 */
//    if (!g_otherParameter.overTemperature) {
//        MpptModeChoice();
//        MpptContorlChoice();
//    }

    MpptContorlChoice();
}






