#include <Adafruit_NeoPixel.h>
// --------- Pin Definitions ---------
#define SELECT_BUTTON_PIN 2 // Button to select a color & sparkle
#define EFFECT_BUTTON_PIN 3 // Button to run the pulse effect & trigger solenoid
#define SOLENOID_PIN 4 // Controls the MOSFET for the solenoid
#define NEOPIXEL_PIN 11 // Data pin for the NeoPixel strip
// --------- NeoPixel Settings ---------
#define NUM_PIXELS 180 // Full 3 m strip at 60 LEDs/m
#define TAIL_LENGTH 8 // Number of LEDs lit in the moving pulse
#define SPARK_TIME 2000 // Duration for the sparkle effect
#define PULSE_SPEED 20 // Speed of the pulse effect
// --------- Color Options ---------
uint32_t colorOptions[] = {
Adafruit_NeoPixel::Color(255, 0, 0), // Red
Adafruit_NeoPixel::Color(0, 255, 0), // Green
Adafruit_NeoPixel::Color(0, 0, 255), // Blue
Adafruit_NeoPixel::Color(255, 255, 0), // Yellow
Adafruit_NeoPixel::Color(255, 0, 255), // Magenta
Adafruit_NeoPixel::Color(0, 255, 255), // Cyan
Adafruit_NeoPixel::Color(255, 128, 0) // Orange
};
const int numColors = sizeof(colorOptions) / sizeof(colorOptions[0]);
// Default selected color is white.
uint32_t selectedColor = Adafruit_NeoPixel::Color(255, 255, 255);
Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
// Initialize buttons with internal pull-ups
pinMode(SELECT_BUTTON_PIN, INPUT_PULLUP);
pinMode(EFFECT_BUTTON_PIN, INPUT_PULLUP);
// Set up the solenoid control pin
pinMode(SOLENOID_PIN, OUTPUT);
digitalWrite(SOLENOID_PIN, LOW); // Ensure the solenoid is off
// Initialize the NeoPixel strip
strip.begin();
strip.show(); // Turn all pixels off
// Seed the random number generator with noise from an unconnected analog pin.
randomSeed(analogRead(A0));
}
void loop() {
// ----- Color Select & Sparkle Effect -----
if (digitalRead(SELECT_BUTTON_PIN) == LOW) {
delay(50); // debounce
if (digitalRead(SELECT_BUTTON_PIN) == LOW) { // Confirm button is still pressed
// Pick a random color from the list.
selectedColor = Adafruit_NeoPixel::Color(random(0, 256), random(0, 256), random(0, 256));
// Sparkle the scepter with the chosen color for the specified duration.
sparklingEffect(selectedColor, SPARK_TIME);
// Wait until the button is released.
while (digitalRead(SELECT_BUTTON_PIN) == LOW) {
delay(10);
}
delay(100); // extra debounce
}
}
// ----- Pulse Effect & Solenoid Activation -----
if (digitalRead(EFFECT_BUTTON_PIN) == LOW) {
delay(50); // debounce
if (digitalRead(EFFECT_BUTTON_PIN) == LOW) { // Confirm button is still pressed
pulseEffect(selectedColor);
// Briefly pulse the solenoid
digitalWrite(SOLENOID_PIN, HIGH);
delay(100); // 100 ms pulse; change if necessary
digitalWrite(SOLENOID_PIN, LOW);
// Wait until the button is released.
while (digitalRead(EFFECT_BUTTON_PIN) == LOW) {
delay(10);
}
delay(100); // extra debounce
}
}
}
// -----------------
// sparklingEffect()
// -----------------
// Flashes the scepter by lighting 10 random pixels in random colors.
// The effect runs for the specified duration (in milliseconds).
void sparklingEffect(uint32_t color, unsigned long durationMillis) {
unsigned long startTime = millis();
while (millis() - startTime < durationMillis) {
strip.clear();
// Light up 10 random pixels with random colors.
for (int i = 0; i < 10; i++) {
int pix = random(NUM_PIXELS);
// Generate a random color for each spark
uint32_t sparkColor = Adafruit_NeoPixel::Color(random(0, 256), random(0, 256), random(0, 256));
strip.setPixelColor(pix, sparkColor);
}
strip.show();
delay(100); // Cycle speed (adjust for faster or slower sparkles)
}
strip.clear();
strip.show();
}
// -----------------
// pulseEffect()
// -----------------
// Creates a moving “pulse” (with a fading tail) from the bottom to the top of the strip,
// using the specified color. After the pulse, the strip is cleared.
void pulseEffect(uint32_t color) {
for (int i = NUM_PIXELS + TAIL_LENGTH - 1; i >= 0; i--) {
strip.clear();
for (int j = 0; j < TAIL_LENGTH; j++) {
int pixelIndex = i + j;
if (pixelIndex >= 0 && pixelIndex < NUM_PIXELS) {
uint8_t brightness = 255 - (j * (255 / TAIL_LENGTH));
uint8_t r = (color >> 16) & 0xFF;
uint8_t g = (color >> 8) & 0xFF;
uint8_t b = color & 0xFF;
r = (uint8_t)(((uint16_t)r * brightness) / 255);
g = (uint8_t)(((uint16_t)g * brightness) / 255);
b = (uint8_t)(((uint16_t)b * brightness) / 255);
uint32_t fadeColor = strip.Color(r, g, b);
strip.setPixelColor(pixelIndex, fadeColor);
}
}
strip.show();
delay(PULSE_SPEED); // Adjust the speed of the pulse (smaller = faster)
}
strip.clear();
strip.show();
}