Tune button feel: faster majority vote, idle pull, short lockout.
Snappier press detection without long-hold; reduces bounce chatter. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: CYD Button (cyd)
|
||||
git: 280c5ea
|
||||
git: 7459f9b
|
||||
date: 2026-10-23
|
||||
board: ESP32-2432S028R (ILI9341)
|
||||
features: SoftSPI touch, LVGL, 3-pin button OUT on GPIO22 count+1
|
||||
@@ -12,5 +12,5 @@ offsets:
|
||||
sha256:
|
||||
bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8
|
||||
boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0
|
||||
firmware.bin BFCAD59431009CF5930B228CA7D6E3DE24C5FD2587690D131F770070EC8C604D
|
||||
firmware.bin CE4D141B462731BC137E5793F055A5116A81F680DCA51D0F6A4E26F73E701F86
|
||||
partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1
|
||||
|
||||
Binary file not shown.
@@ -3,70 +3,89 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// 三脚按键模块:VCC→3.3V,GND→GND,OUT/S→GPIO22
|
||||
// 开机采样空闲电平,反相即为“按下”(兼容按下拉高 / 按下拉低两种模块)
|
||||
// 三脚按键模块:VCC→3.3V,GND→GND,OUT→GPIO22
|
||||
// 短积分 + 多数表决:轻触更快;松开锁存防连跳
|
||||
|
||||
static uint32_t g_count = 0;
|
||||
static bool g_stable_down = false;
|
||||
static int g_stable_raw = LOW;
|
||||
static int g_active_level = HIGH; // 按下时期望电平
|
||||
static uint32_t g_change_ms = 0;
|
||||
static int g_pending_raw = LOW;
|
||||
static bool g_pending = false;
|
||||
static constexpr uint32_t DEBOUNCE_MS = 30;
|
||||
static int g_active_level = HIGH;
|
||||
static int g_idle_level = LOW;
|
||||
static int8_t g_score = 0;
|
||||
static uint32_t g_lock_until_ms = 0;
|
||||
|
||||
static constexpr int8_t SCORE_MAX = 4;
|
||||
static constexpr int8_t DOWN_TH = 2; // 约 2~3 次有效采样即算按下
|
||||
static constexpr int8_t UP_TH = -2;
|
||||
static constexpr uint32_t LOCKOUT_MS = 70; // 一次有效按下后忽略连跳
|
||||
|
||||
static bool raw_is_down(int raw) { return raw == g_active_level; }
|
||||
|
||||
static int read_majority() {
|
||||
int high_n = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (digitalRead(BTN_PIN) == HIGH) {
|
||||
high_n++;
|
||||
}
|
||||
delayMicroseconds(40);
|
||||
}
|
||||
return (high_n >= 2) ? HIGH : LOW;
|
||||
}
|
||||
|
||||
void button_init() {
|
||||
// 模块自带上下拉,不要用内部上拉去顶它
|
||||
pinMode(BTN_PIN, INPUT);
|
||||
delay(30);
|
||||
delay(20);
|
||||
|
||||
int high_n = 0;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
if (digitalRead(BTN_PIN) == HIGH) {
|
||||
high_n++;
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
const int idle = (high_n >= 10) ? HIGH : LOW;
|
||||
g_active_level = (idle == HIGH) ? LOW : HIGH;
|
||||
g_stable_raw = idle;
|
||||
g_idle_level = (high_n >= 15) ? HIGH : LOW;
|
||||
g_active_level = (g_idle_level == HIGH) ? LOW : HIGH;
|
||||
|
||||
// 内部弱拉向空闲侧,压噪声、减轻“半按不稳”
|
||||
if (g_idle_level == HIGH) {
|
||||
pinMode(BTN_PIN, INPUT_PULLUP);
|
||||
} else {
|
||||
pinMode(BTN_PIN, INPUT_PULLDOWN);
|
||||
}
|
||||
|
||||
g_stable_down = false;
|
||||
g_pending = false;
|
||||
g_pending_raw = idle;
|
||||
g_change_ms = millis();
|
||||
g_score = -SCORE_MAX;
|
||||
g_lock_until_ms = 0;
|
||||
g_count = 0;
|
||||
|
||||
Serial.printf(
|
||||
"Button module GPIO%d INPUT idle=%s active=%s (VCC/GND/OUT)\n", BTN_PIN,
|
||||
idle == HIGH ? "HIGH" : "LOW", g_active_level == HIGH ? "HIGH" : "LOW");
|
||||
Serial.printf("Button GPIO%d idle=%s active=%s pull=%s\n", BTN_PIN,
|
||||
g_idle_level == HIGH ? "HIGH" : "LOW",
|
||||
g_active_level == HIGH ? "HIGH" : "LOW",
|
||||
g_idle_level == HIGH ? "UP" : "DOWN");
|
||||
}
|
||||
|
||||
bool button_poll_press() {
|
||||
const int raw = digitalRead(BTN_PIN);
|
||||
const int raw = read_majority();
|
||||
if (raw_is_down(raw)) {
|
||||
if (g_score < SCORE_MAX) {
|
||||
g_score++;
|
||||
}
|
||||
} else if (g_score > -SCORE_MAX) {
|
||||
g_score--;
|
||||
}
|
||||
|
||||
const uint32_t now = millis();
|
||||
|
||||
if (raw != g_stable_raw) {
|
||||
if (!g_pending || raw != g_pending_raw) {
|
||||
g_pending = true;
|
||||
g_pending_raw = raw;
|
||||
g_change_ms = now;
|
||||
} else if ((now - g_change_ms) >= DEBOUNCE_MS) {
|
||||
g_stable_raw = g_pending_raw;
|
||||
g_pending = false;
|
||||
const bool down = raw_is_down(g_stable_raw);
|
||||
if (down && !g_stable_down) {
|
||||
g_stable_down = true;
|
||||
g_count++;
|
||||
Serial.printf("Button press count=%lu raw=%s\n", (unsigned long)g_count,
|
||||
g_stable_raw == HIGH ? "HIGH" : "LOW");
|
||||
return true;
|
||||
}
|
||||
g_stable_down = down;
|
||||
if (!g_stable_down && g_score >= DOWN_TH) {
|
||||
g_stable_down = true;
|
||||
if (now >= g_lock_until_ms) {
|
||||
g_count++;
|
||||
g_lock_until_ms = now + LOCKOUT_MS;
|
||||
Serial.printf("Button press count=%lu score=%d\n", (unsigned long)g_count,
|
||||
(int)g_score);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
g_pending = false;
|
||||
} else if (g_stable_down && g_score <= UP_TH) {
|
||||
g_stable_down = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
13
src/main.cpp
13
src/main.cpp
@@ -39,7 +39,14 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
const bool pressed = button_poll_press();
|
||||
// 每圈多采几次,轻触更快跟上
|
||||
bool pressed = false;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (button_poll_press()) {
|
||||
pressed = true;
|
||||
}
|
||||
delayMicroseconds(200);
|
||||
}
|
||||
|
||||
static bool last_down = false;
|
||||
static int last_raw = -1;
|
||||
@@ -52,6 +59,6 @@ void loop() {
|
||||
}
|
||||
|
||||
lv_timer_handler();
|
||||
lv_tick_inc(5);
|
||||
delay(5);
|
||||
lv_tick_inc(4);
|
||||
delay(4);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user