You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于计数器与定时需求的LED切换功能开发求助

按键控制LED定时切换解决方案

需求说明

  • 两个按键分别控制计数器递增/递减,计数器范围为1-5,对应5个LED
  • 计数器值为N时,点亮第N个LED(对应ledOnTime数组索引N-1的时长),其余LED立即熄灭
  • 若LED点亮时长未结束时切换计数器,立即关闭当前LED,启动新LED的定时
  • LED达到指定时长后自动熄灭

修改后完整代码

//Buttons//
const uint8_t MIN_COUNT = 1;
const uint8_t MAX_COUNT = 5;

//Button1: count up
const uint8_t btnUpPin = 2;
//Button2: count down
const uint8_t btnDownPin = 3;

uint8_t currentCount = MIN_COUNT; // 统一计数器,初始为1
unsigned long lastBtnUpTime = 0;
unsigned long lastBtnDownTime = 0;
const uint8_t DEBOUNCE_DELAY = 35;
const uint8_t SHORT_PRESS_THRESHOLD = 500;

////Leds/////
const int ledPins[] = {4,5,6,7,8}; // LED引脚数组
const int numOfLeds = sizeof(ledPins) / sizeof(ledPins[0]);

// LED点亮时长(毫秒)
const unsigned long ledOnTime[] = {19*1000, 44*1000, 9*1000, 7*1000, 33*1000};

// LED控制变量
int currentActiveLed = -1; // 当前激活的LED索引,-1表示无LED点亮
unsigned long ledStartMillis = 0; // LED点亮的起始时间

void setup() {
  Serial.begin(115200);
  
  pinMode(btnUpPin, INPUT_PULLUP);
  pinMode(btnDownPin, INPUT_PULLUP);
  
  // 初始化LED引脚为输出
  for (int j = 0; j < numOfLeds; j++) {
    pinMode(ledPins[j], OUTPUT);
    digitalWrite(ledPins[j], LOW); // 初始全灭
  }
}

void loop() {
  handleBtnUp();
  handleBtnDown();
  handleLedControl();
}

// 处理递增按键
void handleBtnUp() {
  unsigned long currentMillis = millis();
  uint8_t btnState = digitalRead(btnUpPin);
  
  if (btnState == LOW) {
    if (currentMillis - lastBtnUpTime > DEBOUNCE_DELAY) {
      lastBtnUpTime = currentMillis;
      static unsigned long pressStart = 0;
      pressStart = currentMillis;
      
      // 等待按键释放
      while (digitalRead(btnUpPin) == LOW) {
        // 空循环等待释放,避免重复触发
      }
      
      unsigned long pressDuration = currentMillis - pressStart;
      if (pressDuration < SHORT_PRESS_THRESHOLD) {
        currentCount++;
        if (currentCount > MAX_COUNT) {
          currentCount = MIN_COUNT;
        }
        Serial.print("当前计数: ");
        Serial.println(currentCount);
      }
    }
  }
}

// 处理递减按键
void handleBtnDown() {
  unsigned long currentMillis = millis();
  uint8_t btnState = digitalRead(btnDownPin);
  
  if (btnState == LOW) {
    if (currentMillis - lastBtnDownTime > DEBOUNCE_DELAY) {
      lastBtnDownTime = currentMillis;
      static unsigned long pressStart = 0;
      pressStart = currentMillis;
      
      // 等待按键释放
      while (digitalRead(btnDownPin) == LOW) {
        // 空循环等待释放
      }
      
      unsigned long pressDuration = currentMillis - pressStart;
      if (pressDuration < SHORT_PRESS_THRESHOLD) {
        currentCount--;
        if (currentCount < MIN_COUNT) {
          currentCount = MAX_COUNT;
        }
        Serial.print("当前计数: ");
        Serial.println(currentCount);
      }
    }
  }
}

// 处理LED控制逻辑
void handleLedControl() {
  unsigned long currentMillis = millis();
  int targetLedIndex = currentCount - 1; // 计数转LED索引(1→0,2→1...)
  
  // 情况1:计数器变化,需要切换LED
  if (targetLedIndex != currentActiveLed) {
    // 关闭之前的LED
    if (currentActiveLed != -1) {
      digitalWrite(ledPins[currentActiveLed], LOW);
    }
    // 启动新LED
    currentActiveLed = targetLedIndex;
    ledStartMillis = currentMillis;
    digitalWrite(ledPins[currentActiveLed], HIGH);
    Serial.print("点亮LED");
    Serial.println(currentCount);
  }
  
  // 情况2:当前LED已达到点亮时长,自动熄灭
  if (currentActiveLed != -1) {
    if (currentMillis - ledStartMillis >= ledOnTime[currentActiveLed]) {
      digitalWrite(ledPins[currentActiveLed], LOW);
      currentActiveLed = -1;
      Serial.print("LED");
      Serial.print(currentCount);
      Serial.println("已自动熄灭");
    }
  }
}

关键修改说明

  • 统一计数器变量:将原来分散的计数变量合并为currentCount,简化逻辑避免变量混乱
  • 优化按键防抖:基于millis实现非阻塞防抖,等待按键释放后判断按压时长,避免误触发
  • LED状态跟踪:用currentActiveLed记录当前点亮的LED索引,ledStartMillis记录点亮起始时间,精准控制定时
  • 核心控制逻辑:
    • 计数器变化时,立即关闭旧LED并启动新LED,重置定时
    • 持续检查当前LED的点亮时长,达到设定值后自动熄灭
  • 移除风险宏定义:去掉原有的sec/min宏(易引发运算错误),直接用*1000转换秒为毫秒

内容的提问来源于stack exchange,提问作者lon_ly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:01:34