Creating a Staff That Answers Questions
Introducing a captivating DIY project that combines technology and enchantment: a motion-activated, fortune-telling staff. This interactive prop is perfect for Halloween or themed events, delighting users with random fortunes, vibrant LED displays, and mystical sounds.
Components and supplies
1
Passive Buzzer
1
Arduino Nano
1
16x2 LCD display with I²C interface
1
16x2 LCD display with I²C interface
1
WS2182B LED
1
SW-420
Tools and machines
1
buzzer
1
WS2812 LED Strip
1
Resistor
1
LCD Display 16X2
1
Arduino
1
SW-420 Sensor
Apps and platforms
1
Arduino IDE 2.0 (beta)
Project description
Code
Staff Code
c
1// Include the library code 2#include <Wire.h> 3#include <LiquidCrystal_I2C.h> 4#include <FastLED.h> 5 6// Initialize the library with the numbers of the interface pins 7LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16x2 LCD display 8 9#define NUM_LEDS 60 10#define DATA_PIN 6 11#define BUTTON_PIN 5 // Button pin 12#define BUZZER_PIN 4 // Passive buzzer pin 13 14CRGB leds[NUM_LEDS]; 15uint8_t maxBrightness = 50; // Reduced brightness (0-255) 16 17void setup() { 18 // Initialize the LCD 19 lcd.init(); // Initialize the LCD 20 lcd.backlight(); // Turn on the backlight 21 22 // Initialize the LED strip 23 FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS); 24 25 // Set up the button pin 26 pinMode(BUTTON_PIN, INPUT_PULLUP); // Use internal pull-up resistor 27 28 // Set up the buzzer pin 29 pinMode(BUZZER_PIN, OUTPUT); 30 31 // Reset the lights at the start 32 resetLights(); 33} 34 35void loop() { 36 // Check if the button is pressed 37 if (digitalRead(BUTTON_PIN) == LOW) { 38 // Reset the lights at the start of the sequence 39 resetLights(); 40 lcd.init(); // Initialize the LCD 41 lcd.backlight(); 42 // Display "Thinking..." on the LCD 43 lcd.clear(); 44 lcd.print("Thinking..."); 45 46 47 // Run the sine wave effect for 3 seconds 48 runSineWaveEffect(); 49 50 // Define the magical messages 51 const char* positiveMessages[] = { 52 "The path is clear. ", 53 "Fortune favors the brave. ", 54 "Winds whisper of change. ", 55 "The stars align in your favor. ", 56 "Magic flows through you. ", 57 "Your staff glows with power. ", 58 "Wizards recognize your strength. ", 59 "Ancient spells protect you. ", 60 "You wield the magic of the ancients. ", 61 "The light of magic guides you. " 62 }; 63 64 const char* negativeMessages[] = { 65 "Shadows cannot hide the truth. ", 66 "Darkness holds no power here. ", 67 "Mystery lingers in the air. ", 68 "A great journey awaits. ", 69 "Beware the lure of false magic. ", 70 "Illusions may cloud your path. ", 71 "Power can corrupt even the wisest. ", 72 "The staff may lead you astray. ", 73 "Magic can twist intentions. ", 74 "Dark forces lurk nearby. " 75 }; 76 77 const char* neutralMessages[] = { 78 "Courage lights the way forward. ", 79 "Seek the unknown with wisdom. ", 80 "Ask again later. ", 81 "Uncertain times ahead. ", 82 "The winds carry whispers of change. ", 83 "The magic is not yet revealed. ", 84 "Your staff holds untapped potential. ", 85 "A new journey begins soon. ", 86 "Mysteries await your discovery. ", 87 "Balance the magic within. " 88 }; 89 90 int randomCategory = random(0, 3); // Choose a random category (0 for Positive, 1 for Negative, 2 for Neutral) 91 const char* randomMessage; 92 93 // Choose a random phrase from the selected category 94 if (randomCategory == 0) { 95 randomMessage = positiveMessages[random(0, 10)]; // Pick one of the positive options 96 for (int i = 0; i < NUM_LEDS; i++) { 97 leds[i] = CRGB::Green; // Set all LEDs to green for "Positive" 98 } 99 playPositiveSound(); // Play a positive sound for positive messages 100 } else if (randomCategory == 1) { 101 randomMessage = negativeMessages[random(0, 10)]; // Pick one of the negative options 102 for (int i = 0; i < NUM_LEDS; i++) { 103 leds[i] = CRGB::DarkRed; // Set all LEDs to dark red for "Negative" 104 } 105 playWrongSound(); // Play a wrong sound for negative messages 106 } else { 107 randomMessage = neutralMessages[random(0, 10)]; // Pick one of the neutral options 108 for (int i = 0; i < NUM_LEDS; i++) { 109 leds[i] = CRGB::Blue; // Set all LEDs to blue for "Neutral" 110 } 111 playRandomSound(); // Play a random sound for neutral messages 112 } 113 114 FastLED.show(); // Update the LED strip to show the final color 115 116 // Wait a moment for the sound and lights before displaying the message 117 delay(1000); // Delay to allow sound to play and LED color to set 118 119 // Scroll the message on the LCD twice 120 for (int i = 0; i < 2; i++) { // Display the message twice 121 scrollMessage(randomMessage); 122 } 123 124 // Wait for 8 seconds before starting the passive light show 125 for (int i = 0; i < 8; i++) { 126 delay(1000); // Delay for 1 second 127 } 128 129 // Reset lights and LCD after 8 seconds 130 resetLights(); 131 lcd.clear(); 132 lcd.noBacklight(); 133 134 // Start the passive light show 135 while (true) { 136 smoothColorAnimation(); // Start the smooth color animation 137 if (digitalRead(BUTTON_PIN) == LOW) { 138 resetLights(); // Reset lights if the button is pressed again 139 break; // Break the loop to allow the button to work again 140 } 141 } 142 } else { 143 // If no input, run a smooth color animation in passive mode 144 smoothColorAnimation(); 145 } 146} 147 148// Function to reset the lights (turn them off) 149void resetLights() { 150 for (int i = 0; i < NUM_LEDS; i++) { 151 leds[i] = CRGB::Black; // Turn off all LEDs 152 } 153 FastLED.show(); // Update the LED strip 154} 155 156// Function to run the sine wave effect for 3 seconds 157void runSineWaveEffect() { 158 unsigned long startTime = millis(); // Get the current time 159 while (millis() - startTime < 3000) { // Run the loop for 3 seconds (3000 ms) 160 for (int i = 0; i < NUM_LEDS; i++) { 161 // Calculate the sine value based on the position of the LED and time 162 float sineValue = sin((i + millis() / 100.0) * 0.2); // Adjust 0.2 to control the wave frequency 163 164 // Map the sine value to brightness (0 to 255) 165 uint8_t colorBrightness = (sineValue + 1) * (maxBrightness / 2); // Scales sine value (-1 to 1) to brightness 166 167 // Set the LED color to white with the calculated brightness 168 leds[i] = CRGB(colorBrightness, colorBrightness, colorBrightness); // White based on sine wave 169 } 170 171 FastLED.show(); // Update the LED strip 172 delay(20); // Small delay for smoother animation 173 } 174} 175 176// Function to run a smooth color animation in passive mode 177void smoothColorAnimation() { 178 static uint8_t hue = 0; // Initialize hue for color cycling 179 for (int i = 0; i < NUM_LEDS; i++) { 180 leds[i] = CHSV(hue + (i * 255 / NUM_LEDS), 255, maxBrightness); // Cycle through colors 181 } 182 FastLED.show(); // Update the LED strip 183 hue++; // Increment hue for the next frame 184 delay(30); // Adjust delay for the speed of the color cycling 185} 186 187// Function to scroll a message on the LCD 188void scrollMessage(const char* message) { 189 int messageLength = strlen(message); // Get the length of the message 190 int displayLength = 16; // Length of the display (number of characters) 191 192 // Loop through the message 193 for (int position = 0; position < messageLength - displayLength + 1; position++) { 194 lcd.setCursor(0, 0); // Reset cursor to the start 195 lcd.print(message + position); // Print a substring starting from current position 196 delay(300); // Delay to control scrolling speed 197 } 198 199 // If the message is longer than the display length, scroll it back to the beginning 200 for (int position = messageLength - displayLength; position >= 0; position--) { 201 lcd.setCursor(0, 0); // Reset cursor to the start 202 lcd.print(message + position); // Print a substring starting from current position 203 delay(300); // Delay to control scrolling speed 204 } 205} 206 207// Function to play a wrong sound for "Negative" 208void playWrongSound() { 209 tone(BUZZER_PIN, 500, 300); // Play tone at 500 Hz for 300 ms 210 delay(300); 211 tone(BUZZER_PIN, 400, 300); // Play tone at 400 Hz for 300 ms 212 delay(300); 213 noTone(BUZZER_PIN); 214} 215 216// Function to play a positive sound for "Positive" 217void playPositiveSound() { 218 tone(BUZZER_PIN, 1000, 300); // Play tone at 1000 Hz for 300 ms 219 delay(300); 220 tone(BUZZER_PIN, 1200, 300); // Play tone at 1200 Hz for 300 ms 221 delay(300); 222} 223 224// Function to play a random sound 225void playRandomSound() { 226 tone(BUZZER_PIN, random(500, 1500), 300); // Play random tone for 300 ms 227 delay(300); 228}
Comments
Only logged in users can leave comments