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

Arduino Uno多定时器控制求助:初始警报功能无法实现

Arduino Uno 非阻塞多任务实现方案

核心思路

用millis()实现非阻塞计时,通过状态机区分三个执行阶段:

  • 阶段0:设备启动后等待6分钟,不触发警报
  • 阶段1:首次触发1分钟警报(仅执行一次)
  • 阶段2-3:循环切换警报开关(1分钟关、1分钟开)
    全程保持LED独立闪烁,互不阻塞。

完整代码

// 引脚定义
const int ledPin = 2;
const int buzzerPin = 9;

// 计时变量
unsigned long ledPreviousMillis = 0;
unsigned long buzzerPreviousMillis = 0;

// 时间间隔定义(毫秒)
const unsigned long LED_INTERVAL = 500; // LED闪烁间隔,可自行调整
const unsigned long WAIT_FIRST_ALERT = 6 * 60 * 1000; // 初始等待6分钟
const unsigned long ALERT_DURATION = 60 * 1000; // 警报持续/关闭时长1分钟

// 状态机阶段:0=等待首次警报,1=首次警报中,2=循环关闭中,3=循环开启中
int buzzerStage = 0;
bool ledState = LOW;
bool buzzerState = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  // 第一部分:LED持续闪烁(不受任何状态影响)
  unsigned long currentMillis = millis();
  if (currentMillis - ledPreviousMillis >= LED_INTERVAL) {
    ledPreviousMillis = currentMillis;
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
  }

  // 第二部分:警报状态机逻辑
  switch(buzzerStage) {
    case 0: // 等待6分钟触发首次警报
      if (currentMillis >= WAIT_FIRST_ALERT) {
        buzzerState = HIGH;
        digitalWrite(buzzerPin, buzzerState);
        buzzerPreviousMillis = currentMillis;
        buzzerStage = 1;
      }
      break;

    case 1: // 首次警报持续1分钟
      if (currentMillis - buzzerPreviousMillis >= ALERT_DURATION) {
        buzzerState = LOW;
        digitalWrite(buzzerPin, buzzerState);
        buzzerPreviousMillis = currentMillis;
        buzzerStage = 2;
      }
      break;

    case 2: // 循环阶段:警报关闭1分钟
      if (currentMillis - buzzerPreviousMillis >= ALERT_DURATION) {
        buzzerState = HIGH;
        digitalWrite(buzzerPin, buzzerState);
        buzzerPreviousMillis = currentMillis;
        buzzerStage = 3;
      }
      break;

    case 3: // 循环阶段:警报开启1分钟
      if (currentMillis - buzzerPreviousMillis >= ALERT_DURATION) {
        buzzerState = LOW;
        digitalWrite(buzzerPin, buzzerState);
        buzzerPreviousMillis = currentMillis;
        buzzerStage = 2;
      }
      break;
  }
}

代码说明

  1. 非阻塞计时:用millis()记录当前时间,通过时间差判断触发条件,完全替代delay(),避免阻塞LED闪烁。
  2. 状态机设计:通过buzzerStage变量明确当前执行阶段,每个阶段只处理对应逻辑,避免逻辑混乱。
  3. LED独立运行:LED闪烁逻辑放在最前端,无论警报处于哪个阶段,都会持续执行,保证全程闪烁。
  4. 变量复用:buzzerPreviousMillis在每个阶段切换时更新,统一记录当前阶段的起始时间,减少冗余变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:57:22