Skip to content

feat(buzzer): add buzzer melody example with basic playback#4

Open
DumontALINE wants to merge 6 commits into
mainfrom
feat/buzzer-melody
Open

feat(buzzer): add buzzer melody example with basic playback#4
DumontALINE wants to merge 6 commits into
mainfrom
feat/buzzer-melody

Conversation

@DumontALINE

@DumontALINE DumontALINE commented Apr 20, 2026

Copy link
Copy Markdown

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

  • Add DEMO/buzzer.cpp with buzzer initialization and melody playback
  • Add a Note struct containing frequency and duration fields
  • Add three melodies: happy_sound, sad_sound, and epic_sound as Note arrays
  • Add play_sound() to iterate through notes using tone(), delay(), and noTone() for correct timing
  • Handle silence notes (freq = 0) explicitly by skipping tone() to avoid undefined behavior on some Arduino cores
  • Trigger each melody on a single button press using falling edge detection to prevent looping while the button is held
  • Add Serial.println() output for each button press to help with debugging

Checklist

  • make build passes (PlatformIO)
  • Tested on hardware
  • Commit messages follow conventional commits format

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.cpp implementing setup_buzzer() / loop_buzzer() with three melodies mapped to A/B/MENU buttons.
  • Updated src/main.cpp to 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.

Comment thread SPEAKER/play_melodies.cpp
for (int i = 0; i < size / sizeof(Note); i++)
{
Serial.println("note");
tone(SPEAKER, sound[i].freq, sound[i].time);

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
tone(SPEAKER, sound[i].freq, sound[i].time);
if (sound[i].freq > 0)
{
tone(SPEAKER, sound[i].freq, sound[i].time);
}
else
{
noTone(SPEAKER);
}

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix in commit : 9c9f5c3

Comment thread DEMO/buzzer.cpp Outdated
Serial.println("le son va être jouer");
for (int i = 0; i < size / sizeof(Note); i++)
{
Serial.println("note");

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
Serial.println("note");

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix in commit : 384dc0f

Comment thread DEMO/buzzer.cpp Outdated
{
if (sound != NULL)
{
Serial.println("le son va être jouer");

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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").

Suggested change
Serial.println("le son va être jouer");
Serial.println("Playing sound");

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix in commit d42438c

Comment thread SPEAKER/play_melodies.cpp
Comment on lines +47 to +70
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);
}

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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;

Copilot uses AI. Check for mistakes.
Comment thread SPEAKER/play_melodies.cpp Outdated
Comment on lines +30 to +36
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++)
{

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread SPEAKER/play_melodies.cpp
Comment on lines +15 to +29
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}};

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a test, no need for such a correction.

@Charly-sketch

Copy link
Copy Markdown
Contributor

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

  1. Lien avec l’issue

    • La PR ne contient pas de mention Closes #2.
    • Sans cela, l’issue ne sera pas automatiquement fermée à la merge.
    • Solution : ajouter Closes #2 ou Fixes #2 dans la description de la PR.
  2. Description de la PR

  3. Convention de commit (scope manquant)

    • Le commit n’a pas de scope.

    • Cela compliquera la lecture de l’historique après merge.

    • Solution : utiliser un scope cohérent, par exemple :

      • feat(speaker): add melody example
  4. Terminologie “buzzer” vs “speaker”

    • Dans le reste du projet, on utilise “speaker”.
    • Ici “buzzer” est utilisé.
    • Solution : renommer pour rester cohérent avec le reste du projet (speaker).
      (ça c'est ma faute désolé)
  5. Nom du dossier et du fichier

    • Le nom actuel n’est pas très explicite.

    • Solution :

      • dossier : SPEAKER
      • fichier : quelque chose de plus descriptif, par exemple play_melodies.

Remarques sur le code

  1. Langue des logs et commentaires

    • Les logs et commentaires sont en français et parfois peu précis ("note", "le son va être jouer").

    • Solution :

      • tout passer en anglais,

      • rendre les logs plus utiles, par exemple :

        • "Playing note: freq=440, duration=200ms"
      • éviter les logs trop vagues comme "note".

  2. Utilisation de const

    • Les tableaux de notes ne sont pas déclarés const.

    • Solution :

      • déclarer les mélodies en const pour éviter toute modification accidentelle :

        const Note happy_sound[] = { ... };
  3. Signature de play_sound

    • La fonction prend une taille en octets et recalcul ensuite le nombre d’éléments.

    • Ce n’est pas très clair ni très sûr.

    • Solution :

      • passer directement le nombre d’éléments :

        void play_sound(const Note* sound, size_t note_count)
      • et appeler avec :

        play_sound(happy_sound, sizeof(happy_sound)/sizeof(Note));
  4. Nommage et cohérence

  • Mélange de styles (happy_sound, "Happy sound", "sad_sound"…).

  • Solution :

    • uniformiser le naming (snake_case ou autre, mais cohérent partout),
    • harmoniser les logs avec les noms des fonctions/tableaux.

Process / collaboration

  1. Réponses aux commentaires
  • Pense à toujours expliquer dans les réponses :

    • ce que tu modifies,
    • et pourquoi.
  • Cela facilite énormément la review et la validation.


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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(buzzer): add buzzer melody example with basic playback

3 participants