#include <Adafruit_NeoPixel.h>
#include <LiquidCrystal.h>
#include <Servo.h>
// LED strip configuration
#define LED_PIN 8 // Pin connected to the NeoPixel strip
#define NUM_LEDS 26 // Number of LEDs in the strip
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Sound sensor and potentiometer configuration
#define SOUND_PIN A0 // Analog pin for sound sensor input
#define POT_PIN A1 // Analog pin for potentiometer input
// Servo configuration
#define SERVO_PIN 9 // Pin connected to the servo motor
Servo myServo;
// LCD configuration
#define LCD_RS 12
#define LCD_E 11
#define LCD_D4 5
#define LCD_D5 4
#define LCD_D6 3
#define LCD_D7 2
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
// Button configuration
#define BUTTON_PIN 7 // Pin connected to the mode button
int mode = 0; // Current operation mode (0: normal, 1: inverse, etc.)
// Color gradient palette
uint32_t colorPalette[] = {
strip.Color(255, 0, 0), // Red
strip.Color(255, 128, 0), // Orange
strip.Color(255, 255, 0), // Yellow
strip.Color(128, 255, 0), // Yellow-Green
strip.Color(0, 255, 0), // Green
strip.Color(0, 255, 128), // Green-Cyan
strip.Color(0, 255, 255), // Cyan
strip.Color(0, 128, 255), // Cyan-Blue
strip.Color(0, 0, 255), // Blue
strip.Color(128, 0, 255), // Blue-Magenta
strip.Color(255, 0, 255), // Magenta
strip.Color(255, 0, 128) // Magenta-Red
};
const int numColors = sizeof(colorPalette) / sizeof(colorPalette[0]);
// Variables for LED control and sound levels
int currentColorIndex = 0; // Current color index in the palette
int previousNumLEDsToLight = 0; // Previous number of lit LEDs for comparison and color changing
// Buffer for storing recent sound readings
const int bufferSize = 40;
int soundBuffer[bufferSize] = {0}; // Circular buffer for sound levels
int bufferIndex = 0; // Current index in the sound buffer
int randomIndices[NUM_LEDS]; // Preset array of random indices for random mode
int lastBrightness; // Last recorded brightness to avoid unnecessary updates
void setup() {
// Initialize LED strip
strip.begin();
strip.show();
// Initialize LCD
lcd.begin(16, 2);
lcd.print("Initializing...");
// Attach and initialize the servo
myServo.attach(SERVO_PIN);
myServo.write(0); // Start at 0 degrees
randomSeed(analogRead(A3)); // Seed for random generation
shuffleArray(); // Generate random LED order for random mode
// Setup button as input with pull-up resistor
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Display the initial mode and brightness on the LCD
lcd.setCursor(0, 0);
lcd.print("Mode:");
int brightness = analogRead(POT_PIN);
printMode();
printBrightness(brightness);
}
void loop() {
// Check for button press to change modes
if (!digitalRead(BUTTON_PIN)) {
mode++;
if (mode == 4) mode = 0; // Cycle through 4 modes
// Turn off all LEDs before changing mode
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off LEDs
}
strip.show();
printMode(); // Update mode display on LCD
delay(1000); // Debounce delay
}
// Read sound level and brightness
int soundLevel = analogRead(SOUND_PIN);
int brightness = analogRead(POT_PIN);
// Update sound buffer with new reading
soundBuffer[bufferIndex] = soundLevel;
bufferIndex = (bufferIndex + 1) % bufferSize;
// Find the maximum value in the buffer
int maxSoundLevel = 0;
for (int i = 0; i < bufferSize; i++) {
if (soundBuffer[i] > maxSoundLevel) {
maxSoundLevel = soundBuffer[i];
}
}
// Map brightness to LED brightness and servo angle
int ledBrightness = map(brightness, 0, 1023, 0, 255); // Adjust as needed
int servoAngle = map(brightness, 0, 1023, 0, 180);
// Update servo and LCD brightness if there is a significant change
if (abs(ledBrightness - lastBrightness) >= 3) {
lastBrightness = ledBrightness;
printBrightness(brightness);
myServo.write(servoAngle);
}
// Determine how many LEDs to light up based on sound level
int numLEDsToLight = map(maxSoundLevel, 525, 680, 0, NUM_LEDS);
// Change color if there's a large increase in lit LEDs
if (numLEDsToLight - previousNumLEDsToLight > 5) {
currentColorIndex = (currentColorIndex + 1) % numColors; // Change color
}
previousNumLEDsToLight = numLEDsToLight;
// Extract RGB components of the current color and adjust by brightness
uint32_t currentColor = colorPalette[currentColorIndex];
int red = (currentColor >> 16) & 0xFF;
int green = (currentColor >> 8) & 0xFF;
int blue = currentColor & 0xFF;
// Scale the RGB components by the brightness
red = (red * ledBrightness) / 255;
green = (green * ledBrightness) / 255;
blue = (blue * ledBrightness) / 255;
// Update LEDs based on the selected mode
for (int i = 0; i < NUM_LEDS; i++) {
if (mode == 0) { // Normal mode: light up LEDs sequentially from the start
if (i < numLEDsToLight) {
strip.setPixelColor(i, strip.Color(red, green, blue)); // Set active LEDs to the current color
} else {
strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off remaining LEDs
}
} else if (mode == 1) { // Reverse mode: light up LEDs sequentially from the end
if (i < numLEDsToLight) {
strip.setPixelColor(NUM_LEDS - 1 - i, strip.Color(red, green, blue)); // Set active LEDs in reverse order
} else {
strip.setPixelColor(NUM_LEDS - 1 - i, strip.Color(0, 0, 0)); // Turn off remaining LEDs
}
} else if (mode == 2) { // Center mode: light LEDs symmetrically from the center outward
int mid = NUM_LEDS / 2;
for (int i = 0; i < NUM_LEDS; i++) {
if (i < numLEDsToLight / 2) {
// Light LEDs symmetrically from the center
strip.setPixelColor(mid - i - 1, strip.Color(red, green, blue));
strip.setPixelColor(mid + i, strip.Color(red, green, blue));
} else {
// Turn off LEDs beyond the active range
if (mid - i - 1 >= 0) strip.setPixelColor(mid - i - 1, strip.Color(0, 0, 0));
if (mid + i < NUM_LEDS) strip.setPixelColor(mid + i, strip.Color(0, 0, 0));
}
}
} else if (mode == 3) { // Random mode: light LEDs in a random order
// Clear all LEDs first
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
// Light LEDs using the preset random order
for (int i = 0; i < numLEDsToLight; i++) {
int idx = randomIndices[i]; // Get random LED index
strip.setPixelColor(idx, strip.Color(red, green, blue)); // Set the color for the random index
}
// Reshuffle random order if no LEDs are lit
if (numLEDsToLight == 0) {
shuffleArray();
}
}
}
// Send the updated LED colors to the strip
strip.show();
//delay(1); // Necessary for the servo, if the servo is shaking the arduino can not keep up with the PWM
}
// Shuffle array for random LED mode
void shuffleArray() {
for (int i = 0; i < NUM_LEDS; i++) {
randomIndices[i] = i;
}
for (int i = NUM_LEDS - 1; i > 0; i--) {
int j = random(0, i + 1);
int temp = randomIndices[i];
randomIndices[i] = randomIndices[j];
randomIndices[j] = temp;
}
}
// Update the LCD with the current mode
void printMode() {
lcd.setCursor(0, 0);
lcd.print("Mode:");
if (mode == 0) lcd.print(" Normal ");
else if (mode == 1) lcd.print(" Inversed ");
else if (mode == 2) lcd.print(" Center ");
else if (mode == 3) lcd.print(" Random ");
}
// Update the LCD with the current brightness
void printBrightness(int bright) {
lcd.setCursor(0, 1);
lcd.print("Brightness: ");
lcd.print(map(bright, 0, 1023, 0, 100));
lcd.print("% ");
}
LCD contrast
Brightness control
Mode change