[PIC®/AVR®/dsPIC®产品] 基于PIC18F16Q40使用PID实现水温调节

[复制链接]
 楼主| 天灵灵地灵灵 发表于 2023-5-23 23:06 | 显示全部楼层 |阅读模式
  1. #include <xc.h>

  2. // 定义PID参数
  3. double kp = 0.5;    // 比例系数
  4. double ki = 0.2;    // 积分系数
  5. double kd = 0.1;    // 微分系数

  6. // 定义PID变量
  7. double setpoint = 40.0;     // 目标温度设定值
  8. double integral = 0.0;      // 积分项
  9. double last_error = 0.0;    // 上一次误差值

  10. // 定义PWM相关变量
  11. unsigned int duty_cycle = 0;    // PWM占空比
  12. unsigned int pwm_period = 1000; // PWM周期

  13. // ADC初始化
  14. void ADC_Init() {
  15.     ADCON0 = 0b00000001;    // 设置ADC转换通道和使能ADC模块
  16.     ADCON1 = 0b00001110;    // 设置ADC输入和参考电压
  17.     ADCON2 = 0b10111110;    // 设置ADC时钟和转换时钟周期
  18.     ADRESH = 0;             // 清零高字节寄存器
  19.     ADRESL = 0;             // 清零低字节寄存器
  20.     ADCON0bits.GO = 1;      // 启动ADC转换
  21. }

  22. // PWM初始化
  23. void PWM_Init() {
  24.     CCP1CON = 0b00001100;   // 选择PWM模式,无输出反转
  25.     CCPR1L = 0;             // 设置初始PWM占空比为0
  26.     PR2 = pwm_period;       // 设置PWM周期
  27.     T2CON = 0b00000100;     // 启动定时器2,选择预分频器为1
  28. }

  29. // PID控制函数
  30. void PID_Control() {
  31.     // 读取温度值
  32.     ADCON0bits.GO = 1;              // 启动ADC转换
  33.     while (ADCON0bits.GO);          // 等待ADC转换完成
  34.     unsigned int temp = ADRESH;     // 读取高字节寄存器值
  35.     temp = (temp << 8) + ADRESL;    // 读取完整的ADC值

  36.     // 计算误差
  37.     double error = setpoint - temp;

  38.     // 计算PID输出
  39.     double output = kp * error + ki * integral + kd * (error - last_error);

  40.     // 更新PWM占空比
  41.     duty_cycle = output;
  42. }

  43. // 更新PWM占空比
  44. void Update_PWM_DutyCycle() {
  45.     unsigned int temp_duty = (unsigned int)(duty_cycle * pwm_period);

  46.     // 防止溢出
  47.     if (temp_duty > pwm_period)
  48.         temp_duty = pwm_period;

  49.     // 更新PWM占空比
  50.     CCPR1L = temp_duty >> 2;
  51.     CCP1CONbits.DC1B = temp_duty & 0x03;
  52. }

  53. int main() {
  54.     // 初始化ADC和PWM
  55.     ADC_Init();
  56.     PWM_Init();

  57.     while (1) {
  58.         // 执行PID控制
  59.         PID_Control();

  60.         // 更新PWM占空比
  61.         Update_PWM_DutyCycle();
  62.     }

  63.    return 0;
  64. }


 楼主| 天灵灵地灵灵 发表于 2023-5-23 23:06 | 显示全部楼层
在主函数中,我们不断循环执行PID控制和更新PWM占空比的操作。通过调用PID_Control函数,我们获取当前温度并计算PID输出。然后,通过调用Update_PWM_DutyCycle函数,将PID输出转换为PWM占空比,并更新PWM模块的输出。

请注意,这只是一个简化的示例代码,用于演示PID控制的基本原理和水温加热的应用。在实际应用中,你可能需要根据具体的硬件和需求进行适当的修改和优化,例如根据传感器特性进行温度转换,设置合适的PID参数,处理系统边界情况等。

另外,上述代码仅给出了PID控制的基本框架,并未涉及具体的初始化和配置细节。在实际使用时,你需要根据PIC18F16Q40的引脚分配、时钟设置和相关模块的配置等进行适当的初始化和配置。

希望以上代码能对你有所帮助,并引导你在PIC18F16Q40上实现PID控制来控制水温加热。
pzsh 发表于 2023-9-18 20:31 | 显示全部楼层
需要实地调节P,I,D 参数
您需要登录后才可以回帖 登录 | 注册

本版积分规则

182

主题

3469

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部