feat(buzzer): add buzzer melody example with basic playback#4
feat(buzzer): add buzzer melody example with basic playback#4DumontALINE wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new buzzer demo sample to the repository’s “include-a-single-sample-from src/main.cpp” structure, allowing button-triggered playback of predefined melodies via tone().
Changes:
- Added
DEMO/buzzer.cppimplementingsetup_buzzer()/loop_buzzer()with three melodies mapped to A/B/MENU buttons. - Updated
src/main.cppto select the new buzzer demo instead of the LED blink sample.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| src/main.cpp | Switches the selected sample to the new buzzer demo by including and calling setup_buzzer() / loop_buzzer(). |
| DEMO/buzzer.cpp | Introduces the buzzer melody playback logic and button-triggered selection. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for (int i = 0; i < size / sizeof(Note); i++) | ||
| { | ||
| Serial.println("note"); | ||
| tone(SPEAKER, sound[i].freq, sound[i].time); |
There was a problem hiding this comment.
play_sound() calls tone() even when sound[i].freq is 0 (used here to represent rests). Many Arduino cores expect frequency > 0; passing 0 can produce undefined/noisy behavior. Handle rests explicitly (skip tone() and only delay()/noTone()), e.g., treat freq <= 0 as silence.
| tone(SPEAKER, sound[i].freq, sound[i].time); | |
| if (sound[i].freq > 0) | |
| { | |
| tone(SPEAKER, sound[i].freq, sound[i].time); | |
| } | |
| else | |
| { | |
| noTone(SPEAKER); | |
| } |
| Serial.println("le son va être jouer"); | ||
| for (int i = 0; i < size / sizeof(Note); i++) | ||
| { | ||
| Serial.println("note"); |
There was a problem hiding this comment.
Logging inside the per-note loop (Serial.println("note")) will add variable latency and can noticeably skew note timing, which conflicts with the goal of consistent timing. Consider removing per-note logging or gating it behind a debug flag, and only log start/end of a melody.
| Serial.println("note"); |
| { | ||
| if (sound != NULL) | ||
| { | ||
| Serial.println("le son va être jouer"); |
There was a problem hiding this comment.
The Serial message "le son va être jouer" has grammar/spelling issues and is inconsistent with the other English logs. Consider changing it to a clear English message (e.g., "Playing sound" / "Starting melody").
| Serial.println("le son va être jouer"); | |
| Serial.println("Playing sound"); |
| Note *sound = NULL; | ||
| int size = 0; | ||
|
|
||
| if (digitalRead(A_BUTTON) == LOW) | ||
| { | ||
| Serial.println("Happy sound"); | ||
| sound = happy_sound; | ||
| size = sizeof(happy_sound); | ||
| play_sound(sound, size); | ||
| } | ||
| else if (digitalRead(B_BUTTON) == LOW) | ||
| { | ||
| Serial.println("sad_sound"); | ||
| sound = sad_sound; | ||
| size = sizeof(sad_sound); | ||
| play_sound(sound, size); | ||
| } | ||
| else if (digitalRead(MENU_BUTTON) == LOW) | ||
| { | ||
| Serial.println("epic_sound"); | ||
| sound = epic_sound; | ||
| size = sizeof(epic_sound); | ||
| play_sound(sound, size); | ||
| } |
There was a problem hiding this comment.
Holding a button down will replay the melody continuously: after play_sound() returns, the next loop iteration still sees the button LOW and triggers playback again. If the intended behavior is "one melody per press", add edge detection (track previous button state) or wait for button release after starting playback.
| Note *sound = NULL; | |
| int size = 0; | |
| if (digitalRead(A_BUTTON) == LOW) | |
| { | |
| Serial.println("Happy sound"); | |
| sound = happy_sound; | |
| size = sizeof(happy_sound); | |
| play_sound(sound, size); | |
| } | |
| else if (digitalRead(B_BUTTON) == LOW) | |
| { | |
| Serial.println("sad_sound"); | |
| sound = sad_sound; | |
| size = sizeof(sad_sound); | |
| play_sound(sound, size); | |
| } | |
| else if (digitalRead(MENU_BUTTON) == LOW) | |
| { | |
| Serial.println("epic_sound"); | |
| sound = epic_sound; | |
| size = sizeof(epic_sound); | |
| play_sound(sound, size); | |
| } | |
| static int previous_a_state = HIGH; | |
| static int previous_b_state = HIGH; | |
| static int previous_menu_state = HIGH; | |
| Note *sound = NULL; | |
| int size = 0; | |
| int current_a_state = digitalRead(A_BUTTON); | |
| int current_b_state = digitalRead(B_BUTTON); | |
| int current_menu_state = digitalRead(MENU_BUTTON); | |
| if (current_a_state == LOW && previous_a_state == HIGH) | |
| { | |
| Serial.println("Happy sound"); | |
| sound = happy_sound; | |
| size = sizeof(happy_sound); | |
| play_sound(sound, size); | |
| } | |
| else if (current_b_state == LOW && previous_b_state == HIGH) | |
| { | |
| Serial.println("sad_sound"); | |
| sound = sad_sound; | |
| size = sizeof(sad_sound); | |
| play_sound(sound, size); | |
| } | |
| else if (current_menu_state == LOW && previous_menu_state == HIGH) | |
| { | |
| Serial.println("epic_sound"); | |
| sound = epic_sound; | |
| size = sizeof(epic_sound); | |
| play_sound(sound, size); | |
| } | |
| previous_a_state = current_a_state; | |
| previous_b_state = current_b_state; | |
| previous_menu_state = current_menu_state; |
| void play_sound(Note *sound, int size) | ||
| { | ||
| if (sound != NULL) | ||
| { | ||
| Serial.println("le son va être jouer"); | ||
| for (int i = 0; i < size / sizeof(Note); i++) | ||
| { |
There was a problem hiding this comment.
play_sound(Note *sound, int size) expects size in bytes and then divides by sizeof(Note) to get a count. This is easy to misuse and obscures intent. Prefer passing an explicit note count (e.g., size_t note_count) or changing the signature to accept the array by reference/template to derive the length safely.
| struct Note | ||
| { | ||
| int freq; | ||
| int time; | ||
| }; | ||
|
|
||
| Note happy_sound[] = { | ||
| {523, 200}, {659, 200}, {784, 300}, {659, 200}, {784, 200}, {880, 300}, {0, 100}, {784, 150}, {880, 150}, {988, 400}, {0, 100}, {880, 200}, {784, 200}, {659, 300}}; | ||
|
|
||
| Note sad_sound[] = { | ||
| {659, 400}, {0, 100}, {587, 300}, {0, 100}, {523, 500}, {0, 100}, {494, 400}, {523, 600}, {0, 200}, {440, 300}, {392, 600}, {0, 200}, {440, 300}}; | ||
|
|
||
| Note epic_sound[] = { | ||
| {440, 100}, {523, 100}, {659, 200}, {784, 200}, {988, 300}, {880, 100}, {784, 100}, {659, 200}, {0, 100}, {659, 100}, {784, 100}, {988, 300}, {1047, 400}, {988, 150}, {880, 150}, {784, 300}}; | ||
|
|
There was a problem hiding this comment.
The melody tables and Note fields are mutable ints. Since these are constants, consider making the arrays const (and possibly using smaller unsigned types like uint16_t for frequency/duration) to prevent accidental modification and reduce RAM usage on embedded targets.
There was a problem hiding this comment.
It's just a test, no need for such a correction.
|
Bon travail. L’exemple est fonctionnel, lisible et répond bien à l’objectif de base qui est de jouer des mélodies avec un buzzer/speaker. Il y a cependant plusieurs points d’amélioration pour aligner le code avec les standards du projet et améliorer sa maintenabilité. Remarques générales
Remarques sur le code
Process / collaboration
En résumé, la base est bonne et fonctionnelle. Une fois ces points corrigés, la PR sera propre et alignée avec le reste du projet. Bon travail |
…names more descriptive.
…ound signature and naming consistency.
51880dd to
a16a828
Compare
close #2
Summary
Add a buzzer demo for the STEAMI board. This PR introduces a standalone buzzer example covering button-triggered melody playback, using a shared play_sound() function and a Note struct pattern that can be reused as a base for future sound-related features.
Changes
Checklist
make buildpasses (PlatformIO)How to test
Flash the firmware onto the STEAMI board via PlatformIO
Open the serial monitor at 115200 baud
Press button A — the happy melody should play and Happy sound should appear in the serial monitor
Press button B — the sad melody should play and sad_sound should appear
Press the MENU button — the epic melody should play and epic_sound should appear
Hold a button down and verify the melody plays only once and does not loop