I have an Arduino project (with UNO clone) about an arcade game where the player pushes a doll to collect score with 3 chances and gain tickets based on the total score, the schematic is shown in the following picture:
And here's the sketch (long):
#include <Arduino.h>
#include "MD_YX5300.h"
//Coin input
#define coin 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
//7 Segment Score
//CLK = Blue long wire
//LATCH = Green long wire
//DATA = White long wire
//Purple jumper wire (mid, score)
#define CLK1 12
#define LATCH1 11
#define DATA1 13
//Green jumper wire (bottom, timer)
#define CLK2 15
#define LATCH2 14
#define DATA2 16
//Orange jumper wire (top, credit)
#define CLK3 18
#define LATCH3 17
#define DATA3 19
unsigned int time;
unsigned int credit;
unsigned int insert;
unsigned int score;
unsigned int score1;
unsigned int score2;
unsigned int score3;
unsigned int total;
const byte binary[11] = {
B11010111, //0
B10000001, //1
B11001110, //2
B11001011, //3
B10011001, //4
B01011011, //5
B01011111, //6
B11000001, //7
B11011111, //8
B11011011, //9
};
//Ticket Dispenser
const int motor = 9; //Brown jumper wire + Blue long wire
unsigned int ticket1;
unsigned int ticket2;
unsigned int ticket3;
unsigned int ticket;
unsigned int reward;
unsigned int mercy;
//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(9600);
//Coin input
pinMode(coin, 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);
//7 Segment
pinMode(LATCH1, OUTPUT);
pinMode(CLK1, OUTPUT);
pinMode(DATA1, OUTPUT);
pinMode(LATCH2, OUTPUT);
pinMode(CLK2, OUTPUT);
pinMode(DATA2, OUTPUT);
pinMode(LATCH3, OUTPUT);
pinMode(CLK3, OUTPUT);
pinMode(DATA3, OUTPUT);
//Ticket Dispenser
pinMode(motor, OUTPUT);
digitalWrite(motor, HIGH);
//Sound
sound.begin();
}
void loop() {
digitalWrite(motor, HIGH);
//Reset
chance=0;
score=0;
score1=0;
score2=0;
score3=0;
total=0;
ticket1=0;
ticket2=0;
ticket3=0;
ticket=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(coin)==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(coin)==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(coin)==LOW){
Credit();
start_coin=current;
}
}
}
unsigned long current = millis();
//Final score
total=score1+score2+score3;
ticket=ticket1+ticket2+ticket3;
Result(3,total);
//3 mercy tickets
if(total==0){
while(mercy<3){
digitalWrite(motor, LOW);
mercy++;
delay(300);
//Mercy sound
sound.playTrack(10);
if(mercy==3){
digitalWrite(motor, HIGH);
sound.playPause();
}
//Coin input
if(current-start_coin>=halt_coin){
if(digitalRead(coin)==LOW){
Credit();
start_coin=current;
}
}
}
}
//Ticket dispensing
else{
while(reward<ticket){
digitalWrite(motor, LOW);
delay(300);
digitalWrite(motor, HIGH);
delay(10);
reward++;
//Award sound
sound.playTrack(7);
if(reward==ticket){
digitalWrite(motor, HIGH);
sound.playPause();
}
}
//Coin input
if(current-start_coin>=halt_coin){
if(digitalRead(coin)==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(long digit, long number){
digitalWrite(LATCH1, LOW);
DisplayScore(digit, number);
digitalWrite(LATCH1, HIGH);
}
void Timer(long digit2, long s){
digitalWrite(LATCH2, LOW);
DisplayTimer(digit2, s);
digitalWrite(LATCH2, HIGH);
}
void Play(long digit3, long acc){
digitalWrite(LATCH3, LOW);
DisplayCoin(digit3, acc);
digitalWrite(LATCH3, 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(DATA1, CLK1, 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(DATA2, CLK2, 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(DATA3, CLK3, 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){
score1=25;
ticket1=2;
}
else if((chance>=3) && (chance<5)){
score2=25;
ticket2=2;
}
else{
score3=25;
ticket3=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){
score1=50;
ticket1=3;
}
else if((chance>=3) && (chance<5)){
score2=50;
ticket2=3;
}
else{
score3=50;
ticket3=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){
score1=100;
ticket1=4;
}
else if((chance>=3) && (chance<5)){
score2=100;
ticket2=4;
}
else{
score3=100;
ticket3=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);
}
}
How the sketch/devices work is the following:
- Insert coin.
- Countdown in 3s.
- The DC motor rotates to unlock the doll, sending it rolling to the player.
- The game starts either if the doll crosses the "3x chance" IR sensor below (PIN 8) or if the countdown reaches 0 (in case the doll was already unlocked before inserting coin), with 30s timer.
- The player pushes the doll to the front to gain score (either gaining 100, 50, and 25, from one of the 3 IR sensors in front).
- The game gives 3 chances, each time the doll crosses the chance IR sensor, one chance is used.
- In 1st-2nd chance, when the doll is thrown to the front, the DC motor will spin to unlock the doll and send it back to the player, but after 3rd chance, the DC motor will not spin.
- Afterwards, the score is counted and the ticket dispenser dispenses tickets based on the score.
- Back to insert coin.
The problem is, at first, the 3 7 segment modules all work fine (for years), but recently, their output is now corrupted. Using long wire (for CLK, LATCH, and DATA) is inevitable for them, as they're located in the upper part of the arcade machine with Arduino below. I tested each of the 3 modules individually, and they work fine, but not if mounted in the arcade machine above with long wires connecting them to the Arduino.
I switched to using protected 3 x 1 wire like this for the modules, and using this, there's some improvement, it works fine with 1-2 modules, but it corrupts 2 of the 3 modules if all modules are used. And initially, it runs for a while using 2 modules (only using the score and timer ones), but now, it corrupts the output of 1 module, and the result is the same when I swapped the modules.
Are there any solutions for this? Like, would using shielded twisted wires for each of the modules solve this?
