基于openEuler构建嵌入式智能温控系统实战
环境准备与验证
系统基础环境检查
首先确认openEuler环境的基本信息:
# 查看系统版本和内核
cat /etc/os-release
uname -r
echo "当前用户:$(whoami)"
echo "工作目录:$(pwd)"
安装开发工具链
# 安装必要的编译和调试工具
sudo dnf update -y
sudo dnf install -y gcc gcc-c++ make cmake gdb
sudo dnf install -y python3 python3-pip
# 验证工具链版本
gcc --version
make --version
cmake --version
实战项目:智能温控系统
系统架构
智能温控系统架构:
├── 传感数据采集
│ ├── 温度采集(模拟)
│ ├── 湿度采集(模拟)
│ └── 数据滤波
├── 控制算法
│ ├── PID控制器
│ ├── 阈值管理
│ └── 状态机
├── 执行器控制
│ ├── 加热器
│ ├── 冷却器
│ └── 风扇
└── 交互界面
├── 实时显示
├── 参数配置
└── 日志
第一步:创建项目目录结构
# 建立项目目录
mkdir -p ~/smart_thermostat/{src,include,config,test,logs}
cd ~/smart_thermostat
# 创建说明文件
cat > README.md << 'EOF'
# 智能温控系统 - openEuler嵌入式实战
## 项目描述
基于openEuler的嵌入式智能温控系统模拟,包含传感器采集、PID控制和执行器管理。
## 特性
- 多传感器模拟采集
- PID温度控制算法
- 实时监控
- 日志记录
- 可配置阈值
## 编译运行
make && ./thermostat
EOF
第二步:硬件抽象层实现
创建硬件头文件:
// include/hardware.h
#ifndef HARDWARE_H
#define HARDWARE_H
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
typedef enum {
DEV_OFF = 0,
DEV_ON = 1
} dev_state_t;
typedef struct {
float temp;
float hum;
float target;
uint32_t ts;
} sensor_data_t;
typedef struct {
dev_state_t heater;
dev_state_t cooler;
dev_state_t fan;
float power;
} actuator_state_t;
typedef struct {
sensor_data_t sensors;
actuator_state_t act;
uint32_t runtime;
uint8_t mode;
uint8_t error;
} sys_state_t;
int init_hardware(void);
int read_temp(float *val);
int read_hum(float *val);
int ctrl_heater(dev_state_t st);
int ctrl_cooler(dev_state_t st);
int ctrl_fan(dev_state_t st);
int set_power(float level);
uint32_t get_time(void);
void delay_ms(uint32_t ms);
void show_status(const sys_state_t *st);
#endif
实现硬件抽象层:
// src/hardware.c
#include "hardware.h"
static uint32_t rnd_seed = 0;
static uint32_t rnd_next(void) {
if (rnd_seed == 0) {
rnd_seed = (uint32_t)time(NULL);
}
rnd_seed = (rnd_seed * 1103515245 + 12345) & 0x7FFFFFFF;
return rnd_seed;
}
static float drift_temp = 22.0;
int init_hardware(void) {
puts("=== 硬件初始化 ===");
puts("温度传感器: 就绪");
puts("湿度传感器: 就绪");
puts("执行器: 就绪");
puts("===================");
rnd_seed = (uint32_t)time(NULL);
drift_temp = 22.0 + (rnd_next() % 100) / 100.0;
return 0;
}
int read_temp(float *val) {
if (!val) return -1;
float noise = (rnd_next() % 200 - 100) / 1000.0;
drift_temp += noise;
if (drift_temp < 15.0) drift_temp = 15.0;
if (drift_temp > 35.0) drift_temp = 35.0;
*val = drift_temp;
return 0;
}
int read_hum(float *val) {
if (!val) return -1;
float base = 60.0;
float var = (rnd_next() % 300 - 150) / 100.0;
*val = base + var;
if (*val < 45.0) *val = 45.0;
if (*val > 75.0) *val = 75.0;
return 0;
}
static actuator_state_t g_act = {
.heater = DEV_OFF,
.cooler = DEV_OFF,
.fan = DEV_OFF,
.power = 0.0
};
int ctrl_heater(dev_state_t st) {
g_act.heater = st;
if (st == DEV_ON) {
drift_temp += 0.05 * g_act.power;
}
printf("[执行器] 加热器: %s\n", st == DEV_ON ? "开" : "关");
return 0;
}
int ctrl_cooler(dev_state_t st) {
g_act.cooler = st;
if (st == DEV_ON) {
drift_temp -= 0.05 * g_act.power;
}
printf("[执行器] 冷却器: %s\n", st == DEV_ON ? "开" : "关");
return 0;
}
int ctrl_fan(dev_state_t st) {
g_act.fan = st;
printf("[执行器] 风扇: %s\n", st == DEV_ON ? "开" : "关");
return 0;
}
int set_power(float level) {
if (level < 0.0) level = 0.0;
if (level > 1.0) level = 1.0;
g_act.power = level;
printf("[执行器] 功率: %.1f%%\n", level * 100.0);
return 0;
}
uint32_t get_time(void) {
return (uint32_t)time(NULL);
}
void delay_ms(uint32_t ms) {
usleep(ms * 1000);
}
void show_status(const sys_state_t *st) {
if (!st) return;
printf("\n");
puts("┌──────────────────────────────────────┐");
puts("│ 温控系统状态 │");
puts("├──────────────────────────────────────┤");
printf("│ 温度: %5.1f°C 目标: %5.1f°C │\n",
st->sensors.temp, st->sensors.target);
printf("│ 湿度: %5.1f%% 运行: %5u秒 │\n",
st->sensors.hum, st->runtime);
printf("│ 加热: %-4s 冷却: %-4s │\n",
st->act.heater ? "开" : "关",
st->act.cooler ? "开" : "关");
printf("│ 风扇: %-6s 功率: %4.1f%% │\n",
st->act.fan ? "开" : "关",
st->act.power * 100.0);
printf("│ 模式: %-8s 状态: %-10s │\n",
st->mode == 0 ? "自动" : "手动",
st->error == 0 ? "正常" : "异常");
puts("└──────────────────────────────────────┘");
}
第三步:PID控制算法实现
// src/pid_ctrl.c
#include "hardware.h"
typedef struct {
float kp;
float ki;
float kd;
float setpoint;
float integral;
float prev_err;
float out_min;
float out_max;
uint32_t last_ts;
} pid_ctrl_t;
void pid_setup(pid_ctrl_t *pid, float kp, float ki, float kd, float sp) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->setpoint = sp;
pid->integral = 0.0;
pid->prev_err = 0.0;
pid->out_min = 0.0;
pid->out_max = 1.0;
pid->last_ts = get_time();
}
float pid_calc(pid_ctrl_t *pid, float input) {
uint32_t now = get_time();
float dt = (float)(now - pid->last_ts);
if (dt <= 0) return 0.0;
float err = pid->setpoint - input;
float p_term = pid->kp * err;
pid->integral += err * dt;
float i_limit = 100.0;
if (pid->integral > i_limit) pid->integral = i_limit;
if (pid->integral < -i_limit) pid->integral = -i_limit;
float i_term = pid->ki * pid->integral;
float d_term = pid->kd * (err - pid->prev_err) / dt;
float output = p_term + i_term + d_term;
if (output > pid->out_max) output = pid->out_max;
if (output < pid->out_min) output = pid->out_min;
pid->prev_err = err;
pid->last_ts = now;
printf("[PID] 误差: %.2f, 输出: %.2f (P:%.2f I:%.2f D:%.2f)\n",
err, output, p_term, i_term, d_term);
return output;
}
第四步:主控系统实现
// src/thermostat.c
#include "hardware.h"
typedef struct {
float target_temp;
float tolerance;
float max_heat_pwr;
float max_cool_pwr;
uint32_t interval_ms;
} sys_config_t;
static sys_state_t g_state = {0};
static pid_ctrl_t g_pid = {0};
static sys_config_t g_cfg = {
.target_temp = 24.0,
.tolerance = 0.5,
.max_heat_pwr = 0.8,
.max_cool_pwr = 0.6,
.interval_ms = 2000
};
int sys_boot(void) {
puts("初始化温控系统...");
if (init_hardware() != 0) {
fprintf(stderr, "硬件初始化失败\n");
return -1;
}
pid_setup(&g_pid, 2.0, 0.1, 0.5, g_cfg.target_temp);
g_pid.out_min = -g_cfg.max_cool_pwr;
g_pid.out_max = g_cfg.max_heat_pwr;
g_state.sensors.target = g_cfg.target_temp;
g_state.mode = 0;
g_state.error = 0;
puts("初始化完成");
return 0;
}
void temp_ctrl_loop(void) {
float temp, hum;
if (read_temp(&temp) != 0) {
fprintf(stderr, "温度读取失败\n");
return;
}
if (read_hum(&hum) != 0) {
fprintf(stderr, "湿度读取失败\n");
return;
}
g_state.sensors.temp = temp;
g_state.sensors.hum = hum;
g_state.runtime = get_time();
float output = pid_calc(&g_pid, temp);
if (output > 0) {
ctrl_heater(DEV_ON);
ctrl_cooler(DEV_OFF);
set_power(output);
} else if (output < 0) {
ctrl_heater(DEV_OFF);
ctrl_cooler(DEV_ON);
set_power(-output);
} else {
ctrl_heater(DEV_OFF);
ctrl_cooler(DEV_OFF);
set_power(0.0);
}
float diff = temp - g_cfg.target_temp;
if (fabs(diff) > 2.0) {
ctrl_fan(DEV_ON);
} else {
ctrl_fan(DEV_OFF);
}
g_state.act.heater = (output > 0) ? DEV_ON : DEV_OFF;
g_state.act.cooler = (output < 0) ? DEV_ON : DEV_OFF;
g_state.act.power = fabs(output);
}
void safety_check(void) {
if (g_state.sensors.temp > 40.0) {
puts("[安全] 温度超限! 关闭加热器");
ctrl_heater(DEV_OFF);
ctrl_fan(DEV_ON);
g_state.error = 1;
}
if (g_state.sensors.temp < 10.0) {
puts("[安全] 温度过低!");
g_state.error = 2;
}
if (g_state.runtime > 3600) {
puts("[监控] 系统已运行1小时");
}
}
int main(void) {
puts("=== openEuler温控系统启动 ===");
if (sys_boot() != 0) return -1;
printf("目标温度: %.1f°C\n", g_cfg.target_temp);
printf("控制间隔: %u ms\n", g_cfg.interval_ms);
puts("按Ctrl+C停止\n");
uint32_t cycles = 0;
while (1) {
printf("\n--- 控制周期 #%u ---\n", ++cycles);
temp_ctrl_loop();
safety_check();
show_status(&g_state);
if (cycles % 10 == 0) {
printf("\n[统计] 周期: %u, 温度: %.1f°C, 目标: %.1f°C\n",
cycles, g_state.sensors.temp, g_cfg.target_temp);
}
delay_ms(g_cfg.interval_ms);
}
return 0;
}
第五步:构建配置
# Makefile
cat > Makefile << 'EOF'
CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -O2 -I./include
LDFLAGS = -lm
TARGET = thermostat
SRC = src/hardware.c src/pid_ctrl.c src/thermostat.c
OBJ = $(SRC:.c=.o)
.PHONY: all clean debug run
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(LDFLAGS) -o $@ $^
@echo "=== 编译完成: $(TARGET) ==="
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
debug: CFLAGS += -g -DDEBUG
debug: $(TARGET)
clean:
rm -f $(OBJ) $(TARGET)
@echo "=== 清理 ==="
run: $(TARGET)
./$(TARGET)
install: $(TARGET)
cp $(TARGET) /usr/local/bin/
@echo "=== 安装 ==="
test: $(TARGET)
@echo "=== 测试 (5个周期) ==="
timeout 10s ./$(TARGET) || true
info:
@echo "项目: 智能温控系统"
@echo "目标: $(TARGET)"
@echo "源码: $(SRC)"
@echo "编译器: $(CC)"
@echo "选项: $(CFLAGS)"
EOF
第六步:编译与运行
make clean
make
file thermostat
ls -lh thermostat
./thermostat
编译输出示例:
=== 编译完成: thermostat ===
thermostat: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
-rwxr-xr-x 1 root root 28K 当前时间 thermostat
运行输出片段:
=== openEuler温控系统启动 ===
初始化温控系统...
=== 硬件初始化 ===
温度传感器: 就绪
湿度传感器: 就绪
执行器: 就绪
===================
初始化完成
目标温度: 24.0°C
控制间隔: 2000 ms
--- 控制周期 #1 ---
[PID] 误差: 1.85, 输出: 0.80 (P:3.70 I:0.00 D:0.00)
[执行器] 加热器: 开
[执行器] 冷却器: 关
[执行器] 功率: 80.0%
[执行器] 风扇: 开
┌──────────────────────────────────────┐
│ 温控系统状态 │
├──────────────────────────────────────┤
│ 温度: 22.2°C 目标: 24.0°C │
│ 湿度: 61.5% 运行: 1730000000秒 │
│ 加热: 开 冷却: 关 │
│ 风扇: 开 功率: 80.0% │
│ 模式: 自动 状态: 正常 │
└──────────────────────────────────────┘
--- 控制周期 #2 ---
[PID] 误差: 1.45, 输出: 0.80 (P:2.90 I:0.29 D:-0.39)
[执行器] 加热器: 开
[执行器] 冷却器: 关
[执行器] 功率: 80.0%
[执行器] 风扇: 开
...
如果对openEuler感兴趣,可访问 DistroWatch openEuler页面 或 openEuler官网 获取更多信息。
