Circuito Final V1 #include #include #include #define SEND_PIN 2 #define RECEIVE_PIN 4 #define BUTTON_PIN 7 //---------------- MP3 ---------------- SoftwareSerial mp3Serial(10, 11); DFRobotDFPlayerMini mp3; //---------------- CONFIGURAÇÕES ---------------- const unsigned long TEMPO_INICIALIZACAO = 5000; const unsigned long INTERVALO_LEITURA = 10; // Amostragem a cada 10ms const unsigned long COOLDOWN_NOTA = 250; // Tempo mínimo entre notas (ms) const byte LEITURAS_CONFIRMAR_TOQUE = 10; // HIGHs consecutivos para confirmar toque const byte LEITURAS_CONFIRMAR_SOLTA = 5; // LOWs consecutivos para confirmar soltura //---------------- MÚSICAS ---------------- const uint8_t musica1[] = {1,1,2,1,4,3,1,1,2,1,5,4,1,1,8,6,4,3,2,7,7,6,4,5,4}; onst uint8_t musica2[] = {3,3,4,5,5,4,3,2,1,1,2,3,3,2,2,3,3,4,5,5,4,3,2,1,1,2,3,2,1,1}; const uint8_t musica3[] = {1,2,3,4,5,6,7,8,9,10,11,12,13}; const uint8_t musica4[] = {1,2,3,4,6,7}; const uint8_t musica5[] = {1,2,3,4,5,6}; const uint8_t musica6[] = {1}; // Música contínua (pasta 06 / arquivo 001.mp3) const uint8_t musica7[] = {1}; // Música contínua (pasta 07 / arquivo 001.mp3) struct Musica { const uint8_t* notas; uint8_t quantidade; }; Musica musicas[] = { {musica1, sizeof(musica1)}, // Música 1 {musica2, sizeof(musica2)}, // Música 2 {musica3, sizeof(musica3)}, // Música 3 {musica4, sizeof(musica4)}, // Música 4 {musica5, sizeof(musica5)}, // Música 5 {musica6, sizeof(musica6)}, // Música 6 {musica7, sizeof(musica7)} // Música 7 }; const byte TOTAL_MUSICAS = sizeof(musicas) / sizeof(musicas[0]); byte musicaAtual = 0; byte notaAtual = 0; //---------------- CONTROLE DE ESTADO ---------------- byte contadorHigh = 0; byte contadorLow = 0; bool toqueAtivo = false; // Controle de Play/Pause para Músicas Contínuas (Pastas 6 e 7) bool musicaContinuaIniciada = false; bool musicaContinuaTocando = false; unsigned long ultimaLeituraSensor = 0; unsigned long ultimoToqueNota = 0; // Controle do Botão bool estadoAnteriorBotao = HIGH; unsigned long ultimoTempoDebounce = 0; const unsigned long ATRASO_DEBOUNCE = 50; //------------------------------------------------ void tocarNota() { uint8_t arquivo = musicas[musicaAtual].notas[notaAtual]; mp3.playFolder(musicaAtual + 1, arquivo); Serial.print("Tocando pasta "); Serial.print(musicaAtual + 1); Serial.print(" arquivo "); Serial.println(arquivo); notaAtual++; if (notaAtual >= musicas[musicaAtual].quantidade) { notaAtual = 0; } } // Emite o arquivo 001.mp3 da PASTA 08 correspondente ao número da música (1 a 7 vezes) void emitirBips(byte quantidade) { for (byte i = 0; i < quantidade; i++) { mp3.playFolder(8, 1); // Toca Pasta 08, Arquivo 001.mp3 delay(350); // Tempo suficiente para reproduzir o bip inteiro + pausa } } //------------------------------------------------ void setup() { Serial.begin(115200); //---------------- SENSOR ---------------- pinMode(SEND_PIN, OUTPUT); digitalWrite(SEND_PIN, HIGH); pinMode(RECEIVE_PIN, INPUT); //---------------- BOTÃO ---------------- pinMode(BUTTON_PIN, INPUT_PULLUP); //---------------- MP3 ---------------- mp3Serial.begin(9600); if (!mp3.begin(mp3Serial)) { Serial.println("Erro DFPlayer"); while (true); } mp3.volume(25); Serial.println("Aguardando estabilização..."); } //------------------------------------------------ void loop() { if (millis() < TEMPO_INICIALIZACAO) return; unsigned long tempoAtual = millis(); //---------------- BOTÃO (Troca de Música + Bips via DFPlayer) ---------------- bool estadoAtualBotao = digitalRead(BUTTON_PIN); if (estadoAtualBotao != estadoAnteriorBotao) { ultimoTempoDebounce = tempoAtual; } if ((tempoAtual - ultimoTempoDebounce) > ATRASO_DEBOUNCE) { static bool estadoEstavel = HIGH; if (estadoAtualBotao != estadoEstavel) { estadoEstavel = estadoAtualBotao; if (estadoEstavel == LOW) { mp3.pause(); musicaAtual++; if (musicaAtual >= TOTAL_MUSICAS) { musicaAtual = 0; // Volta para a primeira música } notaAtual = 0; // Reseta estados do modo Play/Pause das Músicas Contínuas musicaContinuaIniciada = false; musicaContinuaTocando = false; Serial.print("Nova musica selecionada: "); Serial.println(musicaAtual + 1); // Dispara a quantidade de bips equivalente ao número da nova música selecionada emitirBips(musicaAtual + 1); } } } estadoAnteriorBotao = estadoAtualBotao; //---------------- SENSOR CAPACITIVO ---------------- if (tempoAtual - ultimaLeituraSensor >= INTERVALO_LEITURA) { ultimaLeituraSensor = tempoAtual; int leitura = digitalRead(RECEIVE_PIN); if (leitura == HIGH) { contadorLow = 0; if (contadorHigh < LEITURAS_CONFIRMAR_TOQUE) { contadorHigh++; } } else { contadorHigh = 0; if (contadorLow < LEITURAS_CONFIRMAR_SOLTA) { contadorLow++; } } // --- MÚSICAS CONTÍNUAS (PASTAS 06 E 07): SEGURAR PARA TOCAR / SOLTAR PARA PAUSAR --- if (musicaAtual == 5 || musicaAtual == 6) { if (contadorHigh >= LEITURAS_CONFIRMAR_TOQUE) { if (!musicaContinuaIniciada) { tocarNota(); // Toca o arquivo 001.mp3 da pasta atual (6 ou 7) musicaContinuaIniciada = true; musicaContinuaTocando = true; Serial.println("### MÚSICA CONTÍNUA INICIADA ###"); } else if (!musicaContinuaTocando) { mp3.start(); // Retoma o som de onde parou musicaContinuaTocando = true; Serial.println("### MÚSICA CONTÍNUA RESUMIDA ###"); } } else if (contadorLow >= LEITURAS_CONFIRMAR_SOLTA) { if (musicaContinuaTocando) { mp3.pause(); // Pausa a música ao soltar musicaContinuaTocando = false; Serial.println("### MÚSICA CONTÍNUA PAUSADA ###"); } } } // --- DEMAIS MÚSICAS (1 a 5): MODO NOTA POR NOTA --- else { if (contadorLow >= LEITURAS_CONFIRMAR_SOLTA) { toqueAtivo = false; } if (!toqueAtivo && contadorHigh >= LEITURAS_CONFIRMAR_TOQUE) { if (tempoAtual - ultimoToqueNota >= COOLDOWN_NOTA) { toqueAtivo = true; ultimoToqueNota = tempoAtual; Serial.println("### TOQUE DETECTADO ###"); tocarNota(); } } } } } Circuito Final V2 #include #include #include #include #define SEND_PIN 2 #define RECEIVE_PIN 4 #define BUTTON_PIN 7 //---------------- MP3 ---------------- SoftwareSerial mp3Serial(10, 11); DFRobotDFPlayerMini mp3; //---------------- CONFIGURAÇÕES ---------------- const unsigned long TEMPO_INICIALIZACAO = 5000; const unsigned long INTERVALO_LEITURA = 10; const unsigned long COOLDOWN_NOTA = 250; const byte LEITURAS_CONFIRMAR_TOQUE = 10; const byte LEITURAS_CONFIRMAR_SOLTA = 5; //---------------- MÚSICAS ---------------- const uint8_t musica1[] = { 1,1,2,1,4,3,1,1,2,1,5,4, 1,1,8,6,4,3,2,7,7,6,4,5,4 }; const uint8_t musica2[] = { 3,3,4,5,5,4,3,2,1,1,2,3,3,2,2, 3,3,4,5,5,4,3,2,1,1,2,3,2,1,1 }; const uint8_t musica3[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13 }; const uint8_t musica4[] = { 1,2,3,4,6,7 }; const uint8_t musica5[] = { 1,2,3,4,5,6 }; // Música contínua const uint8_t musica6[] = {1}; const uint8_t musica7[] = {1}; struct Musica { const uint8_t* notas; uint8_t quantidade; }; Musica musicas[] = { {musica1, sizeof(musica1)}, {musica2, sizeof(musica2)}, {musica3, sizeof(musica3)}, {musica4, sizeof(musica4)}, {musica5, sizeof(musica5)}, {musica6, sizeof(musica6)}, {musica7, sizeof(musica7)} }; const byte TOTAL_MUSICAS = sizeof(musicas) / sizeof(musicas[0]); byte musicaAtual = 0; byte notaAtual = 0; //---------------- CONTROLE DE ESTADO ---------------- byte contadorHigh = 0; byte contadorLow = 0; bool toqueAtivo = false; // Controle das músicas contínuas bool musicaContinuaIniciada = false; bool musicaContinuaTocando = false; //---------------- TEMPO ---------------- unsigned long ultimaLeituraSensor = 0; unsigned long ultimoToqueNota = 0; //---------------- BOTÃO ---------------- bool estadoAnteriorBotao = HIGH; unsigned long ultimoTempoDebounce = 0; const unsigned long ATRASO_DEBOUNCE = 50; //------------------------------------------------ // TOCAR NOTA //------------------------------------------------ void tocarNota() { uint8_t arquivo = musicas[musicaAtual].notas[notaAtual]; mp3.playFolder(musicaAtual + 1, arquivo); Serial.print("Tocando pasta "); Serial.print(musicaAtual + 1); Serial.print(" arquivo "); Serial.println(arquivo); notaAtual++; if (notaAtual >= musicas[musicaAtual].quantidade) { notaAtual = 0; } } //------------------------------------------------ // BIPS DE SELEÇÃO //------------------------------------------------ void emitirBips(byte quantidade) { for (byte i = 0; i < quantidade; i++) { mp3.playFolder(8, 1); delay(350); wdt_reset(); } } //------------------------------------------------ // SETUP //------------------------------------------------ void setup() { // Desabilita watchdog durante inicialização wdt_disable(); Serial.begin(115200); //---------------- SENSOR ---------------- pinMode(SEND_PIN, OUTPUT); digitalWrite(SEND_PIN, HIGH); pinMode(RECEIVE_PIN, INPUT); //---------------- BOTÃO ---------------- pinMode(BUTTON_PIN, INPUT_PULLUP); //---------------- MP3 ---------------- mp3Serial.begin(9600); if (!mp3.begin(mp3Serial)) { Serial.println("Erro DFPlayer"); while (true) { delay(100); } } mp3.volume(25); Serial.println("Aguardando estabilização..."); //---------------- WATCHDOG ---------------- // Reinicia o Arduino automaticamente // caso o programa trave por aproximadamente 2 segundos. wdt_enable(WDTO_2S); } //------------------------------------------------ // LOOP //------------------------------------------------ void loop() { // Mantém o watchdog alimentado wdt_reset(); //---------------- TEMPO INICIAL ---------------- if (millis() < TEMPO_INICIALIZACAO) { wdt_reset(); return; } unsigned long tempoAtual = millis(); //---------------- BOTÃO ---------------- bool estadoAtualBotao = digitalRead(BUTTON_PIN); if (estadoAtualBotao != estadoAnteriorBotao) { ultimoTempoDebounce = tempoAtual; } if ((tempoAtual - ultimoTempoDebounce) > ATRASO_DEBOUNCE) { static bool estadoEstavel = HIGH; if (estadoAtualBotao != estadoEstavel) { estadoEstavel = estadoAtualBotao; if (estadoEstavel == LOW) { //---------------- PARAR MÚSICA ATUAL ---------------- mp3.stop(); //---------------- TROCAR MÚSICA ---------------- musicaAtual++; if (musicaAtual >= TOTAL_MUSICAS) { musicaAtual = 0; } notaAtual = 0; //---------------- RESET MODO CONTÍNUO ---------------- musicaContinuaIniciada = false; musicaContinuaTocando = false; Serial.print("Nova musica selecionada: "); Serial.println(musicaAtual + 1); //---------------- BIPS ---------------- emitirBips(musicaAtual + 1); } } } estadoAnteriorBotao = estadoAtualBotao; //---------------- VERIFICAR DFPLAYER ---------------- if (mp3.available()) { uint8_t tipo = mp3.readType(); //---------------- MÚSICA TERMINOU ---------------- if (tipo == DFPlayerPlayFinished) { Serial.println("### DFPLAYER: MUSICA TERMINOU ###"); // Se for música contínua, // marca como finalizada. if (musicaAtual == 5 || musicaAtual == 6) { musicaContinuaIniciada = false; musicaContinuaTocando = false; } } } //---------------- SENSOR ---------------- if (tempoAtual - ultimaLeituraSensor >= INTERVALO_LEITURA) { ultimaLeituraSensor = tempoAtual; int leitura = digitalRead(RECEIVE_PIN); //---------------- CONTAGEM HIGH ---------------- if (leitura == HIGH) { contadorLow = 0; if (contadorHigh < LEITURAS_CONFIRMAR_TOQUE) { contadorHigh++; } } //---------------- CONTAGEM LOW ---------------- else { contadorHigh = 0; if (contadorLow < LEITURAS_CONFIRMAR_SOLTA) { contadorLow++; } } //------------------------------------------------ // MÚSICAS CONTÍNUAS //------------------------------------------------ if (musicaAtual == 5 || musicaAtual == 6) { //---------------- TOQUE ---------------- if (contadorHigh >= LEITURAS_CONFIRMAR_TOQUE) { if (!toqueAtivo) { toqueAtivo = true; //---------------- MÚSICA NUNCA INICIADA // OU TERMINOU ---------------- if (!musicaContinuaIniciada) { tocarNota(); musicaContinuaIniciada = true; musicaContinuaTocando = true; Serial.println( "### MUSICA CONTINUA INICIADA ###" ); } //---------------- MÚSICA PAUSADA ---------------- else if (!musicaContinuaTocando) { mp3.start(); musicaContinuaTocando = true; Serial.println( "### MUSICA CONTINUA RESUMIDA ###" ); } } } //---------------- SOLTOU ---------------- else if (contadorLow >= LEITURAS_CONFIRMAR_SOLTA) { toqueAtivo = false; if (musicaContinuaTocando) { mp3.pause(); musicaContinuaTocando = false; Serial.println( "### MUSICA CONTINUA PAUSADA ###" ); } } } //------------------------------------------------ // MÚSICAS NORMAIS //------------------------------------------------ else { //---------------- SOLTOU ---------------- if (contadorLow >= LEITURAS_CONFIRMAR_SOLTA) { toqueAtivo = false; } //---------------- TOQUE ---------------- if (!toqueAtivo && contadorHigh >= LEITURAS_CONFIRMAR_TOQUE) { if (tempoAtual - ultimoToqueNota >= COOLDOWN_NOTA) { toqueAtivo = true; ultimoToqueNota = tempoAtual; Serial.println( "### TOQUE DETECTADO ###" ); tocarNota(); } } } } // Alimenta novamente o watchdog wdt_reset(); }