diff --git a/README.md b/README.md index 57c2b9d..aebe2b6 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,23 @@ GPIO22 读人体红外(PIR)模块 OUT:每次检测到运动开始,屏幕 | 模块 | CYD | |------|-----| -| VCC | **3.3V**(部分模块标 5V 时用 **5V**,以模块说明为准) | +| VCC | 优先 **5V**(HC-SR501 等大模块);仅明确标 3.3V 的小模块用 **3.3V** | | GND | **GND** | | OUT / S / DO | **GPIO22** | -开机自动采空闲电平,反相视为有人(兼容「有人变高」或「有人变低」)。 +引脚用浮空 `INPUT`(无内部上/下拉)。默认空闲 LOW、有人 HIGH;开机若采样明显偏 HIGH 则自动反相。 屏上: - `MOTION` / `IDLE`:当前是否感应到人 - `hold` + 进度条:本次连续有人时长(约 0~5s 满格) -- `OUT HIGH/LOW` 与 `act=`:原始电平与有效电平 +- `OUT HIGH/LOW` 与 `act=`:原始电平与有效电平 —— **挥手时 OUT 应变,不变就是供电/接线问题** -上电校准的几秒内请勿在感应区活动,否则空闲电平会采错。 +注意: + +- 多数 PIR 上电后需 **约 30~60 秒** 预热才稳定 +- 确认 OUT 接到 **GPIO22**(不是 21 背光),共地 +- 模块有灵敏度/延时电位器时,灵敏度先拧到最大 ## 操作 diff --git a/firmware/cyd/VERSION.txt b/firmware/cyd/VERSION.txt index 76f6bb4..2076979 100644 --- a/firmware/cyd/VERSION.txt +++ b/firmware/cyd/VERSION.txt @@ -1,5 +1,5 @@ name: CYD Human IR / PIR (cyd) -git: bab93d0 +git: a7854de date: 2026-10-23 board: ESP32-2432S028R (ILI9341) features: SoftSPI touch, LVGL, PIR OUT on GPIO22 motion count+1 @@ -12,5 +12,5 @@ offsets: sha256: bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8 boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0 - firmware.bin 67228A24CE3DBED1C9CBA1AD811DB016AE7F9D12470E0DAD8E329004DC593F7B + firmware.bin CA8FBB88050BC2284EFDDBF3ECC711A6539D4F3829994017812A30C0E2E6B057 partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1 diff --git a/firmware/cyd/firmware.bin b/firmware/cyd/firmware.bin index 3862442..7a625e1 100644 Binary files a/firmware/cyd/firmware.bin and b/firmware/cyd/firmware.bin differ diff --git a/src/pir.cpp b/src/pir.cpp index 22d7eef..2f8c4ec 100644 --- a/src/pir.cpp +++ b/src/pir.cpp @@ -4,8 +4,8 @@ #include // 人体红外(PIR)模块:VCC / GND / OUT→GPIO22 -// 开机采空闲电平,反相视为有人;上升沿计 1 次 -// 积分滤波:压启动抖沿;松手侧迟滞防闪烁 +// 浮空 INPUT(不上/下拉),避免与模块开漏/弱推挽打架 +// 默认按「空闲 LOW、有人 HIGH」;开机采样仅在明显偏 HIGH 时反相 static uint32_t g_count = 0; static bool g_stable_active = false; @@ -14,12 +14,14 @@ static int g_idle_level = LOW; static int8_t g_score = 0; static uint32_t g_lock_until_ms = 0; static uint32_t g_active_since_ms = 0; +static int g_last_logged_raw = -1; +static uint32_t g_last_hb_ms = 0; -static constexpr int8_t SCORE_MAX = 6; -static constexpr int8_t ON_TH = 3; -static constexpr int8_t OFF_TH = -3; -// PIR 输出常保持数秒;边沿后再忽略短暂抖动,避免同一次感应连计 -static constexpr uint32_t LOCKOUT_MS = 250; +static constexpr int8_t SCORE_MAX = 4; +static constexpr int8_t ON_TH = 2; +static constexpr int8_t OFF_TH = -2; +static constexpr uint32_t LOCKOUT_MS = 200; +static constexpr uint32_t HEARTBEAT_MS = 2000; static bool raw_is_active(int raw) { return raw == g_active_level; } @@ -29,30 +31,31 @@ static int read_majority() { if (digitalRead(PIR_PIN) == HIGH) { high_n++; } - delayMicroseconds(50); + delayMicroseconds(40); } return (high_n >= 3) ? HIGH : LOW; } void pir_init() { + // 与触控模块一样:浮空 INPUT,不要内部上/下拉 pinMode(PIR_PIN, INPUT); - delay(30); + delay(50); int high_n = 0; - for (int i = 0; i < 40; i++) { + for (int i = 0; i < 50; i++) { if (digitalRead(PIR_PIN) == HIGH) { high_n++; } delay(2); } - g_idle_level = (high_n >= 20) ? HIGH : LOW; - g_active_level = (g_idle_level == HIGH) ? LOW : HIGH; - // 推挽 OUT 也可;弱拉向空闲侧减轻悬空噪声 - if (g_idle_level == HIGH) { - pinMode(PIR_PIN, INPUT_PULLUP); + // 多数 PIR:空闲 LOW。仅当开机采样明显偏 HIGH(如反相模块)才反相 + if (high_n >= 40) { + g_idle_level = HIGH; + g_active_level = LOW; } else { - pinMode(PIR_PIN, INPUT_PULLDOWN); + g_idle_level = LOW; + g_active_level = HIGH; } g_stable_active = false; @@ -60,15 +63,32 @@ void pir_init() { g_lock_until_ms = 0; g_active_since_ms = 0; g_count = 0; + g_last_logged_raw = -1; + g_last_hb_ms = 0; - Serial.printf("PIR GPIO%d idle=%s active=%s pull=%s\n", PIR_PIN, - g_idle_level == HIGH ? "HIGH" : "LOW", - g_active_level == HIGH ? "HIGH" : "LOW", - g_idle_level == HIGH ? "UP" : "DOWN"); + Serial.printf( + "PIR GPIO%d float INPUT idle=%s active=%s (high_n=%d/50)\n", PIR_PIN, + g_idle_level == HIGH ? "HIGH" : "LOW", + g_active_level == HIGH ? "HIGH" : "LOW", high_n); + Serial.println( + "PIR tip: many modules need 5V VCC; warm-up ~30s; watch OUT on screen"); } bool pir_poll_detect() { const int raw = read_majority(); + const uint32_t now = millis(); + + if (raw != g_last_logged_raw) { + g_last_logged_raw = raw; + Serial.printf("PIR raw -> %s @%lums\n", raw ? "HIGH" : "LOW", + (unsigned long)now); + } + if (now - g_last_hb_ms >= HEARTBEAT_MS) { + g_last_hb_ms = now; + Serial.printf("PIR hb raw=%s active=%d count=%lu\n", raw ? "HIGH" : "LOW", + (int)g_stable_active, (unsigned long)g_count); + } + if (raw_is_active(raw)) { if (g_score < SCORE_MAX) { g_score++; @@ -77,8 +97,6 @@ bool pir_poll_detect() { g_score--; } - const uint32_t now = millis(); - if (!g_stable_active && g_score >= ON_TH) { g_stable_active = true; g_active_since_ms = now;