// https://forum.arduino.cc/t/arduino-uno-project-7-segment-module-3-inch-3-digit-behavior-problem/1444638/27
// #include <Arduino.h>
#include <MD_YX5300.h> // https://github.com/MajicDesigns/MD_YX5300
//Coin input
#define coinPin 10 // Grey jumper wire + Blue long wire
//DC Motor
const int ENA = 5; //PWM pin, blue jumper wire
const int IN1 = 6; //White jumper wire, IN2 pull-down with R 10K
const int stop = 7; //Green jumper wire, limit switch
//Sensor IR
const int activate = 8; //Detects if object is thrown to activate other IR objects, orange jumper wire
const int ir_low = 4; //Score 25, black jumper wire + Blue long wire
const int ir_mid = 3; //Score 50, grey jumper wire + Blue long wire
const int ir_high = 2; //Score 100, white jumper wire + Blue long wire
const byte clk[] = {12, 15, 18}; // score, timer, credit
const byte lat[] = {11, 14, 17}; // score, timer, credit
const byte dat[] = {13, 16, 19}; // score, timer, credit
// const byte u595scor[] = {12, 11, 13}; // clk, lat, dat // Purple jumper wire (mid, score)
// const byte u595time[] = {15, 14, 16}; // clk, lat, dat // Green jumper wire (bottom, timer)
// const byte u595cred[] = {18, 17, 19}; // clk, lat, dat // Orange jumper wire (top, credit)
unsigned int time;
unsigned int credit;
unsigned int insert;
int scores[] = {0, 0, 0};
unsigned int score;
unsigned int total;
const int ticketMotor = 9; //Brown jumper wire + Blue long wire
int tickets[] = {0, 0, 0};
unsigned int ticket;
unsigned int reward;
unsigned int mercy;
const byte binary[] = { // ORIGINAL SEGMENT BIT POSITIONS: bapfgedc
B11111100, // B11010111, //0
B01100000, // B10000001, //1
B11011010, // B11001110, //2
B11110010, // B11001011, //3
B01100110, // B10011001, //4
B10110110, // B01011011, //5
B00111110, // B01011111, //6
B11100000, // B11000001, //7
B11111110, // B11011111, //8
B11110110 // B11011011, //9
};
//Sounds
MD_YX5300 sound(Serial);
//Chance millis
int chance;
unsigned long halt_chance = 250;
unsigned long start_chance = 0;
//IR Sensor millis
unsigned long halt = 2500; //IR sensor got delayed for 2,5s per throw
unsigned long start_low = 0;
unsigned long start_mid = 0;
unsigned long start_high = 0;
//Limit millis
unsigned long limit = 1000; //for 30s time limit
unsigned long start_limit = 0;
//Sound millis
unsigned long halt_coin = 200;
unsigned long start_coin = 0;
unsigned long start_down = 0;
//Refresh millis
unsigned long refresh = 0;
//Start from upper or bottom
bool above = false;
void setup() {
Serial.begin(115200);
//Coin input
pinMode(coinPin, INPUT_PULLUP); //+External pullup
//DC Motor
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(stop, INPUT);
//Sensor IR
pinMode(activate, INPUT); //+External pullup
pinMode(ir_low, INPUT);
pinMode(ir_mid, INPUT);
pinMode(ir_high, INPUT);
for (byte i = 0; i < 3; i++) { // 7 Segment
pinMode(dat[i], OUTPUT);
pinMode(clk[i], OUTPUT);
pinMode(lat[i], OUTPUT);
}
//Ticket Dispenser
pinMode(ticketMotor, OUTPUT);
digitalWrite(ticketMotor, HIGH);
//Sound
sound.begin();
}
void loop() {
digitalWrite(ticketMotor, HIGH);
//Reset
for (byte i = 0; i < 3; i++) {
tickets[i] = 0;
scores[i] = 0;
}
chance = 0;
ticket = 0;
score = 0;
total = 0;
reward = 0;
mercy = 0;
time = 0;
above = false;
Result(3, score);
Timer(3, time);
Play(3, credit);
//DC motor reset
do {
DCUnlock();
} while (digitalRead(stop) == LOW);
if (digitalRead(stop) == HIGH) {
DCStop();
}
//Standby sound
sound.playTrackRepeat(8);
//Coin input
while (true) {
unsigned long current = millis();
if (current - refresh >= 50) {
Result(3, score);
Timer(3, time);
Play(3, credit);
refresh = current;
}
if (digitalRead(coinPin) == LOW) {
Credit();
time = 3;
Timer(3, time);
//Coin sound
sound.playTrack(9);
delay(1000);
}
if (insert > 0) {
insert--;
time = 3;
Timer(3, time);
break;
}
}
//Ready sound
sound.playTrack(1);
while (true) {
//Coin input
unsigned long current = millis();
if (current - start_coin >= halt_coin) {
if (digitalRead(coinPin) == LOW) {
Credit();
start_coin = current;
}
}
//Doll release
if ((digitalRead(ir_low) == LOW) || (digitalRead(ir_mid) == LOW) || (digitalRead(ir_high) == LOW)) {
above = true;
DCUnlock();
}
//DC Stop
if ((digitalRead(ir_low) == HIGH) && (digitalRead(ir_mid) == HIGH) && (digitalRead(ir_high) == HIGH) && (digitalRead(stop) == HIGH)) {
DCStop();
}
//Countdown
if ((current - start_limit >= limit) && (time > 0)) {
time--;
Timer(3, time);
start_limit = current;
}
//Sensor IR (Activator)
if (current - start_chance >= halt_chance) {
//Countermeasure
if ((digitalRead(activate) == LOW) && (time > 0) && (above == false)) {
start_chance = current;
above = true;
}
//Start from above
else if ((above == true) && (digitalRead(activate) == LOW)) {
start_chance = current;
break;
}
//Start from below
else if ((above == false) && (time == 0)) {
break;
}
}
}
//DC Stop
if ((digitalRead(ir_low) == HIGH) && (digitalRead(ir_mid) == HIGH) && (digitalRead(ir_high) == HIGH) && (digitalRead(stop) == HIGH)) {
DCStop();
}
//Game start
time = 30;
Timer(3, time);
//Theme music
sound.playTrackRepeat(2);
//Scoring system
while (chance < 6) {
unsigned long current = millis();
ScoreAdd();
//3 chances for 2 LOW IR sensor activations each throw
if (current - start_chance >= halt_chance) {
if (digitalRead(activate) == LOW) {
start_chance = current;
chance++;
if (chance % 2 == 0) {
sound.playTrackRepeat(2);
}
//Slide whistle down sound
else if (chance % 2 != 0) {
sound.playTrack(3);
}
}
}
//Timer
if ((current - start_limit >= limit) && (time > 0)) {
time--;
Timer(3, time);
start_limit = current;
//Time's up
if (time == 0) {
chance = 6;
//Time up sound
sound.playTrack(6);
delay(500);
}
}
//Coin input
if (current - start_coin >= halt_coin) {
if (digitalRead(coinPin) == LOW) {
Credit();
start_coin = current;
}
}
}
unsigned long current = millis();
//Final score
total = scores[0] + scores[1] + scores[2];
ticket = tickets[0] + tickets[1] + tickets[2];
Result(3, total);
//3 mercy tickets
if (total == 0) {
while (mercy < 3) {
digitalWrite(ticketMotor, LOW);
mercy++;
delay(300);
//Mercy sound
sound.playTrack(10);
if (mercy == 3) {
digitalWrite(ticketMotor, HIGH);
sound.playPause();
}
//Coin input
if (current - start_coin >= halt_coin) {
if (digitalRead(coinPin) == LOW) {
Credit();
start_coin = current;
}
}
}
}
//Ticket dispensing
else {
while (reward < ticket) {
digitalWrite(ticketMotor, LOW);
delay(300);
digitalWrite(ticketMotor, HIGH);
delay(10);
reward++;
//Award sound
sound.playTrack(7);
if (reward == ticket) {
digitalWrite(ticketMotor, HIGH);
sound.playPause();
}
}
//Coin input
if (current - start_coin >= halt_coin) {
if (digitalRead(coinPin) == LOW) {
Credit();
start_coin = current;
}
}
}
credit--;
}
void Credit() {
credit++;
insert++;
Play(3, credit);
//Coin sound
sound.playTrack(9);
}
void DCUnlock() {
digitalWrite(IN1, HIGH);
analogWrite(ENA, 255);
}
void DCStop() {
digitalWrite(IN1, LOW);
}
void Result(byte digit, long number) {
digitalWrite(lat[0], LOW);
DisplayScore(digit, number);
digitalWrite(lat[0], HIGH);
}
void Timer(byte digit2, long s) {
digitalWrite(lat[1], LOW);
DisplayTimer(digit2, s);
digitalWrite(lat[1], HIGH);
}
void Play(byte digit3, long acc) {
digitalWrite(lat[2], LOW);
DisplayCoin(digit3, acc);
digitalWrite(lat[2], HIGH);
}
void DisplayScore(long t_digit, long t_number) {
long temp_number = t_number;
long temp_N = 1;
for (int i = 0; i < t_digit; i = i + 1) {
int print = (temp_number / temp_N) % 10;
temp_N = temp_N * 10;
shiftOut(dat[0], clk[0], LSBFIRST, binary[print]);
}
}
void DisplayTimer(long t_digit2, long t_s) {
long temp_s = t_s;
long temp_N2 = 1;
for (int j = 0; j < t_digit2; j = j + 1) {
int print2 = (temp_s / temp_N2) % 10;
temp_N2 = temp_N2 * 10;
shiftOut(dat[1], clk[1], LSBFIRST, binary[print2]);
}
}
void DisplayCoin(long t_digit3, long t_acc) {
long temp_acc = t_acc;
long temp_N3 = 1;
for (int k = 0; k < t_digit3; k = k + 1) {
int print3 = (temp_acc / temp_N3) % 10;
temp_N3 = temp_N3 * 10;
shiftOut(dat[2], clk[2], LSBFIRST, binary[print3]);
}
}
void ScoreAdd() {
unsigned long current = millis();
if (current - start_low >= halt) {
if (digitalRead(ir_low) == LOW) {
//Score sound effect
sound.playTrack(4);
score = 25;
if (chance < 3) {
scores[0] = 25;
tickets[0] = 2;
}
else if ((chance >= 3) && (chance < 5)) {
scores[1] = 25;
tickets[1] = 2;
}
else {
scores[2] = 25;
tickets[2] = 2;
time = 1;
Timer(3, time);
}
Result(3, score);
start_low = current;
start_down = current;
}
}
if (current - start_mid >= halt) {
if (digitalRead(ir_mid) == LOW) {
//Score sound effect
sound.playTrack(4);
score = 50;
if (chance < 3) {
scores[0] = 50;
tickets[0] = 3;
}
else if ((chance >= 3) && (chance < 5)) {
scores[1] = 50;
tickets[1] = 3;
}
else {
scores[2] = 50;
tickets[2] = 3;
}
Result(3, score);
start_mid = current;
start_down = current;
}
}
if (current - start_high >= halt) {
if (digitalRead(ir_high) == LOW) {
//Score sound effect
sound.playTrack(4);
score = 100;
if (chance < 3) {
scores[0] = 100;
tickets[0] = 4;
}
else if ((chance >= 3) && (chance < 5)) {
scores[1] = 100;
tickets[1] = 4;
}
else {
scores[2] = 100;
tickets[2] = 4;
time = 2;
Timer(3, time);
}
Result(3, score);
start_high = current;
start_down = current;
}
}
//Doll release
if (((digitalRead(ir_low) == LOW) || (digitalRead(ir_mid) == LOW) || (digitalRead(ir_high) == LOW)) && (chance < 5)) {
DCUnlock();
}
//DC Stop
if ((digitalRead(ir_low) == HIGH) && (digitalRead(ir_mid) == HIGH) && (digitalRead(ir_high) == HIGH) && (digitalRead(stop) == HIGH)) {
DCStop();
}
//Slide whistle up sound
if ((current - start_down == 1000) && (chance < 5)) {
sound.playTrack(5);
}
}
void coininput() {
//Coin input occurs five times... use this function
unsigned long current = millis();
if (current - start_coin >= halt_coin) {
if (digitalRead(coinPin) == LOW) {
Credit();
start_coin = current;
}
}
}STOP
IN1
ENA
IR_L
IR_M
IR_H
Activate
COIN
TIXmot