Skip to content
Arduino UNO:Coffin Dance
📆2020-07-17 | 📂Embedded

其實原曲名叫Astronomia啊,只是被幾位知名舞者(?)給抬出名了。


看到Arduino範例程式的toneMelody發出了一段像是gameover的音效,我就想讓蜂鳴器播放這段相當知名的迷因歌曲🤣

蜂鳴器分為有(震盪)源蜂鳴器,和無(震盪)源蜂鳴器,有源蜂鳴器就是高電位逼逼叫,低電位不叫,就這樣。而無源的蜂鳴器就好玩了,可以控制其聲音頻率而產生音調高低。

Music Scales

參考範例程式中所引入的pitches.h檔案內容:

c
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294

這個.h檔即是定義唱名所對應的聲音頻率(Hz),其中C4就是鋼琴琴鍵的中央C,亦即C大調的低音Do。如此一來只要有簡譜,像我這樣對樂理沒輒的人也能教Arduino怎麼演奏音樂了呢。

LCD Screen

然後我想用個LCD在旁邊顯示播放的曲名,參考GTW的教學解決了我在編譯時發生的找不到函式庫的問題。要使用HD44780U 1602 LCD須安裝LiquidCrystal library,下載後解壓縮到Arduino的libraries資料夾底下即可。但這邊又有個小問題:

shell
Arduino:1.8.13 (Mac OS X), 開發板:"Arduino Uno"
/Users/nick/Documents/Arduino/libraries/LiquidCrystal/I2CIO.cpp:35:10: fatal error: ../Wire/Wire.h: No such file or directory
 #include <../Wire/Wire.h>

這就要找到剛剛解壓縮的資料夾中的I2CIO.cpp,將#include <../Wire/Wire.h>改為#include <Wire.h>。

*1602 LCD的pin腳說明與像素點控制等教學:Interfacing 16×2 Character LCD Module with Arduino

Play Music!

經過強迫症似的反覆聆聽和調整節拍,我覺得很接近原曲了😆

c
#include <LiquidCrystal_I2C.h>
#include "pitches.h"

#define PIN_BUZ 8

// Ref. https://youtu.be/miwoTFkiIfQ
int melody[] = {
    NOTE_AS4, NOTE_AS4, NOTE_AS4, NOTE_AS4,
    NOTE_D5, NOTE_D5, NOTE_D5, NOTE_D5,
    NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5,
    NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,
    NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5,
    NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5, NOTE_G5,
    NOTE_C5, NOTE_AS4, NOTE_A4, NOTE_G4,
    NOTE_G4, 0, NOTE_G4, NOTE_D5, NOTE_C5, NOTE_AS4, NOTE_A4, NOTE_A4, NOTE_A4,
    NOTE_C5, NOTE_AS4, NOTE_A4, NOTE_G4, NOTE_G4, NOTE_G4,
    NOTE_AS5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_AS5, NOTE_G4,
    NOTE_AS5, NOTE_A5, NOTE_AS5, NOTE_A5, NOTE_AS5, NOTE_G4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
byte noteDurations[] = {
    5, 5, 5, 5,
    5, 5, 5, 5,
    5, 5, 5, 5,
    5, 5, 5, 5,
    5, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 5,
    5, 5, 5, 5,
    5, 5, 5, 5, 3, 3, 3, 5, 5,
    3, 5, 5, 5, 5, 5,
    5, 5, 5, 5, 5, 3,
    5, 5, 5, 5, 5, 3
};

// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup() {
    lcd.begin(16, 2); // lcd initial
    lcd.backlight(); // turn on the backlight
    lcd.setCursor(0, 0);
    lcd.print("Play:Astronomia");
    lcd.setCursor(0, 1);
    lcd.print("(Coffin Dance)");
}

void loop() {
    // iterate over the notes of the melody:
    for (int thisNote = 0; thisNote < 59; thisNote++) {

        // 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 noteDuration = 1000 / noteDurations[thisNote];
        tone(PIN_BUZ, melody[thisNote], noteDuration);

        // to distinguish the notes, set a minimum time between them.
        // the note's duration + 30% seems to work well:
        int pauseBetweenNotes = noteDuration * 1.30;
        delay(pauseBetweenNotes);
        // stop the tone playing:
        noTone(PIN_BUZ);
    }
    delay(3000);
}

感謝這位大叔的彈奏教學

Last updated: