#include "APPDEF.h" #include "i2c.h" uint16_t ACCtrl(uint16_t Percent) /*0-1000*/ { uint8_t Out = 0; if (Percent < 10) { Out = 0; } else if (Percent > 990) { Out = 1; } else { Out = 127u - (uint8_t)((float)Percent * 0.128f); } WS100T10_Ctrl(Out); return Percent; } void ACCMD(bool cmd) { if (!cmd) { GPIO_ResetBits(GPIOA, GPIO_Pin_15); } else { GPIO_SetBits(GPIOA, GPIO_Pin_15); } } uint16_t Percent[4]; uint16_t GetPercent[4]; uint16_t PercentOld[4]; void _task_ACCtrl(const void *p_arg) { WS100T10_Init(); for (;;) { if (Percent[0] != PercentOld[0]) { GetPercent[0] = ACCtrl(Percent[0]); PercentOld[0] = Percent[0]; } osDelay(300); } } osThreadDef(_task_ACCtrl, osPriorityNormal, 1u, 0u); void AC_CTRL_Init(void) { osThreadCreate(osThread(_task_ACCtrl), NULL); } // // // extern float Temperature; float Kp, Ki, Kd; static enum enumHeatOp_State { // 采样泵操作状态 eShut, eRunning, eShutReq } volatile HeatOp_State; float HeatOutValue; float OutputMax = 1; static void HeatPID_Task(void) { float SetValue, RunValue, OutValue = 0.0f; float Ek_1, Ek = 0.0f; float Up = 0.0f, Ui = 0.0f, Ud = 0.0f; float Upid = 0.0f; float Initout = 0.0f; float UpidSetGain = 0.800f; uint32_t SaveTick; SetValue = Set.TempSet; Kp = 0.06; Ki = 0.00029; Kd = 1.0; HeatOutValue = 0.0f; Percent[0] = 0; osDelay(500u); ACCMD(true); // 初始化延时 osDelay(500u); SaveTick = osKernelSysTick(); const uint32_t oneTick = osKernelSysTickMicroSec(1000u); uint32_t now, lostTick, delayCount; while (eRunning == HeatOp_State) { RunValue = Temperature; // PID计算 Ek_1 = Ek; Ek = (SetValue - RunValue); if (Ek > 20.0f) { HeatOutValue = OutValue = OutputMax; Percent[0] = OutValue * 1000; } else { Up = Kp * Ek; Ui += Ki * Ek; if (Ui < -1.0f) { Ui = -1.0f; } if (Ui > +1.0f) { Ui = +1.0f; } Ud = (Ud * 0.667f) + (Kd * (Ek - Ek_1) * (1.0f - 0.667f)); Upid = (Upid * UpidSetGain) + (Up + Ui + Ud) * (1.0f - UpidSetGain); OutValue = Upid + Initout; // PID输出 if (OutValue < 0.0f) { OutValue = 0.0f; } if (OutValue > OutputMax) { OutValue = OutputMax; } HeatOutValue = OutValue; Percent[0] = OutValue * 1000; } // 定间隔延时 now = osKernelSysTick(); // 计算已经逝去的tick计时单位 lostTick = (uint32_t)(now + oneTick - 1u - SaveTick) / oneTick; // 计算余下需要的延时周期(设定间隔时间:300ms) if (lostTick < 300u) { delayCount = 300u - lostTick; } else { // 已经逝去的时间超过设定的间隔,重新计算时间起点后少量延时。 SaveTick = now; delayCount = 30u; } osDelay(delayCount); SaveTick += delayCount * oneTick; } // PID 停止 HeatOutValue = 0.0f; Percent[0] = 0; osDelay(500u); ACCMD(false); HeatOp_State = eShut; } /********************************** 功能说明 *********************************** * 套接调用电机控制程序 *******************************************************************************/ static void HeatTask_Socket(void const *p_arg) { // 调用采样控制程序,然后结束任务 HeatPID_Task(); osThreadTerminate(osThreadGetId()); } osThreadDef(HeatTask_Socket, osPriorityHigh, 1, 0); static void HeatTask_Init() { osThreadCreate(osThread(HeatTask_Socket), NULL); } /********************************** 功能说明 *********************************** * 电机任务的启停控制/// 开关指定的采样泵 *******************************************************************************/ // #include "BIOS.H" void Pump_OutCmd(bool NewState) { if (!NewState) { // 发标志,任务会检测标志自行中止。 // osThread_SetReady; HeatOp_State = eShutReq; } else if (eRunning == HeatOp_State) { // 请求开泵,但泵并没有关?! ; } else { // 请求开泵,且已知泵是关的 HeatOp_State = eRunning; HeatTask_Init(); } // if( HeatOp_State == eRunning) // lightopen(); // else // lightclose(); } /// 读取指定的采样泵的调速输出[0.0 ~ 1.0] float Pump_GetOutput(void) { { if (eShutReq == HeatOp_State) { return 0.0f; } else { return HeatOutValue; } } }