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

Arduino中if语句仅触发一次问题及无delay时序实现求助

解决Arduino流水灯只能触发一次及非阻塞定时问题

问题分析

你的代码存在两个核心问题:

  1. delay()阻塞程序:执行TEST()期间,程序会被完全卡住,无法实时检测A0引脚的状态变化,也无法响应新的触发信号。
  2. 无状态重置机制:TEST()仅依次点亮LED但未清除原有状态,再次触发时,之前点亮的LED仍保持亮态,导致视觉上没有变化;同时没有记录流水灯运行进度,无法实现每次触发都从头执行。

修正后的代码

#include <FastLED.h>

#define LED_PIN     7
#define NUM_LEDS    20
#define STEP_DELAY  500  // 每个LED切换的间隔时间(毫秒)

CRGB leds[NUM_LEDS];

// 流水灯状态变量
int currentLedIndex = 0;          // 当前要点亮的LED索引
unsigned long lastUpdateMillis = 0;  // 上次更新LED的时间戳
bool isAnimationRunning = false;  // 标记动画是否正在运行

void setup() {
    pinMode(A0, INPUT_PULLUP);
    FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
    FastLED.clear();  // 初始化所有LED为熄灭状态
    FastLED.show();
}

void loop() {
    bool triggerSignal = (digitalRead(A0) == HIGH);
    
    // 触发动画:仅当未运行时启动,重置状态
    if (triggerSignal && !isAnimationRunning) {
        currentLedIndex = 0;
        isAnimationRunning = true;
        lastUpdateMillis = millis();
        FastLED.clear();
        FastLED.show();
    }
    // 停止触发:立即终止动画并熄灭所有LED
    else if (!triggerSignal && isAnimationRunning) {
        isAnimationRunning = false;
        FastLED.clear();
        FastLED.show();
    }
    
    // 非阻塞执行流水灯动画
    if (isAnimationRunning) {
        unsigned long currentMillis = millis();
        if (currentMillis - lastUpdateMillis >= STEP_DELAY) {
            lastUpdateMillis = currentMillis;
            
            // 定义流水灯颜色序列
            CRGB colorSequence[] = {
                CRGB(255, 0, 0),
                CRGB(0, 255, 0),
                CRGB(0, 0, 255),
                CRGB(150, 0, 255),
                CRGB(255, 200, 20),
                CRGB(85, 60, 180),
                CRGB(50, 255, 20)
            };
            int sequenceLength = sizeof(colorSequence) / sizeof(CRGB);
            
            // 切换LED状态(如果需要保留之前的LED点亮,注释掉FastLED.clear())
            FastLED.clear();
            leds[currentLedIndex] = colorSequence[currentLedIndex];
            FastLED.show();
            
            // 推进到下一个LED,到达末尾后停止(或循环)
            currentLedIndex++;
            if (currentLedIndex >= sequenceLength) {
                isAnimationRunning = false;
                // 如果需要循环播放,替换为 currentLedIndex = 0;
            }
        }
    }
}

核心改进点

  1. 非阻塞定时:用millis()记录时间戳,通过时间差判断是否执行下一步,替代delay(),确保程序始终能响应引脚状态变化。
  2. 状态管理:通过isAnimationRunning和currentLedIndex控制动画的启动、停止和进度,每次触发都从头开始执行。
  3. 灵活的动画逻辑:
    • 注释掉FastLED.clear()即可实现"依次点亮不熄灭"的效果;
    • 将末尾的isAnimationRunning = false改为currentLedIndex = 0,可实现循环播放流水灯。
  4. 实时触发响应:在loop()中持续检测A0引脚,触发时立即启动动画,停止触发时立即终止并熄灭LED,符合汽车尾灯的交互需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:48:22