Concept
I try to find a new challenge in every project. For the Evil Queen’s Dungeon book nook, I wanted to pay homage to the Disneyland Snow White’s Scary Adventures ride before it was plussed to make it a bit less terrifying to small children. For this book nook, the three challenges were:
- Use an audio sound track that can be switched on and off
- Have lightning flashes synchronized to the audio
- Use UV LEDs and fluorescent paint
Successes and challenges
I am extremely happy… that this book nook is DONE! It turned out well and I checked all of the boxes on the challenges. It fought me every step of the way. Fluorescent paint SUCKS! It’s not the paint’s fault—I used really good paint. It just shows every stroke and flaw under UV and you need to paint under UV which I’m sure caused me permanent damage of some sort… ok… not really. It’s a tough material to use and I found that airbrushing always provided the best results so… TIP! There are also a lot of little bits and bottles. Fighting with the paint made wanting to paint a huge chore… which it shouldn’t be.
Resources
It’s important to respect creative rights so I will link to source files where appropriate and provide downloads to files that I’ve created or where licensing allows me to freely redistribute. Sharing is caring in the maker community but, as creative people, we all would like credit where credit is due.
Sound
I have a monthly subscription to Epidemic Sound. I do not currently receive any fat envelopes of cash to endorse them and there are several other free and paid sources of sound tracks and effects out there. For this project, I was inspired by the Sounds of Disneyland audio site and used their Dark Rides section as an inspiration to build my soundtrack.
Downloads
Snow White Nook Walls
Snow White Sign STL
Snow White Sign SVG
Links
Code
/*
Nothing happens in a vacuum. Thanks to the following:
Adafruit NeoPixel Uberguide
https://learn.adafruit.com/adafruit-neopixel-uberguide
DFPlayer Mini Docs
https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299
"If I have seen further it is by standing on the shoulders of Giants."
- Isaac Newton
*/
// These libraries must be installed prior to uploading
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
// neopixel
#include
#ifdef __AVR__
#include
#endif
// Multitasking setup
long previousMillis01 = 0;
long previousMillis02 = 0;
long previousMillis03 = 0;
long previousMillis04 = 0;
// Audio setup
// Use pins 2 and 3 to communicate with DFPlayer Mini
static const uint8_t PIN_MP3_TX = 2; // Connects to module's RX
static const uint8_t PIN_MP3_RX = 3; // Connects to module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
DFRobotDFPlayerMini player;
// Define the audio play button pin
int audiopin = 8;
long startMillis = 0;
// Set initial brightness (0-255)
int brightness = 255;
int flickerDelay = random(10, 100);
int flashDelay = random(30, 100);
int cauldronDelay = random(10, 100);
int pulseDelay = 50;
int r = 0;
int g = 0;
int b = 0;
int w = 0;
int state = 0;
int inc = 0;
// Fire and Cauldron
Adafruit_NeoPixel strip01 = Adafruit_NeoPixel(2, 4, NEO_GRB + NEO_KHZ800);
// Cell
Adafruit_NeoPixel strip02 = Adafruit_NeoPixel(1, 5, NEO_GRB + NEO_KHZ800);
// Windows
Adafruit_NeoPixel strip03 = Adafruit_NeoPixel(2, 6, NEO_GRBW + NEO_KHZ800);
// Ceiling
Adafruit_NeoPixel strip04 = Adafruit_NeoPixel(5, 7, NEO_GRB + NEO_KHZ800);
// Define color of flicker effect function
// c = color being randomize
// r = random range - the smaller the number the less variation
int myFlickerColor(int c, int r) {
int flicker = random(0, r);
c = c - flicker;
if (c < 0) c = 0;
return c;
}
int myFlickerColor02(int c, int r) {
int flicker = random(0, r);
c = c - flicker;
if (c < 0) c = 0;
return c;
}
void setup() {
// Audio setup
// Init serial port
Serial.begin(9600);
// Init serial port for DFPlayer Mini
softwareSerial.begin(9600);
// Start communication with DFPlayer Mini
if (player.begin(softwareSerial)) {
//Serial.println("OK");
player.EQ(DFPLAYER_EQ_JAZZ);
player.volume(0);
} else {
//Serial.println("Connecting to DFPlayer Mini failed!");
}
pinMode(audiopin, INPUT_PULLUP);
// Neopixel setup
strip01.begin();
strip02.begin();
strip03.begin();
strip04.begin();
// Set solid color LEDs
// Parameters (LED number, Red, Green, Blue), LED number starts with 0, color values 0-255
// Cell
strip02.setPixelColor(0, 100, 200, 50);
strip02.show();
// Ceiling
// Rear left
strip04.setPixelColor(0, 25, 100, 10);
// Front left
strip04.setPixelColor(1, 75, 0, 50);
// Front center
strip04.setPixelColor(2, 5, 30, 5);
// Front right
strip04.setPixelColor(3, 75, 25, 0);
// Rear right
strip04.setPixelColor(4, 85, 0, 50);
strip04.show();
// Randomize random
randomSeed(analogRead(0));
}
void loop() {
//grab current milliseconds
unsigned long currentMillis = millis();
// check for audio on
if (digitalRead(audiopin) == HIGH) {
player.pause();
} else
{
// player.volume(20);
}
// check to see if audio is playing
int busyPin = 0;
busyPin = analogRead(A0);
// Test value of busy pin and button state
// Trigger audio if busy pin reads over 300 (no audio playing) and button is high
if (busyPin > 300 && digitalRead(audiopin) != HIGH) {
player.volume(20);
player.play(1);
startMillis = currentMillis;
}
// NeoPixel LEDs
// Windows
if (currentMillis - startMillis < 3000) {
if (currentMillis - previousMillis01 > flashDelay) {
previousMillis01 = currentMillis;
w = myFlickerColor02(220, 220);
strip03.setPixelColor(0, 10, 10, 0, w);
strip03.setPixelColor(1, 10, 10, 0, w);
strip03.show();
flashDelay = random(50, 200);
}
} else {
strip03.setPixelColor(0, 120, 200, 0, 0);
strip03.setPixelColor(1, 120, 200, 0, 0);
strip03.show();
}
if (currentMillis - previousMillis04 > pulseDelay) {
previousMillis04 = currentMillis;
if (state == 0 and inc < 75)
{
strip01.setPixelColor(1, inc, 25, inc);
strip01.show();
inc++;
} else {
state = 1;
}
if (state == 1 and inc > 0) {
strip01.setPixelColor(1, inc, 25, inc);
strip01.show();
inc--;
} else {
state = 0;
}
}
if (currentMillis - previousMillis03 > flickerDelay) {
previousMillis03 = currentMillis;
// Define fire color
r = myFlickerColor(60, 30);
g = myFlickerColor(20, 10);
b = myFlickerColor(0, 10);
strip01.setPixelColor(0, r, g, b);
strip01.show();
flickerDelay = random(25, 150);
}
}