4. 传感器故障诊断:传感器自检、阈值校验、多传感器一致性校验、传感器冗余切换
传感器这东西,在温室里就是我们的「眼睛」和「耳朵」。眼睛花了,耳朵聋了,那整个控制系统就是在瞎指挥。我见过太多温室项目,最后出问题都出在传感器上——不是数据不准,而是压根没发现它已经坏了。
所以这一节,咱们重点聊聊怎么让传感器「自己报故障」。说白了,就是给它装一套自我体检系统。
4.1 传感器自检——上电先查体
我个人习惯,每次系统上电,第一件事不是干活,而是让所有传感器做一遍自检。就像你去医院体检,先量血压、测心率,对吧?
自检分两个层面:
- 硬件自检:传感器内部有没有短路、断路?供电电压稳不稳?
- 通信自检:数据线通不通?能不能正常响应主机的查询指令?
举个例子,我常用的温湿度传感器 SHT30,它内部有个状态寄存器。上电后我发一条指令读这个寄存器,如果返回的值不对,那基本可以判定传感器挂了。
// 伪代码:传感器自检流程
bool sensor_self_check(uint8_t sensor_id) {
// 1. 发送自检指令
send_command(sensor_id, CMD_READ_STATUS);
// 2. 等待响应,超时500ms
uint16_t status = wait_response(sensor_id, 500);
// 3. 检查状态位
if (status & STATUS_BIT_ALERT) {
log_error("传感器 %d 报警", sensor_id);
return false;
}
// 4. 读取一次数据,看是否在合理范围
float temp = read_temperature(sensor_id);
if (temp < -40.0f || temp > 85.0f) {
log_error("传感器 %d 数据异常", sensor_id);
return false;
}
return true;
}
4.2 阈值校验——数据不能太离谱
阈值校验,说白了就是给数据画个「安全框」。温室里温度再高,也不可能到80度;湿度再低,也不会是0%。
我一般设两级阈值:
| 阈值类型 | 温度范围(℃) | 湿度范围(%RH) | CO2浓度(ppm) |
|---|---|---|---|
| 合理范围 | -10 ~ 50 | 10 ~ 100 | 300 ~ 2000 |
| 警告范围 | 0 ~ 45 | 20 ~ 95 | 400 ~ 1500 |
超出合理范围,直接判定传感器故障。超出警告范围,记录日志,但系统继续运行,只是提醒维护人员检查。
嗯,这里要注意:阈值不能设得太死。我记得有一次在北方冬季的温室项目,室外温度零下20度,传感器靠近门口安装,偶尔会测到零下15度。如果阈值设成零下10度,那传感器天天报故障。后来我把阈值放宽到零下20度,同时加了「持续超限」的判断——连续5次采样都超限,才判定故障。
// 阈值校验示例
typedef struct {
float min_valid;
float max_valid;
float min_warn;
float max_warn;
uint8_t fault_count;
} ThresholdConfig;
bool threshold_check(float value, ThresholdConfig *cfg) {
// 超出合理范围,直接故障
if (value < cfg->min_valid || value > cfg->max_valid) {
return false;
}
// 超出警告范围,计数
if (value < cfg->min_warn || value > cfg->max_warn) {
cfg->fault_count++;
if (cfg->fault_count >= 5) {
return false; // 连续5次超限,判定故障
}
} else {
cfg->fault_count = 0; // 恢复正常,清零计数
}
return true;
}
4.3 多传感器一致性校验——三个和尚没水喝?
温室里同一个区域,我通常会装2~3个同类型传感器。为什么?因为单个传感器可能骗你,但多个传感器一起骗你的概率就小多了。
一致性校验的核心思想:如果两个传感器测同一个东西,结果差太多,那肯定有一个有问题。
我常用的方法是「多数投票法」:
- 取3个传感器的读数
- 两两比较差值
- 如果某两个差值小于阈值(比如温度差小于1℃),认为它们一致
- 取一致的那组数据的平均值作为最终值
- 如果三个数据两两都不一致,那... 全都有问题,触发报警
所以我现在做一致性校验,会加一个「位置权重」:
// 带位置权重的一致性校验
typedef struct {
float value;
float weight; // 位置权重,中心区域权重高,边缘权重低
uint8_t location_id;
} SensorData;
float consensus_check(SensorData sensors[], uint8_t count) {
float weighted_sum = 0;
float total_weight = 0;
uint8_t valid_count = 0;
for (int i = 0; i < count; i++) {
for (int j = i + 1; j < count; j++) {
float diff = fabs(sensors[i].value - sensors[j].value);
if (diff < CONSENSUS_THRESHOLD) {
// 这两个传感器一致,都标记为有效
sensors[i].weight = MAX(sensors[i].weight, 0.5f);
sensors[j].weight = MAX(sensors[j].weight, 0.5f);
}
}
}
// 计算加权平均值
for (int i = 0; i < count; i++) {
if (sensors[i].weight > 0) {
weighted_sum += sensors[i].value * sensors[i].weight;
total_weight += sensors[i].weight;
valid_count++;
}
}
if (valid_count < 2) {
// 有效传感器不足2个,触发故障
return NAN;
}
return weighted_sum / total_weight;
}
4.4 传感器冗余切换——主备无缝衔接
冗余切换,说白了就是「备胎转正」。主传感器坏了,备用的立刻顶上,系统不能停。
我常用的冗余架构有两种:
- 冷备份:备用传感器平时不工作,主传感器故障时才启动。优点是省电,缺点是切换时有短暂的数据空白。
- 热备份:备用传感器一直工作,数据同步更新。主传感器故障时,直接切换数据源,几乎无感。
温室控制我建议用热备份。为什么?因为温室的惯性大,几分钟的数据空白可能就导致温度失控了。
切换逻辑我一般这样设计:
// 冗余切换逻辑
typedef struct {
uint8_t primary_id;
uint8_t backup_id;
bool primary_fault;
bool backup_fault;
float last_valid_value;
uint32_t switch_time;
} RedundancyManager;
float get_redundant_value(RedundancyManager *mgr) {
// 先读主传感器
float primary_val = read_sensor(mgr->primary_id);
bool primary_ok = threshold_check(primary_val, &threshold_cfg);
if (primary_ok) {
mgr->primary_fault = false;
mgr->last_valid_value = primary_val;
return primary_val;
}
// 主传感器故障,切到备用
mgr->primary_fault = true;
log_warning("主传感器 %d 故障,切换到备用传感器 %d",
mgr->primary_id, mgr->backup_id);
float backup_val = read_sensor(mgr->backup_id);
bool backup_ok = threshold_check(backup_val, &threshold_cfg);
if (backup_ok) {
mgr->backup_fault = false;
mgr->last_valid_value = backup_val;
mgr->switch_time = get_system_time();
return backup_val;
}
// 两个都故障,返回最后一次有效值
mgr->backup_fault = true;
log_error("主备传感器均故障,使用最后有效值 %.2f", mgr->last_valid_value);
return mgr->last_valid_value;
}
这里有个细节:切换后要记录切换时间。如果短时间内频繁切换(比如几分钟内切了十几次),说明两个传感器可能都有问题,或者环境有剧烈变化。这时候应该触发高级报警,通知维护人员介入。
好了,传感器故障诊断这块,核心就是这四个步骤:自检、阈值、一致性、冗余切换。每一步都不能省,每一步都有坑。你把这些做好了,温室控制系统至少能扛住90%的传感器故障场景。