|
| 1 | +// Circuit Playground Birthday Candles |
| 2 | +// |
| 3 | +// All the NeoPixels will flicker like candles and the speaker will |
| 4 | +// play the tune to Happy Birthday continuously. Blow on the board |
| 5 | +// to slowly blow out all the candles and hear a victory song! |
| 6 | +// Controls: |
| 7 | +// - Slide switch: Move this to +/on to hear music or -/off to disable sound. |
| 8 | +// - Left button: Hold this down and press reset to use a rainbow flicker color. |
| 9 | +// - Right button: Hold this down and press reset to use a simple solid color (no flicker). |
| 10 | +// - If neither left or right button are pressed at startup then a flame-like |
| 11 | +// flickering animation will be used. |
| 12 | +// After all the candles are blown out press reset to reset and start over! |
| 13 | +// |
| 14 | +// Author: Tony DiCola |
| 15 | +// License: MIT (https://opensource.org/licenses/MIT) |
| 16 | + |
| 17 | +#include <Arduino.h> |
| 18 | + |
| 19 | +// PIN_BUZZER should be defined by the supported variant e.g CPlay Bluefruit or CLUE. |
| 20 | +// Otherwise please define the pin you would like to use for tone output |
| 21 | +#ifndef PIN_BUZZER |
| 22 | +#define PIN_BUZZER 5 |
| 23 | +#endif |
| 24 | + |
| 25 | + |
| 26 | +// A few music note frequencies as defined in this tone example: |
| 27 | +// https://www.arduino.cc/en/Tutorial/toneMelody |
| 28 | +#define NOTE_C4 262 |
| 29 | +#define NOTE_CS4 277 |
| 30 | +#define NOTE_D4 294 |
| 31 | +#define NOTE_DS4 311 |
| 32 | +#define NOTE_E4 330 |
| 33 | +#define NOTE_F4 349 |
| 34 | +#define NOTE_FS4 370 |
| 35 | +#define NOTE_G4 392 |
| 36 | +#define NOTE_GS4 415 |
| 37 | +#define NOTE_A4 440 |
| 38 | +#define NOTE_AS4 466 |
| 39 | +#define NOTE_B4 494 |
| 40 | +#define NOTE_C5 523 |
| 41 | +#define NOTE_CS5 554 |
| 42 | +#define NOTE_D5 587 |
| 43 | +#define NOTE_DS5 622 |
| 44 | +#define NOTE_E5 659 |
| 45 | +#define NOTE_F5 698 |
| 46 | +#define NOTE_FS5 740 |
| 47 | +#define NOTE_G5 784 |
| 48 | +#define NOTE_GS5 831 |
| 49 | +#define NOTE_A5 880 |
| 50 | +#define NOTE_AS5 932 |
| 51 | +#define NOTE_B5 988 |
| 52 | + |
| 53 | +// Define note durations. You only need to adjust the whole note |
| 54 | +// time and other notes will be subdivided from it directly. |
| 55 | +#define WHOLE 2200 // Length of time in milliseconds of a whole note (i.e. a full bar). |
| 56 | +#define HALF WHOLE/2 |
| 57 | +#define QUARTER HALF/2 |
| 58 | +#define EIGHTH QUARTER/2 |
| 59 | +#define EIGHTH_TRIPLE QUARTER/3 |
| 60 | +#define SIXTEENTH EIGHTH/2 |
| 61 | + |
| 62 | +// Play a note of the specified frequency and for the specified duration. |
| 63 | +// Hold is an optional bool that specifies if this note should be held a |
| 64 | +// little longer, i.e. for eigth notes that are tied together. |
| 65 | +// While waiting for a note to play the waitBreath delay function is used |
| 66 | +// so breath detection and pixel animation continues to run. No tones |
| 67 | +// will play if the slide switch is in the -/off position or all the |
| 68 | +// candles have been blown out. |
| 69 | +void playNote(int frequency, int duration, bool hold=false, bool measure=true) { |
| 70 | + (void) measure; |
| 71 | + |
| 72 | + if (hold) { |
| 73 | + // For a note that's held play it a little longer than the specified duration |
| 74 | + // so it blends into the next tone (but there's still a small delay to |
| 75 | + // hear the next note). |
| 76 | + tone(PIN_BUZZER, frequency, duration + duration/32); |
| 77 | + } |
| 78 | + else { |
| 79 | + // For a note that isn't held just play it for the specified duration. |
| 80 | + tone(PIN_BUZZER, frequency, duration); |
| 81 | + } |
| 82 | + |
| 83 | + delay(duration + duration/16); |
| 84 | +} |
| 85 | + |
| 86 | +// Song to play when the candles are blown out. |
| 87 | +void celebrateSong() { |
| 88 | + // Play a little charge melody, from: |
| 89 | + // https://en.wikipedia.org/wiki/Charge_(fanfare) |
| 90 | + // Note the explicit boolean parameters in particular the measure=false |
| 91 | + // at the end. This means the notes will play without any breath measurement |
| 92 | + // logic. Without this false value playNote will try to keep waiting for candles |
| 93 | + // to blow out during the celebration song! |
| 94 | + playNote(NOTE_G4, EIGHTH_TRIPLE, true, false); |
| 95 | + playNote(NOTE_C5, EIGHTH_TRIPLE, true, false); |
| 96 | + playNote(NOTE_E5, EIGHTH_TRIPLE, false, false); |
| 97 | + playNote(NOTE_G5, EIGHTH, true, false); |
| 98 | + playNote(NOTE_E5, SIXTEENTH, false); |
| 99 | + playNote(NOTE_G5, HALF, false); |
| 100 | +} |
| 101 | + |
| 102 | +void setup() { |
| 103 | + // Initialize serial output and Circuit Playground library. |
| 104 | + Serial.begin(115200); |
| 105 | + |
| 106 | + pinMode(PIN_BUZZER, OUTPUT); |
| 107 | + digitalWrite(PIN_BUZZER, LOW); |
| 108 | +} |
| 109 | + |
| 110 | +void loop() { |
| 111 | + // Play happy birthday tune, from: |
| 112 | + // http://www.irish-folk-songs.com/happy-birthday-tin-whistle-sheet-music.html#.WXFJMtPytBw |
| 113 | + // Inside each playNote call it will play a note and drive the NeoPixel animation |
| 114 | + // and check for a breath against the sound sensor. Once all the candles are blown out |
| 115 | + // the playNote calls will stop playing music. |
| 116 | + playNote(NOTE_D4, EIGHTH, true); |
| 117 | + playNote(NOTE_D4, EIGHTH); |
| 118 | + playNote(NOTE_E4, QUARTER); // Bar 1 |
| 119 | + playNote(NOTE_D4, QUARTER); |
| 120 | + playNote(NOTE_G4, QUARTER); |
| 121 | + playNote(NOTE_FS4, HALF); // Bar 2 |
| 122 | + playNote(NOTE_D4, EIGHTH, true); |
| 123 | + playNote(NOTE_D4, EIGHTH); |
| 124 | + playNote(NOTE_E4, QUARTER); // Bar 3 |
| 125 | + playNote(NOTE_D4, QUARTER); |
| 126 | + playNote(NOTE_A4, QUARTER); |
| 127 | + playNote(NOTE_G4, HALF); // Bar 4 |
| 128 | + playNote(NOTE_D4, EIGHTH, true); |
| 129 | + playNote(NOTE_D4, EIGHTH); |
| 130 | + playNote(NOTE_D5, QUARTER); // Bar 5 |
| 131 | + playNote(NOTE_B4, QUARTER); |
| 132 | + playNote(NOTE_G4, QUARTER); |
| 133 | + playNote(NOTE_FS4, QUARTER); // Bar 6 |
| 134 | + playNote(NOTE_E4, QUARTER); |
| 135 | + playNote(NOTE_C5, EIGHTH, true); |
| 136 | + playNote(NOTE_C5, EIGHTH); |
| 137 | + playNote(NOTE_B4, QUARTER); // Bar 7 |
| 138 | + playNote(NOTE_G4, QUARTER); |
| 139 | + playNote(NOTE_A4, QUARTER); |
| 140 | + playNote(NOTE_G4, HALF); // Bar 8 |
| 141 | + |
| 142 | + celebrateSong(); |
| 143 | + |
| 144 | + // One second pause before repeating the loop and playing |
| 145 | + delay(1000); |
| 146 | +} |
0 commit comments