// Source code for the Cauldron Project (2016)
// Written by Jonah McKay
//
//
// A Monkey Dream Monkey Do project
// http://www.monkeydreammonkeydo.com
// Contact e-mail: ian@amimckay.com
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
//PIN VARIABLES
const int neopixelPin = 5;
const int triggerPin = 9;
const int pingPin = A1;
const int debugPin = 10;
//NEOPIXEL COUNT
const int neopixelCount = 24;
float neopixelVariation[neopixelCount] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //24 zeroes, count em
//ULTRASONIC VARIABLES
int ultrasonicDistance = 0;
boolean ultrasonicReady = false;
long timeSincePing = 0;
boolean ultrasonicPrimed = false;
boolean ultrasonicGesture = false;
long timeSinceGesture = 0;
long timeSincePrime = 0;
//PHASE VARIABLES
long transitionProgress = 0;
int currentPhase = 0;
long timeSinceTransitionUpdate = 0;
//BEGINNING START VARIABLES
int cyclesHeld = 0;
boolean started = false;
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(neopixelCount, neopixelPin, NEO_GRB + NEO_KHZ800);
void setup() {
// put your setup code here, to run once:
pixels.begin(); // This initializes the NeoPixel library.
pinMode(pingPin, OUTPUT);
pinMode(triggerPin, OUTPUT);
pinMode(debugPin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
//bluePhase(transitionProgress);
if (started) {
if (digitalRead(debugPin) == LOW)
{
while (digitalRead(debugPin) == LOW)
{
delay(10);
}
nextPhase();
}
runCurrentPhase(currentPhase, transitionProgress);
changeVariation(200, 10);
delay(random(1, 100));
if (millis() > timeSinceTransitionUpdate+100)
{
timeSinceTransitionUpdate = millis();
transitionProgress += 1;
}
if (millis() > timeSincePing+500)
{
ultrasonicDistance = ping();
//Serial.println(ultrasonicDistance);
if (ultrasonicDistance < 60 && ultrasonicReady)
{
cyclesHeld++;
if (cyclesHeld > 4)
{
nextPhase();
cyclesHeld = 0;
ultrasonicReady = false;
}
}
if (ultrasonicDistance > 67)
{
ultrasonicReady = true;
cyclesHeld = 0;
}
timeSincePing = millis();
}
}
else //haven't started
{
readyState();
changeVariation(200, 10);
delay(random(1, 100));
//Serial.println(ultrasonicDistance);
if (millis() > timeSincePing+500)
{
ultrasonicDistance = ping();
timeSincePing = millis();
if (ultrasonicDistance < 60)
{
cyclesHeld++;
if (cyclesHeld > 4)
{
//Serial.println("STARTING");
started = true;
nextPhase();
cyclesHeld = 0;
}
}
else
{
cyclesHeld = 0;
}
}
}
}
long ping() {
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
long duration;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
return duration / 29 / 2; //return in centimeters
}
/////////////////////////////////////////
// FUNCTIONS FOR NEOPIXELS ///
// ///
// Includes the variations, and the ///
// "phases" ///
/////////////////////////////////////////
void changeVariation(int bounds, float shave) {
for (int i=0;i<neopixelCount;i++){
float upperBound = (bounds-(neopixelVariation[i]/2))/shave;
float lowerBound = -( (bounds + (neopixelVariation[i]/2) ) / shave);
neopixelVariation[i] += random(lowerBound, upperBound);
}
}
float noNegative(float value)
{
if (value < 0) {
return 0;
}
else
{
return value;
}
}
void setWhiteLight(int i) {
pixels.setPixelColor(i, pixels.Color(150+neopixelVariation[i],150+neopixelVariation[i],150+neopixelVariation[i])); // White
pixels.show();
}
void safeState() {
//Sets the lights to a clean, white colour.
for(int i=0;i<neopixelCount;i++){
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
setWhiteLight(i);
}
}
void safeTransitionState(int chance) {
for(int i=0;i<neopixelCount;i++){
if (random(0, 100) < chance-20)
{
setWhiteLight(i);
}
else if (random(0, 100) < chance)
{
pixels.setPixelColor(i, pixels.Color(50, 50, 50)); // Green Fire
pixels.show();
}
else
{
setReadyLight(i);
}
}
}
void safePhase(long spot) {
if (spot < 200)
{
safeState();
}
else if (spot < 300)
{
safeTransitionState(100 - (spot-200));
}
else
{
readyState();
}
}
void setFireLight(int i) {
pixels.setPixelColor(i, pixels.Color(160+(neopixelVariation[i]*2), 40-neopixelVariation[i]/4,0)); // Fire
pixels.show();
}
void fireState() {
//Sets the lights to a firey, orange-yellow-red colour.
for(int i=0;i<neopixelCount;i++){
setFireLight(i);
}
}
void firePhase(long spot) {
fireState();
}
void setGreenLight(int i) {
pixels.setPixelColor(i, pixels.Color(abs(neopixelVariation[i]/2), 200-abs(neopixelVariation[i]/2), noNegative(neopixelVariation[i]/2))); // Green Fire
pixels.show();
}
void greenState() {
//Sets the lights to a green flame colour
for(int i=0;i<neopixelCount;i++){
setGreenLight(i);
}
}
void greenTransitionState(int chance) {
for(int i=0;i<neopixelCount;i++){
if (random(0, 100) < chance-20)
{
setGreenLight(i);
}
else if (random(0, 100) < chance)
{
pixels.setPixelColor(i, pixels.Color(150, 100-abs(neopixelVariation[i]/2), noNegative(neopixelVariation[i]/2))); // Green Fire
pixels.show();
}
else
{
setReadyLight(i);
}
}
}
void greenPhase(long spot)
{
if (spot < 200)
{
greenState();
}
else if (spot < 300)
{
greenTransitionState(100 - (spot-200));
}
else
{
readyState();
}
}
void setBlueLight(int i)
{
pixels.setPixelColor(i, pixels.Color(abs(neopixelVariation[i]), 30+noNegative(neopixelVariation[i]), 200-(abs(neopixelVariation[i])*2))); // Blue Fire
pixels.show();
}
void blueState() {
//Sets the lights to a blue flame colour
for(int i=0;i<neopixelCount;i++){
setBlueLight(i);
}
}
void blueTransitionState(int chance) {
for(int i=0;i<neopixelCount;i++){
if (random(0, 100) < chance-20)
{
setBlueLight(i);
}
else if (random(0, 100) < chance)
{
pixels.setPixelColor(i, pixels.Color(20-abs(neopixelVariation[i]/5), noNegative(neopixelVariation[i])/4, 100-abs(neopixelVariation[i]/5))); //blue transition fire
pixels.show();
}
else
{
setReadyLight(i);
}
}
}
void bluePhase(long spot)
{
if (spot < 200)
{
blueState();
}
else if (spot < 300)
{
blueTransitionState(100 - (spot-200));
}
else
{
readyState();
}
}
void setRedLight(int i)
{
pixels.setPixelColor(i, pixels.Color(200-abs(neopixelVariation[i]/5), noNegative(neopixelVariation[i]/10), 0)); // Red Fire
pixels.show();
}
void redState() {
//Sets the lights to a blue flame colour
for(int i=0;i<neopixelCount;i++){
setRedLight(i);
}
}
void redTransitionState(int chance) {
for(int i=0;i<neopixelCount;i++){
if (random(0, 100) < chance-20)
{
setRedLight(i);
}
else if (random(0, 100) < chance)
{
pixels.setPixelColor(i, pixels.Color(220-abs(neopixelVariation[i]/5), noNegative(neopixelVariation[i]/4), 80-abs(neopixelVariation[i]/3))); //Red transition fire
pixels.show();
}
else
{
setReadyLight(i);
}
}
}
void redPhase(long spot)
{
if (spot < 200)
{
redState();
}
else if (spot < 300)
{
redTransitionState(100 - (spot-200));
}
else
{
readyState();
}
}
void setPurpleLight(int i)
{
pixels.setPixelColor(i, pixels.Color(200-abs(neopixelVariation[i]/3), 0, 0)); // Purple Fire
pixels.show();
}
void purpleState() {
//Sets the lights to a blue flame colour
for(int i=0;i<neopixelCount;i++){
setPurpleLight(i);
}
}
void purpleTransitionState(int chance) {
for(int i=0;i<neopixelCount;i++){
if (random(0, 100) < chance-20)
{
setPurpleLight(i);
}
else if (random(0, 100) < chance)
{
pixels.setPixelColor(i, pixels.Color(200-abs(neopixelVariation[i]/5), 0, 100-abs(neopixelVariation[i]/5))); //Purple transition fire
pixels.show();
}
else
{
setReadyLight(i);
}
}
}
void purplePhase(long spot)
{
if (spot < 200)
{
purpleState();
}
else if (spot < 300)
{
purpleTransitionState(100 - (spot-200));
}
else
{
readyState();
}
}
void setReadyLight(int i) {
pixels.setPixelColor(i, pixels.Color(5, 0, 0)); //red light
pixels.show();
}
void readyState()
{
int lightCount = random(1, 4);
for(int i=0;i<neopixelCount;i++){
if (i < lightCount)
{
setReadyLight(i);
}
else
{
pixels.setPixelColor(i, pixels.Color(0, 0, 0)); //blank
pixels.show();
}
}
}
/////////////////////////////////////////
// FUNCTIONS FOR ORDER ///
// ///
// Includes functions get which phase ///
// we're in. ///
/////////////////////////////////////////
void runCurrentPhase(int phase, long spot)
{
if (phase == 0)
{
safePhase(spot);
}
else if (phase == 1)
{
greenPhase(spot);
}
else if (phase == 2)
{
bluePhase(spot);
}
else if (phase == 3)
{
redPhase(spot);
}
else
{
currentPhase = 0;
safePhase(spot);
}
}
void nextPhase()
{
currentPhase++;
transitionProgress = 0;
}
void skipToFire()
{
transitionProgress = 300;
}
Comments