基于LPC2124的温度模糊控制系统Proteus仿真

基于LPC2124的温度模糊控制系统Proteus仿真

一、系统概述

本系统采用NXP LPC2124(ARM7TDMI-S内核)微控制器作为核心,结合模糊控制算法实现对温度的智能调节。系统通过温度传感器采集实时温度,经模糊控制器处理后输出PWM信号驱动加热/制冷装置,形成闭环控制。整个系统可在Proteus 8中完成软硬件联合仿真。

二、系统架构

1. 系统框图

┌─────────────────────────────────────────────────────┐
│                温度模糊控制系统                      │
├─────────────────────────────────────────────────────┤
│ 温度传感器 → ADC采集 → LPC2124 → PWM输出 → 执行机构 │
│    (DS18B20/LM35)   │ 模糊控制算法 │ (加热器/风扇)  │
│                     ↓              │                 │
│                LCD显示模块         │                 │
└─────────────────────────────────────────────────────┘

2. 核心组件

模块 器件型号 功能说明
主控制器 LPC2124 ARM7内核,主频60MHz
温度传感器 DS18B20或LM35 温度采集,精度±0.5°C
显示模块 LCD1602 显示当前温度和设定温度
执行机构 加热电阻+风扇 双向温度调节
驱动电路 三极管/继电器 功率放大与控制
仿真环境 Proteus 8.9+ 电路设计与程序仿真
开发环境 Keil MDK-ARM ARM程序开发与编译

三、硬件电路设计(Proteus)

1. Proteus元件清单

元件类别 元件名称 Proteus库中名称
微控制器 LPC2124 LPC2124
温度传感器 DS18B20 DS18B20
显示模块 LCD1602 LM016L (16×2字符LCD)
加热元件 加热电阻 RESISTOR (100Ω/10W)
冷却元件 直流风扇 MOTOR-DC
驱动器件 三极管 2N2222 (NPN)
驱动器件 继电器 RELAY-SPST
电源 直流电源 BATTERY (5V/12V)
调试接口 虚拟终端 VIRTUAL TERMINAL
测量仪器 电压表/电流表 DC VOLTMETER/AMMETER

2. Proteus电路原理图设计

主控电路

LPC2124引脚分配:
P0.0-P0.7  → LCD数据线D0-D7
P0.8       → LCD RS (寄存器选择)
P0.9       → LCD RW (读写控制)
P0.10      → LCD EN (使能信号)
P0.28      → DS18B20数据线 (单总线)
P0.29      → 加热控制PWM输出
P0.30      → 风扇控制PWM输出
P0.31      → ADC输入 (LM35模拟输入)
VDD        → 3.3V电源
VSS        → GND

温度采集电路

功率驱动电路

加热控制:
LPC2124 P0.29 → 1kΩ电阻 → 2N2222基极
2N2222集电极 → 加热电阻 → 12V电源
2N2222发射极 → GND

风扇控制:
LPC2124 P0.30 → 1kΩ电阻 → 继电器线圈
继电器常开触点 → 12V风扇

3. Proteus仿真文件设置

  1. 创建新工程:选择"LPC2124"作为微控制器
  2. 添加元件:从库中搜索并放置上述元件
  3. 连线:按照原理图连接各元件
  4. 电源配置:添加+3.3V和+12V电源
  5. 添加虚拟仪器:用于监测温度和控制信号

四、模糊控制算法设计

1. 模糊控制器结构

输入变量:
E (误差) = 设定温度 - 实际温度
EC (误差变化率) = dE/dt

输出变量:
U (控制量) = PWM占空比 (0-100%)

模糊集定义:
E: {NB, NM, NS, ZO, PS, PM, PB}  (负大,负中,负小,零,正小,正中,正大)
EC: {NB, NM, NS, ZO, PS, PM, PB}
U: {NB, NM, NS, ZO, PS, PM, PB}

2. 隶属度函数设计

// 三角形隶属度函数
typedef struct {
    float a;  // 左边界
    float b;  // 中心点
    float c;  // 右边界
} TriangleMF;

// 误差E的隶属度函数 (-10°C ~ +10°C)
TriangleMF E_mf[7] = {
    {-10, -10, -6},   // NB
    {-8, -5, -2},     // NM
    {-4, -2, 0},      // NS
    {-1, 0, 1},       // ZO
    {0, 2, 4},        // PS
    {2, 5, 8},        // PM
    {6, 10, 10}       // PB
};

// 误差变化率EC的隶属度函数 (-5°C/s ~ +5°C/s)
TriangleMF EC_mf[7] = {
    {-5, -5, -3},     // NB
    {-4, -2, -1},     // NM
    {-2, -1, 0},      // NS
    {-0.5, 0, 0.5},   // ZO
    {0, 1, 2},        // PS
    {1, 2, 4},        // PM
    {3, 5, 5}         // PB
};

3. 模糊规则库(49条规则)

// 模糊规则表 [E][EC] → U
uint8_t fuzzy_rule[7][7] = {
    // EC: NB  NM  NS  ZO  PS  PM  PB
    {  6,  6,  5,  5,  4,  3,  2 },  // E: NB (温度过低)
    {  6,  5,  5,  4,  3,  2,  1 },  // E: NM
    {  5,  5,  4,  3,  2,  1,  0 },  // E: NS
    {  4,  3,  2,  0, -2, -3, -4 },  // E: ZO (接近设定)
    {  0, -1, -2, -3, -4, -5, -5 },  // E: PS
    { -1, -2, -3, -4, -5, -5, -6 },  // E: PM
    { -2, -3, -4, -5, -5, -6, -6 }   // E: PB (温度过高)
};
// 注:输出值0-6对应模糊集{NB...PB},实际控制量需去模糊化

4. 模糊推理与去模糊化

// 重心法去模糊化
float defuzzify(float *membership, float *output_values) {
    float numerator = 0.0;
    float denominator = 0.0;
    
    for(int i = 0; i < 7; i++) {
        numerator += membership[i] * output_values[i];
        denominator += membership[i];
    }
    
    if(denominator == 0) return 0.0;
    return numerator / denominator;
}

参考代码 基于LPC2124的温度模糊控制系统Proteus仿真 www.youwenfan.com/contentcnt/135550.html

五、软件程序设计

1. 主程序框架(main.c)

#include "LPC21xx.h"
#include "fuzzy.h"
#include "lcd.h"
#include "ds18b20.h"
#include "pwm.h"

// 全局变量
float set_temp = 25.0;      // 设定温度
float current_temp = 0.0;   // 当前温度
float last_temp = 0.0;      // 上次温度
float error = 0.0;          // 误差
float error_change = 0.0;   // 误差变化率
float control_output = 0.0; // 控制输出

// 系统初始化
void SystemInit(void) {
    // 1. 系统时钟初始化
    PLL_init();
    
    // 2. GPIO初始化
    GPIO_Init();
    
    // 3. 定时器初始化(用于PWM和采样)
    Timer0_Init();
    Timer1_Init();
    
    // 4. ADC初始化(如果使用LM35)
    ADC_Init();
    
    // 5. PWM初始化
    PWM_Init();
    
    // 6. LCD初始化
    LCD_Init();
    
    // 7. DS18B20初始化
    DS18B20_Init();
    
    // 8. 中断初始化
    Interrupt_Init();
}

// 主循环
int main(void) {
    SystemInit();
    LCD_DisplayString("Temp Ctrl System");
    delay_ms(1000);
    LCD_Clear();
    
    while(1) {
        // 1. 温度采集
        current_temp = Read_Temperature();
        
        // 2. 计算误差和误差变化率
        error = set_temp - current_temp;
        error_change = (current_temp - last_temp) / SAMPLE_TIME;
        last_temp = current_temp;
        
        // 3. 模糊控制计算
        control_output = Fuzzy_Controller(error, error_change);
        
        // 4. 输出控制信号
        if(control_output > 0) {
            // 需要加热
            Set_Heater_PWM(control_output);
            Set_Fan_PWM(0);
        } else {
            // 需要冷却
            Set_Heater_PWM(0);
            Set_Fan_PWM(-control_output);
        }
        
        // 5. 显示更新
        Display_Update();
        
        // 6. 延时(采样周期)
        delay_ms(SAMPLE_PERIOD);
    }
    return 0;
}

2. 模糊控制核心代码(fuzzy.c)

#include "fuzzy.h"

// 计算隶属度
void calculate_membership(float input, TriangleMF *mf, float *membership) {
    for(int i = 0; i < 7; i++) {
        if(input <= mf[i].a || input >= mf[i].c) {
            membership[i] = 0.0;
        } else if(input > mf[i].a && input <= mf[i].b) {
            membership[i] = (input - mf[i].a) / (mf[i].b - mf[i].a);
        } else {
            membership[i] = (mf[i].c - input) / (mf[i].c - mf[i].b);
        }
    }
}

// 模糊控制器
float Fuzzy_Controller(float e, float ec) {
    float e_membership[7], ec_membership[7];
    float rule_strength[7][7];
    float output_membership[7] = {0};
    
    // 1. 模糊化
    calculate_membership(e, E_mf, e_membership);
    calculate_membership(ec, EC_mf, ec_membership);
    
    // 2. 规则评估(Mamdani推理,取小运算)
    for(int i = 0; i < 7; i++) {
        for(int j = 0; j < 7; j++) {
            rule_strength[i][j] = (e_membership[i] < ec_membership[j]) ? 
                                   e_membership[i] : ec_membership[j];
        }
    }
    
    // 3. 规则聚合(取大运算)
    for(int i = 0; i < 7; i++) {
        for(int j = 0; j < 7; j++) {
            int output_index = fuzzy_rule[i][j] + 3; // 映射到0-6
            if(rule_strength[i][j] > output_membership[output_index]) {
                output_membership[output_index] = rule_strength[i][j];
            }
        }
    }
    
    // 4. 去模糊化(重心法)
    float output_values[7] = {-100, -66, -33, 0, 33, 66, 100}; // 输出论域
    return defuzzify(output_membership, output_values);
}

3. DS18B20驱动代码(ds18b20.c)

#include "ds18b20.h"

// DS18B20初始化
void DS18B20_Init(void) {
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM
    DS18B20_WriteByte(0x44); // 启动温度转换
}

// 读取温度
float Read_Temperature(void) {
    uint8_t temp_l, temp_h;
    int16_t temp;
    float temperature;
    
    DS18B20_Reset();
    DS18B20_WriteByte(0xCC); // 跳过ROM
    DS18B20_WriteByte(0xBE); // 读暂存器
    
    temp_l = DS18B20_ReadByte();
    temp_h = DS18B20_ReadByte();
    
    temp = (temp_h << 8) | temp_l;
    temperature = temp * 0.0625; // 12位分辨率
    
    return temperature;
}

// 单总线延时函数
void DS18B20_Delay_us(uint32_t us) {
    uint32_t i;
    for(i = 0; i < us * 10; i++);
}

// 复位DS18B20
uint8_t DS18B20_Reset(void) {
    uint8_t presence = 0;
    
    DS18B20_OUTPUT();
    DS18B20_LOW();
    DS18B20_Delay_us(480);
    
    DS18B20_INPUT();
    DS18B20_Delay_us(60);
    
    presence = !DS18B20_READ();
    DS18B20_Delay_us(420);
    
    return presence;
}

4. PWM控制代码(pwm.c)

#include "pwm.h"

// PWM初始化
void PWM_Init(void) {
    // 配置P0.29为PWM1输出(加热控制)
    PINSEL0 |= (1 << 26); // 选择PWM1功能
    
    // 配置P0.30为PWM2输出(风扇控制)
    PINSEL0 |= (1 << 28); // 选择PWM2功能
    
    // PWM预分频设置
    PWMPR = 0; // 不分频
    
    // 设置PWM周期(决定PWM频率)
    PWMMR0 = 10000; // 假设系统时钟60MHz,PWM频率=60MHz/10000=6kHz
    
    // 设置PWM匹配控制
    PWMMCR = (1 << 1); // MR0匹配时复位计数器
    
    // 使能PWM输出
    PWMPCR = (1 << 9) | (1 << 10); // 使能PWM1和PWM2输出
    
    // 启动PWM
    PWMTCR = (1 << 0) | (1 << 3); // 计数器使能,PWM使能
}

// 设置加热器PWM占空比
void Set_Heater_PWM(float duty) {
    if(duty < 0) duty = 0;
    if(duty > 100) duty = 100;
    
    uint32_t match_value = (uint32_t)(PWMMR0 * duty / 100.0);
    PWMMR1 = match_value; // PWM1匹配值
    PWMLER = (1 << 1);    // 锁存MR1新值
}

// 设置风扇PWM占空比
void Set_Fan_PWM(float duty) {
    if(duty < 0) duty = 0;
    if(duty > 100) duty = 100;
    
    uint32_t match_value = (uint32_t)(PWMMR0 * duty / 100.0);
    PWMMR2 = match_value; // PWM2匹配值
    PWMLER = (1 << 2);    // 锁存MR2新值
}

5. LCD显示代码(lcd.c)

#include "lcd.h"

// LCD初始化
void LCD_Init(void) {
    delay_ms(15);
    LCD_WriteCommand(0x38); // 8位数据,2行显示,5×7点阵
    LCD_WriteCommand(0x0C); // 显示开,光标关,闪烁关
    LCD_WriteCommand(0x06); // 写入后光标右移
    LCD_WriteCommand(0x01); // 清屏
    delay_ms(2);
}

// 显示温度信息
void Display_Update(void) {
    char buffer[16];
    
    // 第一行:当前温度
    LCD_SetCursor(0, 0);
    sprintf(buffer, "Temp:%5.1fC", current_temp);
    LCD_DisplayString(buffer);
    
    // 第二行:设定温度和控制输出
    LCD_SetCursor(0, 1);
    sprintf(buffer, "Set:%3.1f Out:%3.0f%%", set_temp, control_output);
    LCD_DisplayString(buffer);
}

// LCD写命令
void LCD_WriteCommand(uint8_t cmd) {
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_DATA = cmd;
    LCD_EN = 1;
    delay_us(1);
    LCD_EN = 0;
    delay_ms(2);
}

// LCD写数据
void LCD_WriteData(uint8_t dat) {
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_DATA = dat;
    LCD_EN = 1;
    delay_us(1);
    LCD_EN = 0;
    delay_us(100);
}

六、Proteus仿真步骤

1. 仿真环境搭建

  1. 安装软件

    • Proteus 8.9或更高版本
    • Keil MDK-ARM(用于编译代码)
    • LPC2124设备库(Proteus自带)
  2. 创建Proteus工程

    • 新建工程,选择"LPC2124"作为微控制器
    • 添加所需元件并连接电路
    • 设置电源:VDD=3.3V,VCC=5V(传感器)

2. 程序编译与加载

  1. Keil工程配置

    目标设备:LPC2124
    编译器:ARM Compiler V5
    优化等级:Level 2 (-O2)
    输出文件:生成HEX文件
    
  2. 编译程序

    • 将上述C代码文件添加到Keil工程
    • 配置正确的头文件路径
    • 编译生成fuzzy.hex文件
  3. 加载到Proteus

    • 双击Proteus中的LPC2124元件
    • 在"Program File"中选择生成的HEX文件
    • 设置时钟频率为12MHz(外部晶振)

3. 仿真运行与调试

  1. 启动仿真

    • 点击Proteus左下角的"运行"按钮
    • 系统开始运行,LCD显示初始化信息
  2. 温度设置

    • 通过虚拟终端发送命令设置温度
    • 示例命令:SET 30.0(设置目标温度为30°C)
  3. 监测信号

    • 使用Proteus示波器观察PWM波形
    • 使用电压表监测温度传感器输出
    • 观察LCD显示的温度变化
  4. 性能测试

    • 改变环境温度(修改DS18B20的温度值)
    • 观察系统的响应速度和稳态误差
    • 记录超调量和调节时间

七、系统测试与优化

1. 性能测试指标

测试项目 期望值 测试方法
稳态误差 ±0.5°C以内 保持环境温度稳定,记录偏差
调节时间 < 60秒 从阶跃响应开始到进入稳态的时间
超调量 < 5% 最大超调温度与设定温度的比值
温度分辨率 0.1°C 观察最小可分辨的温度变化
控制范围 0-50°C 测试系统在不同设定温度下的性能

2. 模糊规则优化

根据仿真结果调整模糊规则:

// 优化后的规则表(减少超调)
uint8_t fuzzy_rule_optimized[7][7] = {
    {  6,  6,  5,  4,  3,  2,  1 },
    {  5,  5,  4,  3,  2,  1,  0 },
    {  4,  4,  3,  2,  1,  0, -1 },
    {  3,  2,  1,  0, -1, -2, -3 },
    { -1,  0, -1, -2, -3, -4, -4 },
    {  0, -1, -2, -3, -4, -5, -5 },
    {  1, -2, -3, -4, -5, -6, -6 }
};

3. PID-模糊复合控制

// 结合PID提高稳态精度
float PID_Fuzzy_Controller(float e, float ec) {
    float fuzzy_output = Fuzzy_Controller(e, ec);
    float pid_output = PID_Controller(e);
    
    // 模糊控制主导动态过程,PID控制主导稳态
    float weight = fabs(e) / 10.0; // 误差越大,模糊权重越高
    if(weight > 1.0) weight = 1.0;
    
    return weight * fuzzy_output + (1 - weight) * pid_output;
}

八、常见问题与解决

1. Proteus仿真问题

问题 可能原因 解决方案
LPC2124无法运行程序 HEX文件未正确加载 检查HEX文件路径,重新编译
DS18B20温度读取失败 单总线时序不准确 调整延时函数,检查上拉电阻
LCD显示乱码 初始化时序不正确 增加初始化延时,检查命令顺序
PWM输出无波形 引脚功能未正确配置 检查PINSEL寄存器设置
仿真运行缓慢 计算机性能不足 关闭不必要的虚拟仪器,简化电路

2. 程序调试技巧

  1. 使用虚拟终端:输出调试信息

    void UART_SendString(char *str) {
        while(*str) {
            while(!(U0LSR & 0x20));
            U0THR = *str++;
        }
    }
    
  2. 添加软件断点:在关键位置添加LED指示

    void Debug_LED(uint8_t state) {
        if(state) IO0SET = (1 << 11);  // P0.11 LED亮
        else IO0CLR = (1 << 11);       // P0.11 LED灭
    }
    
  3. 变量监视:通过LCD显示关键变量值

九、扩展应用

1. 多区域温度控制

// 扩展为多路温度控制
#define ZONE_COUNT 3
float zone_temp[ZONE_COUNT];
float zone_setpoint[ZONE_COUNT];
float zone_output[ZONE_COUNT];

void MultiZone_Control(void) {
    for(int i = 0; i < ZONE_COUNT; i++) {
        float error = zone_setpoint[i] - zone_temp[i];
        float ec = (zone_temp[i] - last_zone_temp[i]) / SAMPLE_TIME;
        zone_output[i] = Fuzzy_Controller(error, ec);
        last_zone_temp[i] = zone_temp[i];
    }
}

2. 网络通信功能

3. 数据记录与分析

总结

本设计实现了基于LPC2124的温度模糊控制系统Proteus仿真,具有以下特点:

  1. 完整的软硬件方案:提供从电路设计到程序代码的全套解决方案
  2. 智能控制算法:采用模糊控制,适应非线性温度系统
  3. 可视化仿真:Proteus环境下实时观察系统运行状态
  4. 易于扩展:模块化设计,便于功能扩展和修改
  5. 教学实用:适合嵌入式系统、自动控制原理等课程设计

通过本仿真系统,可以深入理解:

后续改进方向

  1. 增加PID-模糊复合控制提高精度
  2. 添加触摸屏人机界面
  3. 实现物联网远程监控
  4. 优化节能控制策略

专注于matlab/simulink,电子电路,编程