From a6c5005eb02f158bb0c9e17ea09b1f1959035b98 Mon Sep 17 00:00:00 2001 From: zzzz Date: Sun, 12 May 2024 19:57:32 +0200 Subject: [PATCH] Better sound, removed potentiometer --- src/SmartSound.cpp | 54 +++++++++++++++++++++++++++++ src/SmartSound.hpp | 20 +++++++++++ src/main.cpp | 38 +++++++-------------- src/main.hpp | 1 + src/nevergonna.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++ src/song.h | 43 ------------------------ 6 files changed, 171 insertions(+), 69 deletions(-) create mode 100644 src/SmartSound.cpp create mode 100644 src/SmartSound.hpp create mode 100644 src/nevergonna.h delete mode 100644 src/song.h diff --git a/src/SmartSound.cpp b/src/SmartSound.cpp new file mode 100644 index 0000000..1701d02 --- /dev/null +++ b/src/SmartSound.cpp @@ -0,0 +1,54 @@ +#include "SmartSound.hpp" +#include "nevergonna.h" + +SmartSound::SmartSound(int buzzerPin) +{ + m_buzzerPin = buzzerPin; +} + +void SmartSound::play(Sound sound, int tempo) +{ + switch (sound) + { + case NeverGonna: + playSound(nevergonna, nevergonna_notes, tempo); + break; + case Bing: + break; + } +} + +void SmartSound::playSound(int melody[], int notes, int tempo) +{ + + // this calculates the duration of a whole note in ms + int wholenote = (60000 * 4) / tempo; + int divider = 0, noteDuration = 0; + + // iterate over the notes of the melody. + // Remember, the array is twice the number of notes (notes + durations) + for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) + { + + // calculates the duration of each note + divider = melody[thisNote + 1]; + if (divider > 0) + { + // regular note, just proceed + noteDuration = (wholenote) / divider; + } + else if (divider < 0) + { + // dotted notes are represented with negative durations!! + noteDuration = (wholenote) / abs(divider); + noteDuration *= 1.5; // increases the duration in half for dotted notes + } + + // we only play the note for 90% of the duration, leaving 10% as a pause + tone(m_buzzerPin, melody[thisNote], noteDuration * 0.9); + // Wait for the specief duration before playing the next note. + delay(noteDuration); + // stop the waveform generation before the next note. + noTone(m_buzzerPin); + } +} \ No newline at end of file diff --git a/src/SmartSound.hpp b/src/SmartSound.hpp new file mode 100644 index 0000000..614df2b --- /dev/null +++ b/src/SmartSound.hpp @@ -0,0 +1,20 @@ +#pragma once +#include +#include "pitches.h" + +class SmartSound +{ +public: + enum Sound { + NeverGonna, + Bing, + }; + +public: + SmartSound(int buzzerPin); + void play(Sound sound, int tempo = 144); + +private: + int m_buzzerPin; + void playSound(int melody[], int notes, int tempo = 114); +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f6d23e6..6ca9534 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,5 @@ #include "main.hpp" #include "secrets.hpp" -#include "song.h" #include #define WIRE Wire @@ -36,6 +35,8 @@ SmartDial smartDial(POTENTIOMETER_PIN); SmartDisplay smartDisplay(&display); TeaNetworking teaNet; +SmartSound sound(BUZZER_PIN); + SmartButton buttonLeft(TACTILE_BTN_LEFT); SmartButton buttonRight(TACTILE_BTN_RIGHT); @@ -122,8 +123,6 @@ void loop() { smartDisplay.printWaitForRFIDScreen(); - // playSong(); - // this blocks execution until a tag has been detected String uid = smartRFID.readTag(); @@ -155,7 +154,7 @@ void loop() } case DISPLAY_SCANNED_TEA_CONFIG: { - int dir = smartDial.smoothEdit(¤tTea.m_steepingSeconds, 0, 6000); + // int dir = smartDial.smoothEdit(¤tTea.m_steepingSeconds, 0, 6000); if (buttonLeft.isJustPressed()) { @@ -165,7 +164,15 @@ void loop() { currentTea.m_steepingSeconds += 10; } - smartDisplay.printTeaConfigScreen(currentTea.m_teaName, currentTea.m_steepingSeconds, dir); + smartDisplay.printTeaConfigScreen(currentTea.m_teaName, currentTea.m_steepingSeconds, 0); + + if (isBtnPressed() && currentTea.m_steepingSeconds <= 0) + { + // rickroll + Serial.println("Easter"); + sound.play(SmartSound::NeverGonna, 155); + break; + } // change state if start pressed if (isBtnPressed()) @@ -201,27 +208,6 @@ void loop() }; } -void playSong() -{ - int size = sizeof(durations) / sizeof(int); - - for (int note = 0; note < size; note++) - { - // to calculate the note duration, take one second divided by the note type. - // e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. - int duration = 1000 / durations[note]; - tone(BUZZER_PIN, melody[note], duration); - - // to distinguish the notes, set a minimum time between them. - // the note's duration + 30% seems to work well: - int pauseBetweenNotes = duration * 1.30; - delay(pauseBetweenNotes); - - // stop the tone playing: - noTone(BUZZER_PIN); - } -} - void toggle_led() { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); diff --git a/src/main.hpp b/src/main.hpp index 7cb8915..fcc0259 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -17,6 +17,7 @@ #include "TeaNetworking.hpp" #include "TeaData.hpp" #include "SmartButton.hpp" +#include "SmartSound.hpp" void playSong(); bool toggle_led(void *); diff --git a/src/nevergonna.h b/src/nevergonna.h new file mode 100644 index 0000000..72a02e4 --- /dev/null +++ b/src/nevergonna.h @@ -0,0 +1,84 @@ +#pragma once +#include "pitches.h" + +// notes of the moledy followed by the duration. +// a 4 means a quarter note, 8 an eighteenth , 16 sixteenth, so on +// !!negative numbers are used to represent dotted notes, +// so -4 means a dotted quarter note, that is, a quarter plus an eighteenth!! +int nevergonna[] = { + + // Never Gonna Give You Up - Rick Astley + // Score available at https://musescore.com/chlorondria_5/never-gonna-give-you-up_alto-sax + // Arranged by Chlorondria + + /* + NOTE_D5, -4, NOTE_E5, -4, NOTE_A4, 4, // 1 + NOTE_E5, -4, NOTE_FS5, -4, NOTE_A5, 16, NOTE_G5, 16, NOTE_FS5, 8, + NOTE_D5, -4, NOTE_E5, -4, NOTE_A4, 2, + NOTE_A4, 16, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 8, NOTE_D5, 16, + NOTE_D5, -4, NOTE_E5, -4, NOTE_A4, 4, // repeat from 1 + NOTE_E5, -4, NOTE_FS5, -4, NOTE_A5, 16, NOTE_G5, 16, NOTE_FS5, 8, + NOTE_D5, -4, NOTE_E5, -4, NOTE_A4, 2, + NOTE_A4, 16, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 8, NOTE_D5, 16, + REST, 4, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_D5, 8, NOTE_E5, 8, NOTE_CS5, -8, + NOTE_B4, 16, NOTE_A4, 2, REST, 4, + + REST, 8, NOTE_B4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 4, NOTE_A4, 8, // 7 + NOTE_A5, 8, REST, 8, NOTE_A5, 8, NOTE_E5, -4, REST, 4, + NOTE_B4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, NOTE_D5, 8, NOTE_E5, 8, REST, 8, + REST, 8, NOTE_CS5, 8, NOTE_B4, 8, NOTE_A4, -4, REST, 4, + REST, 8, NOTE_B4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, NOTE_A4, 4, + NOTE_E5, 8, NOTE_E5, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, 4, REST, 4,*/ + + NOTE_D5, 2, NOTE_E5, 8, NOTE_FS5, 8, NOTE_D5, 8, // 13 + NOTE_E5, 8, NOTE_E5, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, 4, NOTE_A4, 4, + REST, 2, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, + REST, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + + NOTE_E5, -8, NOTE_E5, -8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, -8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, // 18 + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 8, NOTE_A4, 8, NOTE_A4, 8, + NOTE_E5, 4, NOTE_D5, 2, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_A5, 4, NOTE_CS5, 8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, 8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 4, NOTE_A4, 8, // 23 + NOTE_E5, 4, NOTE_D5, 2, REST, 4, /* + REST, 8, NOTE_B4, 8, NOTE_D5, 8, NOTE_B4, 8, NOTE_D5, 8, NOTE_E5, 4, REST, 8, + REST, 8, NOTE_CS5, 8, NOTE_B4, 8, NOTE_A4, -4, REST, 4, + REST, 8, NOTE_B4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, NOTE_A4, 4, + REST, 8, NOTE_A5, 8, NOTE_A5, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, 8, NOTE_D5, 8, + + REST, 8, NOTE_A4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, // 29 + REST, 8, NOTE_CS5, 8, NOTE_B4, 8, NOTE_A4, -4, REST, 4, + NOTE_B4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, NOTE_A4, 4, REST, 8, + REST, 8, NOTE_E5, 8, NOTE_E5, 8, NOTE_FS5, 4, NOTE_E5, -4, + NOTE_D5, 2, NOTE_D5, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, 4, + NOTE_E5, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, 8, NOTE_A4, 8, NOTE_A4, 4, + + REST, -4, NOTE_A4, 8, NOTE_B4, 8, NOTE_CS5, 8, NOTE_D5, 8, NOTE_B4, 8, // 35 + REST, 8, NOTE_E5, 8, NOTE_FS5, 8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_E5, -8, NOTE_E5, -8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, 8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 4, NOTE_A4, 8, + + NOTE_E5, 4, NOTE_D5, 2, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, // 40 + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_A5, 4, NOTE_CS5, 8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, 8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 4, NOTE_A4, 8, + NOTE_E5, 4, NOTE_D5, 2, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, // 45 + NOTE_A5, 4, NOTE_CS5, 8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, 8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 4, NOTE_A4, 8, + NOTE_E5, 4, NOTE_D5, 2, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_FS5, -8, NOTE_FS5, -8, NOTE_E5, -4, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, // 45 + + NOTE_A5, 4, NOTE_CS5, 8, NOTE_D5, -8, NOTE_CS5, 16, NOTE_B4, 8, NOTE_A4, 16, NOTE_B4, 16, NOTE_D5, 16, NOTE_B4, 16, + NOTE_D5, 4, NOTE_E5, 8, NOTE_CS5, -8, NOTE_B4, 16, NOTE_A4, 4, NOTE_A4, 8, + + NOTE_E5, 4, NOTE_D5, 2, REST, 4*/}; + +// sizeof gives the number of bytes, each int value is composed of two bytes (16 bits) +// there are two values per note (pitch and duration), so for each note there are four bytes +int nevergonna_notes = sizeof(nevergonna) / sizeof(nevergonna[0]) / 2; \ No newline at end of file diff --git a/src/song.h b/src/song.h deleted file mode 100644 index 86916be..0000000 --- a/src/song.h +++ /dev/null @@ -1,43 +0,0 @@ -#include "pitches.h" - -int melody[] = { - REST, REST, REST, NOTE_DS4, - NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4, - NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4, - NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4, - NOTE_E4, REST, REST, NOTE_DS4, - - NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4, - NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_G4, NOTE_B4, NOTE_E5, - NOTE_DS5, - NOTE_D5, REST, REST, NOTE_DS4, - NOTE_E4, REST, NOTE_FS4, NOTE_G4, REST, NOTE_DS4, - NOTE_E4, NOTE_FS4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_E4, NOTE_G4, NOTE_B4, - - NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_E4, NOTE_D4, - NOTE_E4, REST, - REST, NOTE_E5, NOTE_D5, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_E4, - NOTE_AS4, NOTE_A4, NOTE_AS4, NOTE_A4, NOTE_AS4, NOTE_A4, NOTE_AS4, NOTE_A4, - NOTE_G4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_E4, NOTE_E4 -}; - -int durations[] = { - 2, 4, 8, 8, - 4, 8, 8, 4, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 2, 16, 16, 16, 16, - 2, 4, 8, 4, - - 4, 8, 8, 4, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 1, - 2, 4, 8, 8, - 4, 8, 8, 4, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - - 2, 16, 16, 16, 16, - 4, 4, - 4, 8, 8, 8, 8, 8, 8, - 16, 8, 16, 8, 16, 8, 16, 8, - 16, 16, 16, 16, 16, 2 -}; \ No newline at end of file