#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <Bounce2.h>
#define CONTROL_BUTTONS 3
#define NUM_PIPES 10
#define INITIAL_LED_STATE LOW
#define INITIAL_PIPE_STATE LOW
Bounce2::Button button[CONTROL_BUTTONS] = {Bounce2::Button()};
struct INFOS
{
const byte buttonPin;
bool ledState;
const byte ledPin;
};
INFOS info[CONTROL_BUTTONS] =
{
{20, INITIAL_LED_STATE, 14},
{21, INITIAL_LED_STATE, 15},
{18, INITIAL_LED_STATE, 16},
};
const byte pipePins[NUM_PIPES] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
// NeoPixel setup
#define PINforControl1 12
#define PINforControl2 13
#define PINforControl3 17
#define NUMPIXELS1 16 // number of LEDs on strip
Adafruit_NeoPixel strip1(NUMPIXELS1, PINforControl1, NEO_GRB + NEO_KHZ800); // Declare our NeoPixel strip1 object
Adafruit_NeoPixel strip2(NUMPIXELS1, PINforControl2, NEO_GRB + NEO_KHZ800); // Declare our NeoPixel strip2 object
Adafruit_NeoPixel strip3(NUMPIXELS1, PINforControl3, NEO_GRB + NEO_KHZ800); // Declare our NeoPixel strip3 object
unsigned long prevTimeT1 = millis(); // Deze is voor de knop LED te laten knipperen. Voor iedere actie met een tijdsfactor moet deze regel herhaald worden // Deze is voor de timer van de buizen vallen (current time)
int fadeStep = 0; // state variable for fade function
int counter;
byte mode = 0;
// variabelen voor random generators
long nextTime; // delay value number
long randPipe; // Pipenummer uit random generator
// array buildup for pipe randomizer
int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const int arraySize = sizeof array / sizeof array[0];
int remainingNumbers = 0;
int Level = 0; // moeilijkheidsgraad
int getRandomEntry();
uint32_t Wheel(byte WheelPos);
void colorWipeDelay(uint32_t c, uint8_t wait);
void rainbowCycle();
void rainbow();
void RunGame();
void AllMagnetsOff();
void AllMagnetsOn() ;
void theaterChaseRainbow();
void prepareGame();
int getRandomEntry()
{
random(micros());
if (remainingNumbers == 0)
{
remainingNumbers = arraySize; // Start over with a full array
}
int index = random(remainingNumbers); // 0 to remainingNumbers - 1
int returnValue = array[index];
if (index < remainingNumbers - 1) // Swap the chosen number with the number at the end of the current array (unless the chosen entry is already at the end)
{
array[index] = array[remainingNumbers - 1]; // Move the last entry into the chosen index
array[remainingNumbers - 1] = returnValue; // Move the value from the chosen index into the last entry
}
remainingNumbers--; // Shorten the list so the picked number is not picked again
return returnValue;
}
void setup()
{
Serial.begin(9600);
// Neopixel startup;
strip1.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip2.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip3.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip1.show();
strip2.show();
strip3.show();
// strip1.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
for (byte i = 0; i < NUM_PIPES; i++)
{
pinMode(pipePins[i], OUTPUT);
digitalWrite(pipePins[i], INITIAL_PIPE_STATE);
}
for (byte i = 0; i < CONTROL_BUTTONS; i++)
{
button[i].attach(info[i].buttonPin, INPUT_PULLUP);
button[i].setPressedState(LOW);
button[i].interval(5);
pinMode(info[i].ledPin, OUTPUT);
digitalWrite(info[i].ledPin, info[i].ledState);
}
prepareGame();
Serial.println("Ready for first run");
}
void loop()
{
rainbow(); // Flowing rainbow cycle along the whole strip with NeoPixel; This blocks the Button read loop because there is a delay within the function
for (byte i = 0; i < CONTROL_BUTTONS; i++)
{
button[i].update();
if (button[0].pressed()) // als knop "Gemakkelijk" wordt ingedrukt; set moeilijkheid naar gemakkelijk en start spel
{
Level = 10;
Serial.println("Button Easy is pressed");
counter = 0;
while (counter < arraySize) // when counter = arraySize; exit loop
{
button[0].update();
if (button[0].pressed())
{
Serial.println("Easy mode selected");
mode = 1;
info[0].ledState = HIGH;
info[1].ledState = LOW;
digitalWrite(info[0].ledPin, info[0].ledState);
digitalWrite(info[1].ledPin, info[1].ledState);
}
rainbowCycle();
RunGame();
}
prepareGame();
}
else if (button[1].pressed()) // als knop "Moeilijk" wordt ingedrukt; set moeilijkheid naar Moeilijk en start spel //this code must yet be corrected based on the Btn_Easy code
{
Level = 3;
Serial.println("Button Hard is pressed");
counter = 0;
while (counter < arraySize) // when counter = arraySize; exit loop
{
button[1].update();
if (button[1].pressed())
{
Serial.println("Hard mode selected");
mode = 2;
info[1].ledState = HIGH;
info[0].ledState = LOW;
digitalWrite(info[1].ledPin, info[1].ledState);
digitalWrite(info[0].ledPin, info[0].ledState);
}
theaterChaseRainbow();
RunGame();
}
prepareGame();
}
else if (button[2].pressed()) // Reset button
{
Serial.println("Reset button pressed");
info[2].ledState = !info[2].ledState;
digitalWrite(info[2].ledPin, info[2].ledState);
}
}
}
void AllMagnetsOn() // insert a small delay to give relay unit some time to initialize all relays one at a time to prevent current peak.
{
for (byte i = 0; i < NUM_PIPES; i++)
{
digitalWrite(pipePins[i], !INITIAL_PIPE_STATE);
delay(50);
}
}
void AllMagnetsOff()
{
for (byte i = 0; i < NUM_PIPES; i++)
{
digitalWrite(pipePins[i], INITIAL_PIPE_STATE);
}
}
void RunGame()
{
random(micros());
static unsigned long lastTime = 3000;
static unsigned int nextTime = random(100, 1000);
if ((millis() - lastTime) < (nextTime * Level))
{
return;
}
// select and drop random
randPipe = getRandomEntry();
digitalWrite(randPipe + 2, HIGH); // laat de honden los!
Serial.print("Random delay value: ");
Serial.println(nextTime * Level);
Serial.print("Pipe nr: ");
Serial.print(randPipe);
Serial.print(", Pin nr: ");
Serial.println(randPipe + 2);
Serial.print("Pipe counter value; ");
Serial.print(counter);
Serial.print(", array size; ");
Serial.println(arraySize);
Serial.println();
// schedule
nextTime = random(100, 1000);
lastTime = millis();
counter++; // counts every time a pipe has dropped
}
void prepareGame()
{
// prepare for the game
colorWipeDelay(strip1.Color(255, 50, 0), 100); // Orange
colorWipeDelay(strip2.Color(255, 50, 0), 100); // Orange
colorWipeDelay(strip3.Color(255, 50, 0), 100); // Orange
AllMagnetsOn(); // Alle magneten inschakelen
colorWipeDelay(strip1.Color(0, 255, 0), 100); // Green
colorWipeDelay(strip2.Color(0, 255, 0), 100); // Green
colorWipeDelay(strip3.Color(0, 255, 0), 100); // Green
delay(2000);
colorWipeDelay(strip1.Color(0, 0, 0), 100); // Off
colorWipeDelay(strip2.Color(0, 0, 0), 100); // Off
colorWipeDelay(strip3.Color(0, 0, 0), 100); // Off
}
void rainbow() // modified from Adafruit example to make it a state machine
{
static uint16_t j = 0;
static unsigned long lastUpdate;
if (millis() - lastUpdate < 15)
{
return;
}
for (unsigned int i = 0; i < strip1.numPixels(); i++)
{
strip1.setPixelColor(i, Wheel((i + j) & 255));
strip2.setPixelColor(i, Wheel((i + j) & 255));
strip3.setPixelColor(i, Wheel((i + j) & 255));
}
strip1.show();
strip2.show();
strip3.show();
j++;
if (j >= 256)
{
j = 0;
}
lastUpdate = millis(); // time for next change to the display
}
void rainbowCycle() // modified from Adafruit example to make it a state machine
{
static uint16_t j = 0;
static unsigned long lastUpdate2;
if (millis() - lastUpdate2 < 20)
{
return;
}
for (unsigned int i = 0; i < strip1.numPixels(); i++) // moet dit ook nog worden opgebouwd voor strip 2 en 3?
{
strip1.setPixelColor(i, Wheel(((i * 256 / strip1.numPixels()) + j) & 255));
strip2.setPixelColor(i, Wheel(((i * 256 / strip2.numPixels()) + j) & 255));
strip3.setPixelColor(i, Wheel(((i * 256 / strip3.numPixels()) + j) & 255));
}
strip1.show();
strip2.show();
strip3.show();
j++;
if (j >= 256 * 5)
{
j = 0;
}
lastUpdate2 = millis(); // time for next change to the display
}
void theaterChaseRainbow() // modified from Adafruit example to make it a state machine
{
static int j = 0, q = 0;
static boolean on = true;
static unsigned long lastUpdate3;
if (millis() - lastUpdate3 < 30)
{
return;
}
if (on)
{
for (unsigned int i = 0; i < strip1.numPixels(); i = i + 3) // moet dit ook nog worden opgebouwd voor strip 2 en 3?
{
strip1.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on
strip2.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on
strip3.setPixelColor(i + q, Wheel((i + j) % 255)); // turn every third pixel on
}
}
else
{
for (unsigned int i = 0; i < strip1.numPixels(); i = i + 3)
{
strip1.setPixelColor(i + q, 0); // turn every third pixel off
strip2.setPixelColor(i + q, 0); // turn every third pixel off
strip3.setPixelColor(i + q, 0); // turn every third pixel off
}
}
on = !on; // toggel pixelse on or off for next time
strip1.show(); // display
strip2.show(); // display
strip3.show(); // display
q++; // update the q variable
if (q >= 3) // if it overflows reset it and update the J variable
{
q = 0;
j++;
if (j >= 256)
{
j = 0;
}
}
lastUpdate3 = millis(); // time for next change to the display
}
void colorWipeDelay(uint32_t c, uint8_t wait) // Fill the dots one after the other with a color
{
for (uint16_t i = 0; i < strip1.numPixels(); i++)
{
strip1.setPixelColor(i, c);
strip2.setPixelColor(i, c);
strip3.setPixelColor(i, c);
strip1.show();
strip2.show();
strip3.show();
delay(wait);
}
}
uint32_t Wheel(byte WheelPos)
{
WheelPos = 255 - WheelPos;
if (WheelPos < 85)
{
return strip1.Color(255 - WheelPos * 3, 0, WheelPos * 3);
return strip2.Color(255 - WheelPos * 3, 0, WheelPos * 3);
return strip3.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170)
{
WheelPos -= 85;
return strip1.Color(0, WheelPos * 3, 255 - WheelPos * 3);
return strip2.Color(0, WheelPos * 3, 255 - WheelPos * 3);
return strip3.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip1.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
return strip2.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
return strip3.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}