#include <Adafruit_NeoPixel.h>
#define BUTTON_PIN 2 // Button pin
#define LED_PIN 5 // NeoPixel LED strip pin
#define LED_COUNT 16
#define BUZZER_PIN 6 // Buzzer pin
#define RESET_PIN 3 // Reset button pin
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
enum State { IDLE, FIRST_CYCLE, FIRST_CYCLE_FINISHED, SECOND_CYCLE, SECOND_CYCLE_FINISHED, PAUSED, FINISHED, PULSING };
State state = IDLE;
unsigned long previousMillis = 0;
const long interval = 1000; // Interval at which to update the LEDs (1 second)
int ledIndex = LED_COUNT; // Start with all LEDs on for initialization
int pulseCount = 0; // Count pulses for the last LED
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP); // Use internal pull-up resistor
pinMode(BUZZER_PIN, OUTPUT); // Set the buzzer pin as output
pinMode(RESET_PIN, INPUT_PULLUP); // Use internal pull-up resistor for reset button
strip.begin();
setAllLedsColor(strip.Color(255, 0, 255)); // Initialize all pixels to magenta
strip.show();
}
void loop() {
static bool lastButtonState = HIGH;
static bool lastResetButtonState = HIGH;
bool currentButtonState = digitalRead(BUTTON_PIN);
bool currentResetButtonState = digitalRead(RESET_PIN);
// Detect button press
if (currentButtonState == LOW && lastButtonState == HIGH) {
delay(50); // Debounce
if (digitalRead(BUTTON_PIN) == LOW) {
if (state == IDLE) {
state = FIRST_CYCLE;
ledIndex = LED_COUNT;
pulseCount = 0; // Reset pulse count for new cycle
previousMillis = millis();
setAllLedsColor(strip.Color(0, 255, 0)); // Start with all LEDs green for first cycle
} else if (state == FIRST_CYCLE_FINISHED) {
state = SECOND_CYCLE;
ledIndex = LED_COUNT;
pulseCount = 0; // Reset pulse count for new cycle
previousMillis = millis();
setAllLedsColor(strip.Color(255, 255, 0)); // Start with all LEDs yellow for second cycle
} else if (state == SECOND_CYCLE_FINISHED) {
state = IDLE;
setAllLedsColor(strip.Color(255, 255, 0)); // All LEDs yellow for the next cycle
} else if (state == FIRST_CYCLE || state == SECOND_CYCLE) {
state = PAUSED;
} else if (state == PAUSED) {
state = (state == FIRST_CYCLE) ? FIRST_CYCLE : SECOND_CYCLE;
previousMillis = millis() - (interval * (LED_COUNT - ledIndex)); // Adjust timing to resume correctly
}
}
}
lastButtonState = currentButtonState;
// Detect reset button press
if (currentResetButtonState == LOW && lastResetButtonState == HIGH) {
delay(50); // Debounce
if (digitalRead(RESET_PIN) == LOW) {
// "Boot" effect
strip.setPixelColor(0, strip.Color(255, 255, 0)); // First LED yellow
strip.show();
delay(200);
setAllLedsColor(strip.Color(255, 255, 0)); // Reset all LEDs to yellow
strip.show();
state = IDLE; // Reset state to IDLE
}
}
lastResetButtonState = currentResetButtonState;
if (state == FIRST_CYCLE || state == SECOND_CYCLE) {
updateCycle();
}
if (state == PULSING) {
pulseLastLed();
}
}
void setAllLedsColor(uint32_t color) {
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, color);
}
strip.show();
}
void updateCycle() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval && ledIndex > 0) {
previousMillis = currentMillis;
ledIndex--;
for (int i = 0; i < ledIndex; i++) {
// Update colors based on the current segment
if (state == FIRST_CYCLE) {
if (ledIndex > 9) {
strip.setPixelColor(i, strip.Color(0, 255, 0)); // Green
} else if (ledIndex > 4) {
strip.setPixelColor(i, strip.Color(255, 165, 0)); // Orange
} else {
strip.setPixelColor(i, strip.Color(255, 0, 0)); // Red
}
} else if (state == SECOND_CYCLE) {
strip.setPixelColor(i, strip.Color(255, 165, 0)); // Orange
}
}
strip.setPixelColor(ledIndex, strip.Color(0, 0, 0)); // Turn off the next LED
strip.show();
if (ledIndex == 0) {
state = PULSING; // Transition to pulsing the last LED
}
}
}
void pulseLastLed() {
static bool isOn = false;
static unsigned long lastPulseTime = millis();
if (millis() - lastPulseTime > 100 && pulseCount < 20) { // Faster pulse rate for the last LED, limit to 20 pulses
isOn = !isOn;
strip.setPixelColor(0, isOn ? strip.Color(255, 0, 0) : strip.Color(0, 0, 0)); // Toggle the last LED
strip.show();
lastPulseTime = millis();
pulseCount++;
if (pulseCount == 20) {
strip.setPixelColor(0, strip.Color(0, 0, 0)); // Ensure the last LED is off after pulsing
strip.show();
beep(); // Beep to signal the end of the cycle
state = (state == FIRST_CYCLE) ? FIRST_CYCLE_FINISHED : SECOND_CYCLE_FINISHED; // Mark the cycle as finished
}
}
}
void beep() {
digitalWrite(BUZZER_PIN, HIGH);
delay(100); // Beep for 100 milliseconds
digitalWrite(BUZZER_PIN, LOW);
}