Here is my latest code to copy and paste into the arduino mega . It will change over time. It may also contain features that are not in use yet (and may give the result I though it would. Grok and Chatgtp are great assistants to explain what is going on with it.
This code will work to create a music player .
The name of this code is mega29.
below is the code– Uses Arduino Mega, has 2 dfmini players
*********************************************************************
* PINBALL ARCADE – 4-PLAYER TOURNAMENT EDITION
* Version will automatically show the sketch filename
* NOW WITH FULL PIN → MP3 TRACK MAP AT STARTUP
*********************************************************************/
#include<DFRobotDFPlayerMini.h>
DFRobotDFPlayerMini dfPlayerMusic;
DFRobotDFPlayerMini dfPlayerFX;
constint pinCount = 44;
constintpins[pinCount] = {
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 53
};
constint ledPin = 52;
bool ledShouldBlink = false;
unsignedlong lastBlinkTime = 0;
unsignedlong ledBlinkStartTime = 0;
bool ledState = LOW;
booltriggered[pinCount];
unsignedlonglastTriggerTime[pinCount];
bool musicPlaying = false;
constint originalVolume = 25;
constint totalTracks = 8;
intplaylist[totalTracks];
int currentTrackIndex = 0;
constint busyPin = 53;
constunsignedlong debounceInterval = 80;
constunsignedlong setupDelay = 2000;
bool setupDelayComplete = false;
longplayerScore[5] = {0, 0, 0, 0, 0}; // 1-4 used
int activePlayer = 0;
bool fadingOut = false;
unsignedlong fadeStartTime = 0;
constunsignedlong fadeDuration = 5000;
// ———- COMPLETE STARTUP INFO WITH PIN → MP3 MAP ———-
voidprintStartupInfo() {
Serial.println(F(“”));
Serial.println(F(“╔══════════════════════════════════════════════════════════╗”));
Serial.println(F(“║ PINBALL ARCADE – 4-PLAYER TOURNAMENT EDITION ║”));
Serial.print (F(“║ Version: “));
Serial.print (__FILE__);
Serial.println(F(” ║”));
Serial.println(F(“║ by Zory + Grok ║”));
Serial.println(F(“╚══════════════════════════════════════════════════════════╝”));
Serial.println(F(“”));
Serial.println(F(“CONTROL PINS:”));
Serial.println(F(” Pin 2 → Start New Game / Music”));
Serial.println(F(” Pin 3 → Game Over (5-sec fade + final scores)”));
Serial.println(F(” Pin 46 → PLAYER 4 active”));
Serial.println(F(” Pin 47 → PLAYER 3 active”));
Serial.println(F(” Pin 48 → PLAYER 2 active”));
Serial.println(F(” Pin 49 → PLAYER 1 active”));
Serial.println(F(” Pin 51 → Hurry-Up mode (8-sec LED blink + 10k jackpot on Pin 44)”));
Serial.println(F(” Pin 52 → Hurry-Up LED”));
Serial.println(F(” Pin 53 → DFPlayer BUSY line”));
Serial.println(F(“”));
Serial.println(F(“SCORING PINS → MP3 SOUND FX MAP:”));
Serial.println(F(” Pin | MP3 Track | Points | Notes”));
Serial.println(F(” ——+———–+————+——————“));
// Group 1: Pins 4–12 → tracks 001–009
for (int p = 4; p <= 12; p++) {
int track = p – 3;
Serial.print(F(” “)); Serial.print(p < 10 ? ” ” : “”); Serial.print(p);
Serial.print(F(” | “)); Serial.print(track < 100 ? (track < 10 ? “00” : “0”) : “”); Serial.print(track); Serial.print(F(“.mp3”));
Serial.print(F(” | “));
if (p == 8) Serial.print(F(” +10″));
elseif (p == 9) Serial.print(F(” +100″));
elseSerial.print(F(” +100″));
Serial.println(p == 8 || p == 9 ? F(” Special”) : F(“”));
}
// Group 2: Pins 22–45 → tracks 010–033
for (int p = 22; p <= 45; p++) {
int track = p – 12;
Serial.print(F(” “)); Serial.print(p);
Serial.print(F(” | “)); Serial.print(track < 100 ? “0” : “”); Serial.print(track); Serial.print(F(“.mp3”));
Serial.print(F(” | “));
if (p == 31) Serial.print(F(” +1000″));
elseif (p == 44) Serial.print(F(” +100 / +10k”));
elseSerial.print(F(” +100″));
Serial.println(p == 31 ? F(” Special”) : (p == 44 ? F(” JACKPOT target”) : F(“”)));
}
// Group 3: Pins 50–53
Serial.println(F(” 50 | 035.mp3 | +100″));
Serial.println(F(” 51 | 036.mp3 | Hurry-Up trigger”));
Serial.println(F(” 53 | 038.mp3 | (used as BUSY pin)”));
Serial.println(F(“”));
Serial.println(F(“MUSIC TRACKS (shuffled): 001.mp3 → 008.mp3”));
Serial.println(F(“”));
}
// ———- SHOW ALL 4 SCORES ———-
voidshowAllScores() {
Serial.println(“════════════════════════════════════”);
Serial.print(” PLAYER 1 SCORE: “); Serial.println(playerScore[1]);
Serial.print(” PLAYER 2 SCORE: “); Serial.println(playerScore[2]);
Serial.print(” PLAYER 3 SCORE: “); Serial.println(playerScore[3]);
Serial.print(” PLAYER 4 SCORE: “); Serial.println(playerScore[4]);
Serial.println(“════════════════════════════════════”);
}
// ———- SHOW CURRENT PLAYER ———-
voidshowActivePlayer() {
if (activePlayer >= 1 && activePlayer <= 4) {
Serial.print(“>>> CURRENTLY SCORING: PLAYER “);
Serial.println(activePlayer);
} else {
Serial.println(“>>> NO PLAYER SELECTED <<<“);
}
}
// ———- LED FLASH ———-
voidflashLED(int times, int d = 200) {
for (int i = 0; i < times; i++) {
digitalWrite(ledPin, HIGH); delay(d);
digitalWrite(ledPin, LOW); if (i < times – 1) delay(d);
}
}
// ———- SETUP ———-
voidsetup() {
Serial.begin(9600);
randomSeed(analogRead(0));
pinMode(ledPin, OUTPUT);
for (int i = 0; i < pinCount; i++) pinMode(pins[i], INPUT_PULLUP);
pinMode(busyPin, INPUT);
Serial1.begin(9600);
if (!dfPlayerMusic.begin(Serial1, true, false)) while(1) flashLED(1);
dfPlayerMusic.volume(originalVolume);
Serial2.begin(9600);
if (!dfPlayerFX.begin(Serial2, true, false)) while(1) flashLED(2);
dfPlayerFX.volume(19);
printStartupInfo();
flashLED(5);
shufflePlaylist();
Serial.println(“4-PLAYER SYSTEM READY!”);
showActivePlayer();
showAllScores();
}
// ———- PLAYLIST ———-
voidshufflePlaylist() {
for (int i = 0; i < totalTracks; i++) playlist[i] = i + 1;
for (int i = 0; i < totalTracks; i++) {
int r = random(i, totalTracks);
int temp = playlist[i]; playlist[i] = playlist[r]; playlist[r] = temp;
}
}
voidplayNextTrack() {
if (digitalRead(busyPin) == LOW || currentTrackIndex >= totalTracks) return;
dfPlayerMusic.play(playlist[currentTrackIndex++]);
musicPlaying = true;
}
// ———- FADE OUT ———-
voidstartFadeOutAndGameOver() {
if (fadingOut) return;
fadingOut = true;
fadeStartTime = millis();
Serial.println(“Pin 3 → GAME OVER! Fading music…”);
}
voidupdateFadeOut() {
if (!fadingOut) return;
unsignedlong elapsed = millis() – fadeStartTime;
if (elapsed >= fadeDuration) {
dfPlayerMusic.stop();
musicPlaying = false;
fadingOut = false;
Serial.println(“════════════════════════════════════”);
Serial.println(” FINAL SCORES”);
Serial.print(” PLAYER 1: “); Serial.println(playerScore[1]);
Serial.print(” PLAYER 2: “); Serial.println(playerScore[2]);
Serial.print(” PLAYER 3: “); Serial.println(playerScore[3]);
Serial.print(” PLAYER 4: “); Serial.println(playerScore[4]);
Serial.println(“════════════════════════════════════”);
Serial.println(“All scores reset!”);
for (int i = 1; i <= 4; i++) playerScore[i] = 0;
activePlayer = 0;
showActivePlayer();
} else {
int vol = originalVolume * (fadeDuration – elapsed) / fadeDuration;
dfPlayerMusic.volume(max(vol, 0));
}
}
// ———- FX MAP ———-
intpinToFxTrack(int pin) {
if (pin >= 4 && pin <= 12) return pin – 3;
if (pin >= 22 && pin <= 45) return pin – 12;
if (pin >= 46 && pin <= 53) return pin – 15;
return1;
}
// ———- ADD POINTS ———-
voidaddPoints(int points, constchar* msg = “”) {
if (activePlayer >= 1 && activePlayer <= 4) {
playerScore[activePlayer] += points;
Serial.print(“P”); Serial.print(activePlayer); Serial.print(” “);
Serial.print(msg); Serial.print(” +”); Serial.print(points);
Serial.print(” → “); Serial.println(playerScore[activePlayer]);
} else {
Serial.println(“NO PLAYER ACTIVE – points ignored!”);
}
}
// ———- MAIN LOOP ———-
voidloop() {
unsignedlong now = millis();
if (!setupDelayComplete && now >= setupDelay) { dfPlayerMusic.stop(); setupDelayComplete = true; }
if (!setupDelayComplete) return;
updateFadeOut();
for (int i = 0; i < pinCount; i++) {
int pin = pins[i];
int state = digitalRead(pin);
if (state == LOW && !triggered[i] && (now – lastTriggerTime[i] >= debounceInterval)) {
triggered[i] = true;
lastTriggerTime[i] = now;
if (pin == 49 && activePlayer != 1) { activePlayer = 1; Serial.println(“\n>>> NOW PLAYING: PLAYER 1 <<<“); showActivePlayer(); showAllScores(); }
elseif (pin == 48 && activePlayer != 2) { activePlayer = 2; Serial.println(“\n>>> NOW PLAYING: PLAYER 2 <<<“); showActivePlayer(); showAllScores(); }
elseif (pin == 47 && activePlayer != 3) { activePlayer = 3; Serial.println(“\n>>> NOW PLAYING: PLAYER 3 <<<“); showActivePlayer(); showAllScores(); }
elseif (pin == 46 && activePlayer != 4) { activePlayer = 4; Serial.println(“\n>>> NOW PLAYING: PLAYER 4 <<<“); showActivePlayer(); showAllScores(); }
elseif (pin == 2) {
if (digitalRead(busyPin) == HIGH && !fadingOut) {
Serial.println(“Pin 2 → Starting music”);
dfPlayerMusic.volume(originalVolume);
currentTrackIndex = 0;
shufflePlaylist();
playNextTrack();
}
}
elseif (pin == 3) startFadeOutAndGameOver();
else {
dfPlayerFX.play(pinToFxTrack(pin));
if (pin == 8) addPoints(10, “Score”);
elseif (pin == 9) addPoints(100, “Score”);
elseif (pin == 31) addPoints(1000, “Score”);
elseif (pin == 44) addPoints(ledShouldBlink ? 10000 : 100, ledShouldBlink ? “JACKPOT” : “Score”);
elseaddPoints(100, “Hit”);
}
if (pin == 51) {
Serial.println(“Pin 51 → Hurry-Up ON”);
ledShouldBlink = true;
ledBlinkStartTime = now;
}
}
if (state == HIGH) triggered[i] = false;
}
if (ledShouldBlink && now – lastBlinkTime >= 100) {
lastBlinkTime = now;
ledState = !ledState;
digitalWrite(ledPin, ledState);
if (now – ledBlinkStartTime > 8000) {
ledShouldBlink = false;
digitalWrite(ledPin, LOW);
Serial.println(“Hurry-Up ended.”);
}
}
staticbool wasBusy = false;
bool isBusy = (digitalRead(busyPin) == LOW);
if (musicPlaying && wasBusy && !isBusy && !fadingOut) {
Serial.println(“Track ended → Playing next”);
playNextTrack();
}
wasBusy = isBusy;
}