feat:增加跌倒时间消抖

fix:修复误触发报警
This commit is contained in:
2026-08-14 16:25:04 +08:00
parent 577eafd0ee
commit 9a4b5cfbeb
+56 -18
View File
@@ -56,14 +56,18 @@ bool g_humiDismissed = false;
uint8_t g_tempAbnCnt = 0;
uint8_t g_humiAbnCnt = 0;
uint8_t g_radarTimeoutCnt = 0;
uint8_t g_heartAbnCnt = 0; // 心率异常防抖
uint8_t g_breathAbnCnt = 0; // 呼吸异常防抖
uint32_t g_heartAbnMs = 0; // 心率异常持续计时 (ms)
uint32_t g_heartNormalMs = 0; // 心率正常持续计时 (ms)
uint32_t g_breathAbnMs = 0; // 呼吸异常持续计时 (ms)
uint32_t g_breathNormalMs = 0; // 呼吸正常持续计时 (ms)
uint32_t g_fallDetectMs = 0; // 跌倒检测计时 (ms)
uint32_t g_fallClearMs = 0; // 跌倒清除计时 (ms)
bool g_fallDismissed = false; // 已手动解除, 不重复报警
#define ALARM_HYSTERESIS 3 // 连续3次确认才触发
#define FALL_DETECT_MS 2000 // 跌倒持续2秒才触发 (房顶安装, 过滤坐下)
#define FALL_CLEAR_MS 5000 // 跌倒消失5秒后才清除 (防误消)
#define FALL_DETECT_MS 10000 // 跌倒持续10秒才触发 (房顶安装, 过滤坐下)
#define FALL_CLEAR_MS 18000 // 跌倒消失18秒后才清除 (防误消)
#define VITAL_DETECT_MS 20000 // 心率/呼吸持续异常20秒才触发
#define VITAL_CLEAR_MS 15000 // 心率/呼吸持续正常15秒才恢复
// ============================================================
// 时间同步
@@ -115,8 +119,10 @@ void handleAlarmCommand(const AlarmCommand& cmd) {
g_tempAbnCnt = 0;
g_humiAbnCnt = 0;
g_radarTimeoutCnt = 0;
g_heartAbnCnt = 0;
g_breathAbnCnt = 0;
g_heartAbnMs = 0;
g_heartNormalMs = 0;
g_breathAbnMs = 0;
g_breathNormalMs = 0;
g_fallDetectMs = 0;
g_fallClearMs = 0;
g_fallDismissed = false;
@@ -335,55 +341,85 @@ void checkLocalAlarms(const RadarRawData& radar) {
g_fallClearMs = 0; // 仍在跌倒, 重置消失计时
}
// ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 防抖3次, 30s) ───
// ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 持续异常20s触发/正常15s恢复, 30s) ───
#if RADAR_TYPE != RADAR_TYPE_AFD1
if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.heartRate > 0) {
bool heartAbn = (radar.heartRate < HEART_RATE_MIN || radar.heartRate > HEART_RATE_MAX);
if (heartAbn) {
if (!g_heartDismissed && ++g_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) {
// 持续异常: 累积时长, 满 VITAL_DETECT_MS 触发
if (!g_heartDismissed && !g_localHeartAbnActive) {
if (g_heartAbnMs == 0) {
g_heartAbnMs = millis();
} else if (millis() - g_heartAbnMs >= VITAL_DETECT_MS) {
g_localHeartAbnActive = true;
char buf[32];
snprintf(buf, sizeof(buf), "心率异常: %d bpm", radar.heartRate);
g_alarm.triggerLocal(AlarmManager::ALARM_HEART_ABNORMAL, buf);
}
}
g_heartNormalMs = 0; // 仍异常, 重置正常计时
} else {
g_heartAbnCnt = 0;
g_heartDismissed = false;
// 持续正常: 累积时长, 满 VITAL_CLEAR_MS 清除 + 重新武装
g_heartAbnMs = 0; // 正常了, 重置异常计时
if (g_heartNormalMs == 0) {
g_heartNormalMs = millis();
}
if (millis() - g_heartNormalMs >= VITAL_CLEAR_MS) {
if (g_localHeartAbnActive) {
g_localHeartAbnActive = false;
g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL);
}
if (g_heartDismissed) {
g_heartDismissed = false; // 持续正常后重新武装
}
}
}
} else if (!humanPresent && g_localHeartAbnActive) {
g_localHeartAbnActive = false;
g_heartAbnCnt = 0;
g_heartAbnMs = 0;
g_heartNormalMs = 0;
g_heartDismissed = false;
g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL);
}
#endif // RADAR_TYPE != AFD1
// ─── ★★★★★ 人身安全: 呼吸异常 (仅卧室+ABD1, 防抖3次, 30秒后生效) ───
// ─── ★★★★★ 人身安全: 呼吸异常 (仅卧室+ABD1, 持续异常20s触发/正常15s恢复, 30秒后生效) ───
#if RADAR_TYPE != RADAR_TYPE_AFD1
if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.breathRate > 0) {
bool breathAbn = (radar.breathRate < BREATH_RATE_MIN || radar.breathRate > BREATH_RATE_MAX);
if (breathAbn) {
if (!g_breathDismissed && ++g_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) {
// 持续异常: 累积时长, 满 VITAL_DETECT_MS 触发
if (!g_breathDismissed && !g_localBreathAbnActive) {
if (g_breathAbnMs == 0) {
g_breathAbnMs = millis();
} else if (millis() - g_breathAbnMs >= VITAL_DETECT_MS) {
g_localBreathAbnActive = true;
char buf[32];
snprintf(buf, sizeof(buf), "呼吸异常: %d 次/分", radar.breathRate);
g_alarm.triggerLocal(AlarmManager::ALARM_BREATH_ABNORMAL, buf);
}
}
g_breathNormalMs = 0; // 仍异常, 重置正常计时
} else {
g_breathAbnCnt = 0;
g_breathDismissed = false;
// 持续正常: 累积时长, 满 VITAL_CLEAR_MS 清除 + 重新武装
g_breathAbnMs = 0; // 正常了, 重置异常计时
if (g_breathNormalMs == 0) {
g_breathNormalMs = millis();
}
if (millis() - g_breathNormalMs >= VITAL_CLEAR_MS) {
if (g_localBreathAbnActive) {
g_localBreathAbnActive = false;
g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL);
}
if (g_breathDismissed) {
g_breathDismissed = false; // 持续正常后重新武装
}
}
}
} else if (!humanPresent && g_localBreathAbnActive) {
g_localBreathAbnActive = false;
g_breathAbnCnt = 0;
g_breathAbnMs = 0;
g_breathNormalMs = 0;
g_breathDismissed = false;
g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL);
}
@@ -551,8 +587,10 @@ void setup() {
g_localDhtFaultActive = false;
g_tempAbnCnt = 0;
g_humiAbnCnt = 0;
g_heartAbnCnt = 0;
g_breathAbnCnt = 0;
g_heartAbnMs = 0;
g_heartNormalMs = 0;
g_breathAbnMs = 0;
g_breathNormalMs = 0;
g_radarTimeoutCnt = 0;
g_fallClearMs = 0;
g_fallDismissed = true; // 抑制重复报警, 等跌倒信号消了再恢复