WS2812流水灯(转向灯)上电模式

WS2812流水灯(转向灯)上电模式实现

WS2812流水灯(转向灯)上电模式实现方案,模拟汽车转向灯效果,包含多种模式切换功能。

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif

#define LED_PIN     6
#define LED_COUNT  16
#define BUTTON_LEFT 2
#define BUTTON_RIGHT 3
#define BUTTON_HAZARD 4
#define BRIGHTNESS 50

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// 转向灯模式枚举
enum TurnSignalMode {
  OFF,
  LEFT_SIGNAL,
  RIGHT_SIGNAL,
  HAZARD_LIGHTS
};

TurnSignalMode currentMode = OFF;
unsigned long previousMillis = 0;
const long interval = 300;  // 闪烁间隔(毫秒)
bool ledState = false;      // LED状态
int animationPosition = 0;  // 动画位置

void setup() {
  pinMode(BUTTON_LEFT, INPUT_PULLUP);
  pinMode(BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(BUTTON_HAZARD, INPUT_PULLUP);
  
  strip.begin();
  strip.show(); // 初始化所有LED为关闭状态
  strip.setBrightness(BRIGHTNESS);
  
  // 上电自检动画
  powerOnSelfTest();
  
  Serial.begin(9600);
  Serial.println("WS2812 Turn Signal System Ready");
}

void loop() {
  // 检测按钮输入
  checkButtons();
  
  // 根据当前模式执行相应动画
  unsigned long currentMillis = millis();
  
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    
    switch(currentMode) {
      case OFF:
        allOff();
        break;
      case LEFT_SIGNAL:
        leftSignalAnimation();
        break;
      case RIGHT_SIGNAL:
        rightSignalAnimation();
        break;
      case HAZARD_LIGHTS:
        hazardLightsAnimation();
        break;
    }
    
    ledState = !ledState; // 切换LED状态
    strip.show();
  }
}

// 上电自检动画
void powerOnSelfTest() {
  // 全部LED渐亮为白色
  for (int b = 0; b <= BRIGHTNESS; b++) {
    strip.setBrightness(b);
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(100, 100, 100));
    }
    strip.show();
    delay(20);
  }
  
  delay(300);
  
  // 红色流水效果(从左到右)
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(150, 0, 0));
    strip.show();
    delay(50);
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  
  // 绿色流水效果(从右到左)
  for (int i = strip.numPixels()-1; i >= 0; i--) {
    strip.setPixelColor(i, strip.Color(0, 150, 0));
    strip.show();
    delay(50);
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  
  // 黄色流水效果(从中间向两边)
  int center = strip.numPixels() / 2;
  for (int i = 0; i <= center; i++) {
    if (center - i >= 0) {
      strip.setPixelColor(center - i, strip.Color(150, 150, 0));
    }
    if (center + i < strip.numPixels()) {
      strip.setPixelColor(center + i, strip.Color(150, 150, 0));
    }
    strip.show();
    delay(70);
  }
  
  // 全部渐灭
  for (int b = BRIGHTNESS; b >= 0; b--) {
    strip.setBrightness(b);
    strip.show();
    delay(15);
  }
  
  // 重置亮度
  strip.setBrightness(BRIGHTNESS);
  allOff();
}

// 左转向灯动画
void leftSignalAnimation() {
  allOff();
  
  // 流水效果
  if (ledState) {
    for (int i = 0; i < 8; i++) { // 左半部分LED
      int pos = (animationPosition + i) % 8;
      strip.setPixelColor(pos, strip.Color(255, 100, 0)); // 琥珀色
    }
    animationPosition = (animationPosition + 1) % 8;
  }
}

// 右转向灯动画
void rightSignalAnimation() {
  allOff();
  
  // 流水效果
  if (ledState) {
    for (int i = 0; i < 8; i++) { // 右半部分LED
      int pos = LED_COUNT - 1 - ((animationPosition + i) % 8);
      strip.setPixelColor(pos, strip.Color(255, 100, 0)); // 琥珀色
    }
    animationPosition = (animationPosition + 1) % 8;
  }
}

// 双闪灯动画
void hazardLightsAnimation() {
  allOff();
  
  if (ledState) {
    // 全部琥珀色LED亮起
    for (int i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(255, 100, 0));
    }
  }
}

// 关闭所有LED
void allOff() {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
}

// 检测按钮输入
void checkButtons() {
  if (digitalRead(BUTTON_LEFT) == LOW) {
    if (currentMode != LEFT_SIGNAL) {
      currentMode = LEFT_SIGNAL;
      animationPosition = 0;
      Serial.println("Left turn signal activated");
      delay(300); // 防抖延时
    }
  }
  
  if (digitalRead(BUTTON_RIGHT) == LOW) {
    if (currentMode != RIGHT_SIGNAL) {
      currentMode = RIGHT_SIGNAL;
      animationPosition = 0;
      Serial.println("Right turn signal activated");
      delay(300); // 防抖延时
    }
  }
  
  if (digitalRead(BUTTON_HAZARD) == LOW) {
    if (currentMode != HAZARD_LIGHTS) {
      currentMode = HAZARD_LIGHTS;
      Serial.println("Hazard lights activated");
      delay(300); // 防抖延时
    }
  }
}

说明

1. 上电自检动画

  • 渐亮效果:所有LED从暗到亮渐变为白色
  • 流水测试
    • 红色LED从左向右流动
    • 绿色LED从右向左流动
    • 黄色LED从中间向两边扩散
  • 渐灭效果:所有LED逐渐熄灭

2. 转向灯模式

  • 左转向灯:LED从左侧开始流动(琥珀色)
  • 右转向灯:LED从右侧开始流动(琥珀色)
  • 双闪灯:所有LED同步闪烁(琥珀色)

3. 控制方式

  • 三个按钮分别控制:
    • 左转向灯
    • 右转向灯
    • 双闪灯

4. 参数配置

#define LED_PIN     6      // WS2812数据引脚
#define LED_COUNT  16      // LED数量
#define BUTTON_LEFT 2      // 左转向按钮引脚
#define BUTTON_RIGHT 3     // 右转向按钮引脚
#define BUTTON_HAZARD 4   // 双闪按钮引脚
#define BRIGHTNESS 50     // LED亮度(0-255)

参考项目 WS2812流水灯(转向灯)上电模式 www.youwenfan.com/contentcna/69897.html

硬件连接

WS2812 LED灯带:
  DIN -> Arduino引脚6
  VCC -> 5V电源
  GND -> 地线

按钮:
  左转向按钮 -> Arduino引脚2
  右转向按钮 -> Arduino引脚3
  双闪按钮  -> Arduino引脚4
  所有按钮另一端接地

自定义选项

  1. 修改颜色
// 琥珀色 (255, 100, 0)
strip.setPixelColor(i, strip.Color(R, G, B));
  1. 调整动画速度
const long interval = 300; // 增加此值减慢动画,减小则加快
  1. 改变LED数量
#define LED_COUNT 16 // 根据实际LED数量修改
  1. 添加更多模式
  • TurnSignalMode枚举中添加新模式
  • loop()的switch语句中添加处理逻辑
  • 创建对应的动画函数

这个实现模拟了汽车转向灯的真实效果,流水动画让转向指示更加直观,上电自检功能确保所有LED正常工作,适合用于车辆模型、自行车转向指示或任何需要方向指示的应用场景。

posted @ 2025-07-24 09:51  kiyte  阅读(49)  评论(0)    收藏  举报