ESP32超声波传感器系统按键控制问题求助:双击关机/单击开机
ESP32传感器系统问题修复
原代码核心问题
- 赋值/比较运算符混淆:所有
if (变量 = 值)的写法都是错误的,这是赋值操作而非逻辑判断,应该用==。这是导致系统状态无法正确切换的根本原因。 - 按键逻辑混乱:没有正确实现“开机状态下1-2秒内按两次关机”的逻辑,计时变量未正确初始化,脉冲计数逻辑错误,且使用
delay阻塞程序导致按键响应不及时。 - 引脚模式重复设置:在
loop中反复调用pinMode,属于冗余操作,应该一次性在setup中完成。 - LED闪烁阻塞程序:使用
delay(5)实现红灯闪烁会阻塞整个系统,导致按键和传感器检测无法正常工作,需改用非阻塞方式。 - 时间阈值错误:注释标注1秒内按两次,但代码写的是
4000毫秒(4秒),与需求不符。 - 缺少按键消抖:未处理按键机械抖动,容易导致误触发。
修正后的代码
#include <Arduino.h> #define trigger 27 #define echo 14 #define ledrojo 4 #define ledverde 5 #define BOTON 13 float distancia = 0; unsigned long ta = 0; unsigned long lastPressTime = 0; // 记录上次按键时间 int pressCount = 0; // 按键计数 int sistemaEstado = 0; // 0=关闭,1=开启 unsigned long lastBlinkTime = 0; // 红灯闪烁计时 const long BLINK_INTERVAL = 500; // 红灯闪烁间隔(毫秒) void setup() { Serial.begin(9600); // 初始化所有引脚模式 pinMode(BOTON, INPUT_PULLUP); pinMode(trigger, OUTPUT); pinMode(echo, INPUT); pinMode(ledrojo, OUTPUT); pinMode(ledverde, OUTPUT); // 系统初始状态:关闭,LED全灭 digitalWrite(ledrojo, LOW); digitalWrite(ledverde, LOW); sistemaEstado = 0; } void loop() { // 处理按键逻辑 handleButton(); // 根据系统状态执行对应操作 if (sistemaEstado == 1) { // 传感器检测 measureDistance(); // 控制LED controlLEDs(); } else { // 系统关闭时,关闭所有输出 digitalWrite(ledrojo, LOW); digitalWrite(ledverde, LOW); digitalWrite(trigger, LOW); } } // 处理按键逻辑:开机按一次,关机1-2秒内按两次 void handleButton() { static unsigned long lastDebounceTime = 0; const unsigned long DEBOUNCE_DELAY = 50; // 消抖延时 int buttonState = digitalRead(BOTON); // 按键消抖:检测到按键按下(INPUT_PULLUP,低电平为按下) if (buttonState == LOW && (millis() - lastDebounceTime) > DEBOUNCE_DELAY) { lastDebounceTime = millis(); if (sistemaEstado == 0) { // 系统关闭,按一次开机 sistemaEstado = 1; Serial.println("系统已开启"); pressCount = 0; } else { // 系统开启,计数按键次数 pressCount++; if (pressCount == 1) { // 记录第一次按键时间 lastPressTime = millis(); } else if (pressCount == 2) { // 检测两次按键间隔是否在1-2秒内 if (millis() - lastPressTime >= 1000 && millis() - lastPressTime <= 2000) { sistemaEstado = 0; Serial.println("系统已关闭"); } // 重置计数,避免多次触发 pressCount = 0; } } } // 如果超过2秒未按第二次,重置计数 if (sistemaEstado == 1 && pressCount == 1 && (millis() - lastPressTime) > 2000) { pressCount = 0; } } // 超声波传感器测距 void measureDistance() { digitalWrite(trigger, HIGH); delayMicroseconds(10); digitalWrite(trigger, LOW); ta = pulseIn(echo, HIGH); if (ta == 0) { // 超时处理,默认设为远距 distancia = 100; return; } ta = ta / 2; distancia = ta / 29.1; // 修正系数,提高测距准确性 } // 控制LED状态 void controlLEDs() { if (distancia <= 30) { // 红灯闪烁(非阻塞) if (millis() - lastBlinkTime >= BLINK_INTERVAL) { lastBlinkTime = millis(); digitalWrite(ledrojo, !digitalRead(ledrojo)); } digitalWrite(ledverde, LOW); Serial.println("¡PELIGRO, RETROCEDA!"); } else { // 绿灯常亮,红灯熄灭 digitalWrite(ledverde, HIGH); digitalWrite(ledrojo, LOW); } }
关键修改说明
- 修复运算符错误:将所有赋值
=替换为比较==,确保逻辑判断正确。 - 重构按键逻辑:用
millis()实现非阻塞计时,加入消抖处理,准确实现“开机按一次,关机1-2秒内按两次”的需求,避免阻塞程序。 - 引脚初始化移至setup:所有
pinMode调用放在setup中,避免loop中重复执行的冗余操作。 - 非阻塞LED闪烁:用
millis()替代delay实现红灯闪烁,确保系统其他功能(按键、传感器)能正常响应。 - 传感器优化:加入
pulseIn超时判断,避免传感器无信号时程序阻塞,修正距离计算系数提高准确性。 - 状态变量命名优化:将
estadosistema改为sistemaEstado,变量名更清晰易读。
内容的提问来源于stack exchange,提问作者28nodbot
相关产品推荐
相关产品推荐

