本帖最后由 8051启蒙者 于 2022-12-27 14:19 编辑
做风扇调速的原因是,以前同事做的风扇测试跟电脑检测误差超5%,正好我刚做水冷水泵调速跟电脑4线风扇一样需要采集FG周期来控制水泵转速,于是用水泵测试转速程式来测风扇转速结果跟以前同事做的一样测试结果,当时参考STC8H8K64U-DEMO-CODE范例05-利用定时器测量脉冲宽度,范例量测半周期,分析了好久才找到问题是采集问题,用示波器抓波发现风扇FG信号正半轴与负半周占空比有差异,把这个差异转换为RPM每分钟转速误差就大了,后来改采集整个周期问题解决。
原本只需PWM输出0% 50% 75% 100%(显示风扇转速),后来我在原基础上增加了调速功能刚开使用的是设置上下限1%,超过了就调整,但是最近的一个新品风扇0% PWM风扇停转,而且这个风扇有点怪调速滞后很多,就是PWM定值FG也会来回抖动等很久后才稳定,如果再用原本调速方法就会出现转速慢慢高慢慢变低,一开始也研究了下PID一直没有搞定,这次没办法如果搞不定老板就要找话说了,搞了几个终于搞定了,下面分享下,(参考QQ群里别人的分享PID,修改了)
原4线风扇测试转速 与电脑测试对比
原4线风扇测试
1.用外部中断下降沿来判定一周(原本在tim1里面)我觉得这样减少了在定时器1里面判断(因P32没加上拉电阻所以开启了内部上拉)。
风扇FG内部示意图
- //P32内部上拉 FAN FG
- P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
- P3PU |= 0x04; //P3.2
- P_SW2 &= 0x7f;
- //INT0
- IT0 = 1; //使能INT0下降沿中断
- EX0 = 1; //使能INT0中断
-
- //int0
- void INT0_Isr(void) interrupt 0 //INT0
- {
- FG_Flag = 1; //标记
- Rpm0[1] = Rpm0[0]; //转存
- Rpm0[0] = 0; //清零
- }
复制代码
2.定时器1用500000K 0.2uS计数,这样可以100-50000 RPM范围
- //tim1
- void timer1(void) interrupt 3 //2us
- {
- Rpm0[0]++; //FG周期
- }
复制代码
3.PID调速
- //PID
- pid_p = 0.002;
- pid_i = 0.0008;
- pid_d = 0.0004; //PID三个参数初值
- lastError = 0; //之前误差初始为0
- sumError = 0; //偏差积累初始为0
-
- //pid
- void PID(u32 dat)
- {
- long xdata dError;
- long xdata Error;
- long xdata Total_Error;
-
- Error = dat - SpeedSet; //当前误差
- sumError = Error + sumError; //误差积累
- dError = Error - lastError; //误差偏差
- lastError = Error;
- Total_Error = pid_p*Error + pid_i*sumError + pid_d*dError; //三个参数计算
-
- if(Total_Error > 600) Total_Error = 600;
- if(Total_Error < 60) Total_Error = 60;
- PWM6_Duty = Total_Error;
- UpdatePwm6(PWM6_Duty);
- }
- //UpdatePwm6
- void UpdatePwm6(u16 pwm_tmp6)
- {
- P_SW2 |= 0x80;
- PWMB_CCR2H = (u8)(pwm_tmp6 >> 8); //设置占空比时间
- PWMB_CCR2L = (u8)(pwm_tmp6);
- P_SW2 &= 0x7f;
- }
复制代码
测试效果600RPM
测试效果1200RPM
测试效果1800RPM
测试效果8000RPM
测试效果12000RPM
完整代码
FG-PID.rar
(36.98 KB, 下载次数: 271)
|