# MicroPython implementation of fuzzy temperature control
# Converted from original C implementation (fuzzy.C)
# Original author: xukaiming
# Original date: 2025.06.16
import time
from machine import Pin
from micropython import const
#from task import TaskScheduler

#0.1度  以前是0.01度
#设定为度



# 三个参数 通过显示屏config配置
_DEFAULT_Ki 	= const(1)  # Integral coefficient 积分系数
_DEFAULT_KI 	= const(960)  # KI value (can be 60 or 80 depending on temperature)
_DEFAULT_Kp 	= const(320)  # Proportional coefficient 比例系数

_DEFAULT_KC 	= const(1)  # Control difference 控制差异 0.01℃
_DEFAULT_MAXNEGINTERG = const(-1000)  # Maximum negative integral 最大负值
_MAX_TEMP = const(200*10)  # Maximum negative integral 最大正值？

# Constants
PWM_PITCED = const(0)  # PWM minimum 控温最小周期
PWM_PERIOD = const(4000)  # PWM period 控温最大周期
DEF_CTEMP  = const(300) #初始启动控制温度 举例：300 == 3.00℃


class AI_Control:
    """AI control structure for fuzzy temperature control"""

    def __init__(self):

        # Control constants
        self.KC = _DEFAULT_KC  # Control difference 控制差异 0.01℃
        self.Ki = _DEFAULT_Ki  # Integral coefficient 积分系数
        self.KI = _DEFAULT_KI  # KI value (can be 60 or 80 depending on temperature) 积分时间 
        self.Kp = _DEFAULT_Kp  # Proportional coefficient 比例系数
        self.MAXNEGINTERG = _DEFAULT_MAXNEGINTERG  # Maximum negative integral 最大负值
        
        # control varible
        self.WarmFlag = 0  # Heating flag 加热标志位
        self.iDestTemp = 0  # Target temperature 目标温度
        self.gTemp = None # Current temperature pointer 当前温度
        self.CTEMP = DEF_CTEMP  # Initial start control temperature   初始启动控制温度2000 == 5.00℃

        self.Error = [0, 0]  # Error values (current and previous) 差异值
        self.dErr = 0  # Error change rate 差异变化量

        self.SumErrLimit = 0  # Integral value 积分值
        self.PreOut = 0  # Previous output 上一个输出
        self.CurOut = 0  # Current output   当前输出
        
        self.set_p_out = None
        self.stop_heat()
        
    def task_fuzzy(self):
        """Fuzzy control task""" 
        if self.WarmFlag:  #判断是否开始加热？
            self.Error[1] = self.Error[0] #保存当前差异作为上一个差异 
            temp = self.gTemp[0]  # Assuming gTemp is now a list or array 
            #print(f"gTemp =  {self.gTemp[0]}\r")
            self.Error[0] = int((self.iDestTemp - temp) / self.KC)  # Calculate error 目标值减当前值，计算差异
            self.dErr = self.Error[0] - self.Error[1]  # Calculate error change 计算误差变化率

            if self.Error[0] < self.CTEMP: 
                # Error is within control range 误差差异进入控制范围
                if ((self.Error[0] * self.dErr) > 0) or ((self.Error[0] == 0) and (self.dErr != 0)):
                    # Error is increasing 差异在增加，降温趋势
                    self.SumErrLimit += self.Error[0]  # Accumulate error 误差差异累积
                    if self.SumErrLimit < self.MAXNEGINTERG:
                        self.SumErrLimit = self.MAXNEGINTERG #赋值最小负值，控制积分分离深度

                    # Calculate output = proportional + integral 当前输出=比例+积分
                    self.CurOut = self.Error[0] * self.Kp + self.SumErrLimit * self.Ki * self.Kp / self.KI
                    # KI 积分时间，累积到与当前比例作用相同输出量所需要的时间，越小越强。 
                else:
                    # Error is decreasing or stable 差异在减小或稳定，升温趋势或稳定
                    if ((self.Error[0] * self.dErr) < 0) or (self.dErr == 0):
                        # Error is decreasing   差异在减小，升温趋势
                        self.CurOut = self.SumErrLimit * self.Ki * self.Kp / self.KI
                    else:
                        # Error is stable   差异稳定，稳定趋势；用上一个输出量持续输出
                        self.CurOut = self.PreOut
            else:
                # Error is outside control range - use direct calculation 误差差异在控制范围外
                self.CurOut = int(self.iDestTemp / 3000 * PWM_PERIOD / 4.0)
                #参数说明，根据设定温度 控制全速加热量，全速加热4000,120℃以下非全速加热
            if self.dErr < -20: #两次温升差异大于0.2℃/4S，抑制积分作用
                self.SumErrLimit = 0  #抑制上升速度
                
            # Limit output range 限制输出范围
            if self.CurOut < 0:
                self.CurOut = 0 # 最小输出值 0
            if self.CurOut > PWM_PERIOD:
                self.CurOut = PWM_PERIOD # 最大输出值 4000

            # Set output and save previous value
            if self.set_p_out != None:
                self.set_p_out(self.CurOut)
            self.PreOut = self.CurOut  # 保存当前输出量 作为上一个输出量
            #输出excel曲线
            print(f"Error = {self.Error[0]},dErr={self.dErr},SumErrLimit={self.SumErrLimit},CurOut={self.CurOut},PreOut={self.PreOut }\r")
        else:
            if self.set_p_out != None:
                self.set_p_out(PWM_PITCED)
            
        
    def stop_heat(self):
        """Stop heating""" 
        self.WarmFlag = 0 
        if self.set_p_out !=  None:
            self.set_p_out(PWM_PITCED)
        
     
    '''
    def set_p_out(self,pwm_width):
        if(pwm_width>0):
            #TaskScheduler.start_timer(TIMER_MODE_ONCEROUTINE, pwm_width, )
            pass
        else:
            #set_p_out
            pass
        pass
    '''


    def ctrl_stove(self,c_open, cur_temp, l_dest_temp):
        """
        Control stove function

        Args:
            c_open: Open control flag
            cur_temp: Pointer to current temperature
            l_dest_temp: Target temperature 
        """  
        self.WarmFlag = c_open

        if c_open:
            # Start heating
            self.gTemp = cur_temp  # Current temperature 
            print(f"KC={self.KC}  Ki =  {self.Ki} KI = {self.KI} Kp= {self.Kp} CTEMP= {self.CTEMP}\r")
            #print(f"WarmFlag={self.WarmFlag}  gTemp =  {self.gTemp[0]} l_dest_temp = {l_dest_temp}\r")
            self.iDestTemp = l_dest_temp  # Target temperature 

            
            self.CTEMP = DEF_CTEMP
            self.SumErrLimit = 0

            self.KI = 60
            
        else:
            self.stop_heat()
            
# Global AI control instance
ai_ctrl = AI_Control()

def Task_fuzzy():          
    ai_ctrl.task_fuzzy()

if __name__ == '__main__':
    temper = [3000,4000]
    l_dest_temp = 800                 
    print("fuzzy 测试\r")
    ai_ctrl.ctrl_stove(1,temper,l_dest_temp);
    #ai_ctrl.Heat_ctrl(0)  #关闭加热
    #ai_ctrl.Heat_ctrl(1)  #启动加热
    while True:
        temper[0] = 4000.1
        ai_ctrl.task_fuzzy()
        time.sleep(1)  # 模拟耗时1秒的操作
        temper[0] = 3000.1 
        ai_ctrl.task_fuzzy()
        time.sleep(1)  # 模拟耗时1秒的操作
        temper[0] = 4000.1 
        ai_ctrl.task_fuzzy()
        time.sleep(1)  # 模拟耗时1秒的操作
        temper[0] = 5000.1 
        ai_ctrl.task_fuzzy()
        time.sleep(1)  # 模拟耗时1秒的操作
        temper[0] = 6000.1 
        ai_ctrl.task_fuzzy()
        time.sleep(0)  # 模拟耗时1秒的操作
        
        #ai_ctrl.Heat_ctrl(0)  #关闭加热
        
         

