#include <FastLED.h>
// 灯珠数量
#define NUM_LEDS 30
// LED 灯起始引脚
#define DATA_PIN 2
// led灯带数量
#define NUM_STRIPS 6
float distThreshold = 20;
// 吹气感应引脚
int breathPin = 8;
// 超声波测距
int trigPin = 6;
int echoPin = 7;
// 按钮数量
#define btnNum 4
// 按钮引脚数组
int btnPins[btnNum] = {2,3,4,5};
// led 颜色
CRGB ledColor = CRGB(0, 255, 0);
// 三条 LED 灯带
CRGB leds[NUM_STRIPS][NUM_LEDS];
// 亮的灯带下标 (同时只能亮一个)
int ledsIndex = -1;
int lastLedsIndex = ledsIndex;
int ledCountIndex = 0; // 亮到第几颗 Led 灯珠
// 获取距离
float getDistance(int trig, int echo);
void setup() {
// 设定串口通信波特率
Serial.begin(9600);
Serial.setTimeout(50);
// 吹气感应
pinMode(breathPin, INPUT);
// 超声波测距
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// 按钮
for(int i=0; i<btnNum; i++){
pinMode(btnPins[i], INPUT);
}
// led 灯带指定控制引脚 WS2812
FastLED.addLeds<NEOPIXEL,9>(leds[0],NUM_LEDS);
FastLED.addLeds<NEOPIXEL,10>(leds[1],NUM_LEDS);
FastLED.addLeds<NEOPIXEL,11>(leds[2],NUM_LEDS);
FastLED.addLeds<NEOPIXEL,12>(leds[3],NUM_LEDS);
FastLED.addLeds<NEOPIXEL,13>(leds[4],NUM_LEDS);
FastLED.addLeds<NEOPIXEL,14>(leds[5],NUM_LEDS);
// 灯带亮度
FastLED.setBrightness(84); // [0,255]
FastLED.clear();
FastLED.show();
}
// 时间间隔检测
int ledLastTime = 0, ledInterval = 0.015;
// led 灯是否正在亮灯
bool canLedLight = false;
bool ledShowUpdateFlag = true;
void loop() {
// 0: 有吹气 1: 没有吹气
int breathVal = digitalRead(breathPin);
if((ledCountIndex == 0 || ledCountIndex >= NUM_LEDS-1) && breathVal <= 0 && !canLedLight){
Serial.print("breathVal: ");
Serial.print(breathVal);
Serial.print(",");
ledShowUpdateFlag = true;
ledsIndex = 0;
FastLED.clear();
FastLED.show();
}
// 距离
float dist = getDistance(trigPin,echoPin);
if((ledCountIndex == 0 || ledCountIndex >= NUM_LEDS-1) && dist <= distThreshold && !canLedLight){
Serial.print("dist: ");
Serial.print(dist);
Serial.print(",");
ledShowUpdateFlag = true;
ledsIndex = 1;
FastLED.clear();
FastLED.show();
}
// 按钮
// 0: 没有按 1: 按了
int btn = 0;
for(int i=0; i<btnNum; i++){
int tmpBtnVal = digitalRead(btnPins[i]);
btn |= tmpBtnVal;
if((ledCountIndex == 0 || ledCountIndex >= NUM_LEDS-1) && tmpBtnVal >= 1 && !canLedLight){
Serial.print("btn[" + String(i) +"]: ");
Serial.print(tmpBtnVal);
Serial.print(",");
ledShowUpdateFlag = true;
ledsIndex = 2+i;
FastLED.clear();
FastLED.show();
}
}
if(ledsIndex >= 0 && ledShowUpdateFlag){
ledLight(ledsIndex);
}
delay(300);
}
void ledLight(int ledsIndex){
// ledsIndex = -1 没有需要亮灯的
if(ledsIndex < 0) return;
Serial.print("ledCountIndex: ");
// ledCountIndex
Serial.println(ledCountIndex);
canLedLight = true; // 设置正在亮灯
float currentTime = millis() / 1000.0;
if(ledLastTime == 0 || (currentTime-ledLastTime) >= ledInterval){ // 间隔亮灯
ledLastTime = currentTime;
leds[ledsIndex][ledCountIndex] = ledColor;
FastLED.show();
if(ledCountIndex < NUM_LEDS-1) ledCountIndex++;
else{
canLedLight = false;
ledCountIndex = 0;
ledShowUpdateFlag = false;
Serial.println(ledsIndex);
}
}
}
// 获取距离 cm
float getDistance(int trig, int echo) {
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
float distance = pulseIn(echo, HIGH) * 0.0343 / 2;
delay(10);
return distance;
}