完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
硬件:
1。用可控硅控制4.5KW电炉 用K型热电偶采集温度,采用cs1242做温度转换,可以到正负一度的精度 实验目标: 在300度到1000度内可对任意设定的温度恒温,精度先做到+/-1度吧 基本的控制实现方法: 因为是对加热的炉子温度进行控制,属于滞后效应系统,所以采样周期先定为2秒(这里指的是PID计算的周期,注意我的温度采样是实时的),所以CPU外部中断次数为15次/S,对应的功率计算结果输出为0~255,就是说把这2秒钟划分为255等份,根据计算的结果来决定在这2秒钟内应该加热多少等份 /****************************************************************************** FILE: FUZZY.C POPURSE: WRITER: Xukaiming DATE: 2007.03.08 ******************************************************************************/ #include "main.h" #include "task.h" #include "fuzzy.h" #include "ied_ctrl.h" #include "math.h" #include "x5043.h" #include "manctrl.h" #define ERRORCNT 9 //误差记录 #define DERRORCNT 10 //误差变化率记录 //#define DOOROPENSPEED -15L //开门时的升温速度,如果低于此温度,认为电阻丝的热量完全散发出来或者开门升温 xdata long DOOROPENSPEED = - 15L; #define MAXNEGINTERG (-200L*KI/Ki) extern code unsigned int K_Temp_Tab[]; typedef struct AI_CONTROL { long gDest; //目标温度的AD值 long CTEMP; //开始控制温度 long Error[ERRORCNT]; //偏差 long dErr[DERRORCNT]; //偏差变化率 long ECSUM; //10S内的偏差变化率之和 long SumErrLimit; //加热初值 long PreviewOut; long du; long DoorOpenValue; //保存炉子门状态 char LowSpeedCnt; unsigned int iDestTemp; //目标温度值 }; #define Kp 15 //输出变量u比例因子 #define Ki 1/10 //衰减系数; #define KI 15 //Kp 变小的时候 ki要变大 xdata struct AI_CONTROL Ai_CTRL; void TaskFuzzy(void) { char cnt; _nop_(); if (IED.lADTemp > MAX_TEMP) //超温保护 { SetPWM(PWM_PITCED); return ; } //求偏差 for (cnt = ERRORCNT - 1; cnt > 0; cnt--) { Ai_CTRL.Error[cnt] = Ai_CTRL.Error[cnt - 1]; } //保存上次偏差值 Ai_CTRL.Error[0] = (long)(((Ai_CTRL.gDest - IED.lADTemp) / KC)); for (cnt = DERRORCNT - 1; cnt > 0; cnt--) { Ai_CTRL.dErr[cnt] = Ai_CTRL.dErr[cnt - 1]; } //保存上次偏差率值 Ai_CTRL.dErr[0] = Ai_CTRL.Error[0] - Ai_CTRL.Error[1]; //计算偏差变化率 Ai_CTRL.ECSUM = Ai_CTRL.dErr[0] + Ai_CTRL.dErr[1] + Ai_CTRL.dErr[2] + Ai_CTRL.dErr[3] + Ai_CTRL.dErr[4]; //10s的温升速率 =iol if (Ai_CTRL.Error[0] < Ai_CTRL.CTEMP) { if (((Ai_CTRL.Error[0] *Ai_CTRL.dErr[0]) > 0) || ((Ai_CTRL.Error[0] == 0) && (Ai_CTRL.dErr[0] != 0))) //误差变大的情况 { Ai_CTRL.SumErrLimit += Ai_CTRL.Error[0]; //误差变大的时候,求积分 if (Ai_CTRL.SumErrLimit < MAXNEGINTERG) //限幅,如果超过负的最大值, 保持为负的最大值 Ai_CTRL.SumErrLimit = MAXNEGINTERG; //////////////////////////////////////////////////////////// Ai_CTRL.du = Ai_CTRL.Error[0] *Kp + Ai_CTRL.SumErrLimit * Ki / KI * Kp; //增益抑制模式 // } else //开环保持模式 { if (((Ai_CTRL.Error[0] *Ai_CTRL.dErr[0]) < 0) || (Ai_CTRL.dErr[0] == 0)) //误差变小的情况 { Ai_CTRL.du = Ai_CTRL.SumErrLimit * Ki / KI * Kp; } else { Ai_CTRL.du = Ai_CTRL.PreviewOut; } } } else Ai_CTRL.du = PWM_PERIOD; //升温 if (Ai_CTRL.du < 0) Ai_CTRL.du = 0; if (Ai_CTRL.du > PWM_PERIOD) Ai_CTRL.du = PWM_PERIOD; #ifdef _DEBUG printf("%ld,", Ai_CTRL.CTEMP); printf("%ld,%ld,", Ai_CTRL.Error[0], Ai_CTRL.dErr[0]); printf("%ld,%ld,%dn", Ai_CTRL.ECSUM, Ai_CTRL.SumErrLimit, (int)Ai_CTRL.du); #endif SetPWM((unsigned char)Ai_CTRL.du); //保存上次输出 Ai_CTRL.PreviewOut = Ai_CTRL.du; } //functions prototype /************************************************************************ 仿人智能控制器//Humanoid Intelligent Controller ************************************************************************/ /******************************************************************* 模糊控制数据变量 ********************************************************************/ void InitFuzzy(void) { Ai_CTRL.DoorOpenValue = 0; // 重新统计升温速度 Ai_CTRL.LowSpeedCnt = 0; SetPWM(PWM_PITCED); } /********************************************************************* 启动高温炉 **********************************************************************/ void CtrlStove(UCHAR cOpen, long lDefTemp, UCHAR cRate) { xdata StableTempTab psTmpTab; //停止 SuspendTask(TASK_FUZZY); InitFuzzy(); if (cOpen) //启动 { Ai_CTRL.gDest = (((double)(0xFFFFFFUL << 2)) / 5000000UL) *K_Temp_Tab[lDefTemp] + 20; //将 目标 温度值 转换 为 AD值 Ai_CTRL.CTEMP = (1010L - lDefTemp); //控温范围 ActiveTask(TASK_FUZZY, PWM_SCAN); } } /********************************************************************** 设置PWM,PWM0控制高温炉 16MHz时,T=2*512/16=64uS,F=42.666KHz,计数周期=256,占空比=0%--99.61% ***********************************************************************/ ***it POUT = P1 ^ 3; char gcPoutTimer = - 1; void StopPOut() { POUT = 1; } void SetPWM(UCHAR cPeriod) { /* CMOD = 0x00; // Setup PCA timer // Configure PCA0 Counter operating mode CCAP0L=CCAP0H=cPeriod; // Set duty for TCM0 CCON =0x40; CCAPM0=0x42; // Set TCM0 operationg mode */ long period; StopTimer(&gcPoutTimer); POUT = 1; period = PWM_SCAN * cPeriod / 255 / 10; if (period > 0) { POUT = 0; gcPoutTimer = StartTimer(TIMER_MODE_ONCEROUTINE, period, StopPOut, 0); } } |
|
相关推荐
6个回答
|
|
|
没看懂楼主发这帖子想说什么
|
|
|
|
|
|
PID算法也没说明白啊?!!!
|
|
|
|
|
|
我也没看懂...
|
|
|
|
|
|
不明觉力。。。
|
|
|
|
|
|
不懂。。。。。。。。。。
|
|
|
|
|
|
这个模糊控制的例子
|
|
|
|
|
只有小组成员才能发言,加入小组>>
请问下图大疆lightbridge2遥控器主板电源芯片型号是什么?
4892 浏览 1 评论
使用常见的二极管、三极管和mos做MCU和模组的电平转换电路,但是模组和MCU无法正常通信,为什么?
834浏览 2评论
为了提高USIM卡电路的可靠性和稳定性,在电路设计中须注意的点有哪些?
904浏览 2评论
993浏览 2评论
858浏览 2评论
2211浏览 2评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-15 13:53 , Processed in 0.851866 second(s), Total 82, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1650