Skip to content
Snippets Groups Projects
Commit 4a58113a authored by Anders Kattrup Noesgaard's avatar Anders Kattrup Noesgaard
Browse files

initial

parents
No related branches found
No related tags found
No related merge requests found
// ==========
// PROGRAM
// ==========
#include <EEPROM.h> // Be able to save variable to memory
boolean reciting = false;
boolean successfullRecitement = false;
# define SEQUENCE_MAX_LENGTH 18 // Max out at 16 hits per sequence
int sayingSequence[SEQUENCE_MAX_LENGTH];
int sayingLength = 1;
int recitementStep = 0;
int DIFFICULTY_DELAY = 1000;
int DIFFICULTY_HARD = 750;
int DIFFICULTY_EASY = 1500;
int toggleDifficultyPin = 12;
int startNewGamePin = 13;
// ==========
// PIEZO
// ==========
int sensorIn1 = A0;
int sensorIn2 = A1;
int sensorIn3 = A2;
int sensorIn4 = A3;
int THRESHOLD = 150;
// ==========
// LED
// ==========
#include <FastLED.h>
#define NUM_LEDS 36 // How many LED's in total?
CRGB leds[NUM_LEDS];
#define LED_PIN 3
int BRIGHTNESS = 20;
// Define LEDs for each symbol
int LEDone[] = {0, 1, 2, 21, 22, 23, 24, 25, 26}; // Circle
int LEDtwo[] = {3, 4, 5, 18, 19, 20, 27, 28, 29}; // Triangle
int LEDthree[] = {6, 7, 8, 15, 16, 17, 30, 31, 32}; // Octagon
int LEDfour[] = {9, 10, 11, 12, 13, 14, 33, 34, 35}; // X
// ==========
// STEPPERMOTOR
// ==========
#include <Stepper.h>
#define stepsPerRevolution 800
#define STEP_SIZE 100
#define MAX_STEPS 18 // Maximum number of steps our product can handle
Stepper stepper(stepsPerRevolution, 8, 6, 7, 5);
int stepsTaken = 0;
int SPEED = 5;
// When stepping, negative is up and positive is down.
// ==========
// SPEAKER
// ==========
#include "SoftwareSerial.h"
int RX = 11;
int TX = 10;
SoftwareSerial mySerial(TX, RX);
# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
# define ACTIVATED LOW
int VOLUME = 30; // interval (0-30)
// ============================================================
void setup() {
Serial.begin(9600);
// Switch and button
pinMode(toggleDifficultyPin, INPUT_PULLUP);
pinMode(startNewGamePin, INPUT_PULLUP);
// Provide random seed
randomSeed(analogRead(A4) ^ analogRead(A5)); // A4 and A5 are unconnected, giving random fluctuations as electrical noise
// Setups
setupPiezo();
setupLED();
setupStepmotor();
setupSpeaker();
}
void loop() {
// In state of user reciting what Simon said
if(reciting) {
int hit = getHitDrum();
// Is hit?
if(hit != -1) {
// Good hit?
if(isHitCorrect(hit)) {
recitementStep++;
showLED(hit);
delay(200);
hideAllLEDs();
// Reciting done?
if(recitementStep >= sayingLength) {
reciting = false;
successfullRecitement = true;
pause();
stepOne();
delay(DIFFICULTY_DELAY);
}
} else { // Bad hit, reciting ends
reciting = false;
successfullRecitement = false;
pause();
// FLash error indication
showErrorLED();
delay(250);
hideAllLEDs();
delay(250);
showErrorLED();
delay(250);
hideAllLEDs();
}
}
}
// In state of Simon saying
if(!reciting) {
if(successfullRecitement) { // Continuing game
sayingLength++;
} else { // Starting new game
sayingLength = 1;
resetStepperMotor();
turnOnAllLEDs();
// Clause to interrupt starting of new game until button has been pressed
boolean readyToStartGame = false;
while(!readyToStartGame) {
if(digitalRead(startNewGamePin) == LOW) {
readyToStartGame = true;
hideAllLEDs();
}
delay(100); // Infitie while loop a little eco friendly ;)
}
delay(400); // Wait a little before starting game
// Choose difficulty
int difficulty = digitalRead(toggleDifficultyPin);
if (difficulty == HIGH) {
DIFFICULTY_DELAY = DIFFICULTY_HARD;
showDifficulty(true);
} else {
DIFFICULTY_DELAY = DIFFICULTY_EASY;
showDifficulty(false);
}
}
generateRecitement(sayingLength);
showSayingSequence();
// Continue playing music if continuing game, start music over if start of game
if(successfullRecitement) {
play();
} else {
playFirst();
}
reciting = true;
successfullRecitement = false;
recitementStep = 0;
}
}
// ==========
// PROGRAM FUNCTION
// ==========
// Generate a simon says sequence of given length
void generateRecitement(int length) {
// Reset sequence
for(int i = 0; i < SEQUENCE_MAX_LENGTH; i++) {
sayingSequence[i] = -1;
}
// Update length of sequence
sayingLength = length;
// Create sequence
for(int i = 0; i < sayingLength; i++) {
int randomNumber = random(4);
sayingSequence[i] = randomNumber;
}
}
// Show the sequence saved in memory
void showSayingSequence() {
hideAllLEDs();
for(int i = 0; i < sayingLength; i++) {
i == 0 ? delay(250) : delay(DIFFICULTY_DELAY);
showLED(sayingSequence[i]);
delay(DIFFICULTY_DELAY);
hideAllLEDs();
}
}
// Which drum is hit?
// Returns index 0-3 (-1, if no hit)
int getHitDrum() {
int readings[4];
getPiezoReadings(readings);
// Get max value
int maxReading = 0;
int indexOfMaxReading = -1;
for (int i = 0; i < 4; i++) {
if (readings[i] > maxReading) {
maxReading = readings[i];
indexOfMaxReading = i;
}
}
// Above threshold?
if(maxReading < THRESHOLD) {
return -1;
}
Serial.println("Max reading on: "); Serial.println(indexOfMaxReading);
return indexOfMaxReading;
}
// Is a given hit correct?
boolean isHitCorrect(int hitDrum) {
if(sayingSequence[recitementStep] == hitDrum) {
return true;
}
return false;
}
// ==========
// LED FUNCTIONS
// ==========
// Turn off every LED
void hideAllLEDs() {
for(int i = 0; i < NUM_LEDS; i++) {
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 0;
}
FastLED.setBrightness(0);
FastLED.show();
}
// Turn on every LED to white
void turnOnAllLEDs() {
for(int i = 0; i < NUM_LEDS; i++) {
leds[i].r = 100;
leds[i].g = 100;
leds[i].b = 100;
}
FastLED.setBrightness(BRIGHTNESS);
FastLED.show();
}
// Show warning of the difficulty chosen
void showDifficulty(boolean hard) {
int times = hard ? 2 : 1;
for(int j = 0; j < times; j++) {
for(int i = 0; i < NUM_LEDS; i++) {
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 100;
}
FastLED.setBrightness(BRIGHTNESS);
FastLED.show();
delay(500);
hideAllLEDs();
delay(250);
}
}
// Show a given part of the led Array (parameter 0-3)
void showLED(int ledNumber) {
if(ledNumber < 0 || ledNumber > 3) {
// FAILURE
return;
}
int* ledArray; // Pointer to hold the correct LED array
int sizeOfArray = 0; // To store the size of the selected LED array
// Select the appropriate LED array and calculate its size
if (ledNumber == 0) { // Circle - green
ledArray = LEDone;
sizeOfArray = sizeof(LEDone) / sizeof(LEDone[0]);
for (int i = 0; i < sizeOfArray; i++) {
int led = ledArray[i];
leds[led].r = 100;
leds[led].g = 0;
leds[led].b = 0;
}
} else if (ledNumber == 1) { // Triangle - blue
ledArray = LEDtwo;
sizeOfArray = sizeof(LEDtwo) / sizeof(LEDtwo[0]);
for (int i = 0; i < sizeOfArray; i++) {
int led = ledArray[i];
leds[led].r = 0;
leds[led].g = 0;
leds[led].b = 100;
}
} else if (ledNumber == 2) { // Octagon - red
ledArray = LEDthree;
sizeOfArray = sizeof(LEDthree) / sizeof(LEDthree[0]);
for (int i = 0; i < sizeOfArray; i++) {
int led = ledArray[i];
leds[led].r = 0;
leds[led].g = 100;
leds[led].b = 0;
}
} else if (ledNumber == 3) { // X - yellow
ledArray = LEDfour;
sizeOfArray = sizeof(LEDfour) / sizeof(LEDfour[0]);
for (int i = 0; i < sizeOfArray; i++) {
int led = ledArray[i];
leds[led].r = 100;
leds[led].g = 100;
leds[led].b = 0;
}
}
FastLED.setBrightness(BRIGHTNESS);
FastLED.show();
}
void showErrorLED() {
for(int i = 0; i < NUM_LEDS; i++) {
// Red for some reason...
leds[i].r = 0;
leds[i].g = 100;
leds[i].b = 0;
}
FastLED.setBrightness(BRIGHTNESS);
FastLED.show();
}
// ==========
// STEPPER MOTOR FUNCTIONS
// ==========
// Reset to default/starting position
void resetStepperMotor() {
int sizeToStep = STEP_SIZE * stepsTaken;
stepper.step(sizeToStep);
stepsTaken = 0;
EEPROM.write(0, stepsTaken);
}
// Take on step forwards
void stepOne() {
if(stepsTaken < MAX_STEPS) {
stepper.step(-1 * STEP_SIZE);
stepsTaken++;
EEPROM.write(0, stepsTaken);
}
}
// ==========
// SPEAKER FUNCTIONS
// ==========
// Restart the first song
void playFirst() {
execute_CMD(0x3F, 0, 0);
delay(500);
execute_CMD(0x11,0,1);
delay(250);
}
// Pause
void pause() {
execute_CMD(0x0E,0,0);
delay(250);
}
// Play from paused state
void play() {
execute_CMD(0x0D,0,1);
delay(250);
}
// Set volumne
void setVolume(int volume) {
execute_CMD(0x06, 0, volume); // Set the volume (0x00~0x30)
delay(1000);
}
// Execute a command on the DFPlayer
void execute_CMD(byte CMD, byte Par1, byte Par2) {
// Excecute the command and parameters
// Calculate the checksum (2 bytes)
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Build the command line
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};
//Send the command line to the module
for (byte k=0; k<10; k++) {
mySerial.write( Command_line[k]);
}
}
// ==========
// PIEZO FUNCTIONS
// ==========
void getPiezoReadings(int values[4]) {
values[0] = analogRead(sensorIn1);
values[1] = analogRead(sensorIn2);
values[2] = analogRead(sensorIn3);
values[3] = analogRead(sensorIn4);
Serial.print("Piezo values: ");
Serial.print(values[0]); Serial.print(", ");
Serial.print(values[1]); Serial.print(", ");
Serial.print(values[2]); Serial.print(", ");
Serial.print(values[3]);
Serial.println();
}
// ==========
// SETUPS
// ==========
void setupPiezo() {
// No specific setup needed
}
void setupLED() {
FastLED.addLeds<WS2812B, LED_PIN, RGB> (leds, NUM_LEDS);
for(int i = 0; i < NUM_LEDS; i++) {
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 0;
}
FastLED.setBrightness(0);
FastLED.show();
}
void setupStepmotor() {
stepper.setSpeed(SPEED);
// Steps taken are saved in memory
if(EEPROM.read(0) != 0xFF) {
stepsTaken = EEPROM.read(0);
}
// Motor should be absolutely reset on each start-up
resetStepperMotor();
}
void setupSpeaker() {
mySerial.begin(9600);
setVolume(VOLUME);
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment