# 按壓音樂板
## 設計目的
此設計為一款兼具觸覺、視覺、聽覺,三合一的遊戲設施以供小朋友遊玩。除了好玩,更可以滿足小朋友對於感官上進步的需求。
這次的作品主要是進一步改良上學期得按壓音樂板。我們將體積進一步的縮小、換上聲音更大的喇叭以及LED線材隱藏。
## 使用材料
| 項目 | 材料 | 規格/數量 | 圖片 | 備註 |
| --- | ---------------- | --------------- | ----- | --- |
| 1 | 黑色硬紙板 | 全開 X1 |  | 由申甲購入,硬度影響結構堅固程度|
| 2 | 塑膠瓦楞紙 | 10cmX10cm X 1包 |  | 由申甲購入,作為內部結構支撐 |
| 3 | 微動開關 | X6 |  | 大洋電子購入,可依按壓手感選擇不同規格|
| 4 | Arduino UNO | X1 |  | 老師提供 |
| 5 | 57mm外磁紙盆喇叭 | 8Ω 3W X1 |  | 大洋電子購入,可依實際需求更換規格|
| 6 | LED燈條 | 2m X 1 |  | 大洋電子購入 |
| 7 | 彈簧 | X6 |  | 由申甲購入,長度約2.5cm|
| 8 | DFPlayer Mini音效卡 | X1 | | 蝦皮購入 |
| 9 | Micro SD卡 | 2GB X 1 |  | 容量需求可依音效數量調整 |
## 使用工具
* 熱熔槍
* 美工刀
* 撥線鉗
* 尺
* 烙鐵、焊錫
## 結構摘要
外殼使用硬紙板,電源採用行動電源供電。內裝以22cm31cm硬紙板(1)隔開兩層式設計,上層為彈簧(2)、微動開關(3)和圖案紙板(4)構成的按鈕,下層(5)主要由Arduino UNO控制版連接到上層電路、喇叭、DFplayermini音效卡、電源供應。


底層由瓦楞紙做支撐。
## 製作流程
### 外盒製作
音樂盒展開平面圖,包含音樂盒外盒、中間層隔板、按鍵。

---
### 中間層隔板製作
1. 將中間層隔板依照外盒描出六顆按鍵的位置,並將微動開關所需之接線先焊接好。
2. 確定微動開關擺放位置後將硬紙板挖洞並將微動開關卡進去如下圖所示。

4. 以塑膠瓦楞紙製作上、下層支柱,上、下層支撐高度皆為2cm。

---
### 按鍵製作
動物圖示
1. 下圖列印出來後將各動物剪裁為邊長6.5cm之正方形



2. 將裁剪好的資料夾黏在板子上
3. 將4個彈簧以熱融膠固定
4. 將動物圖片放置於資料夾中

---
### 喇叭製作
1. 利用切完外盒遺留的硬紙板切出如下尺寸之紙板

2. 將喇叭線預先接好正負線後放入有圓孔之紙板並使用熱熔膠將其固定
3. 最後將喇叭正負線從接縫處拉出後將剩餘紙板拚上並使用熱熔膠固定

---
### 線路配置
將各部件如下圖配置接好線後,再將各部件以泡棉膠固定至中間層隔板背後即可


---
### Arduino Code
```cpp=
#include <SPI.h>
#include "DFRobotDFPlayerMini.h"
#include "SoftwareSerial.h"
SoftwareSerial mySerial(12, 13); // 宣告虛擬PORT,函式輸入為RX, TX,用來與DFplayer通訊
DFRobotDFPlayerMini myDFPlayer; // 宣告DFplayer
/*********************腳位定義*********************/
static const uint8_t InputPin[] = {A0, A1, A2, A3, A4, A5, A6, A7}; // 輸入腳位宣告
static const uint8_t OutputPin[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // 輸出腳位宣告
// 腳位A0 ~ A5為BUTTON
//#define LED 3 // 定義LED腳位
/* MUSIC ORDER 音效順序
1 frog
2 cow
3 rooster
4 horse
5 bird
6 cat
7 開機提示音
*/
uint16_t LedBreathing = 0;
uint16_t LightChange_interval = 5;
uint16_t present_state = -1;
uint16_t light_state = 0;
int ledPins[] = {3, 4, 5, 6, 7};
int selectFolder = 1;
void setup() {
mySerial.begin(9600); // 給定虛擬PORT的鮑率
Serial.begin(115200); // 給定實體PORT的鮑率
present_state = -1; // 給定初始狀態
pinMode(ledPins[0], OUTPUT);
pinMode(ledPins[1], OUTPUT);
pinMode(ledPins[2], OUTPUT);
pinMode(ledPins[3], OUTPUT);
pinMode(ledPins[4], OUTPUT);
// DFplayer mini Debug字串即初始設定
#if 1
if (!myDFPlayer.begin(mySerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true);
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
//----Set volume----
myDFPlayer.volume(30); //Set volume value (0~30).
// myDFPlayer.volumeUp(); //Volume Up
// myDFPlayer.volumeDown(); //Volume Down
//----Set different EQ----
// myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
//----Set device we use SD as default----
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_U_DISK);
myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_AUX);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_SLEEP);
// myDFPlayer.outputDevice(DFPLAYER_DEVICE_FLASH);
//----Mp3 control----
// myDFPlayer.sleep(); //sleep
// myDFPlayer.reset(); //Reset the module
// myDFPlayer.enableDAC(); //Enable On-chip DAC
// myDFPlayer.disableDAC(); //Disable On-chip DAC
// myDFPlayer.outputSetting(true, 15); //output setting, enable the output and set the gain to 15
//----Mp3 play----
// myDFPlayer.next(); //Play next mp3
// delay(1000);
// myDFPlayer.previous(); //Play previous mp3
// delay(1000);
// myDFPlayer.play(1); //Play the first mp3
// delay(1000);
// myDFPlayer.loop(1); //Loop the first mp3
// delay(1000);
// myDFPlayer.pause(); //pause the mp3
// delay(1000);
// myDFPlayer.start(); //start the mp3 from the pause
// delay(1000);
// myDFPlayer.playFolder(15, 4); //play specific mp3 in SD:/15/004.mp3; Folder Name(1~99); File Name(1~255)
// delay(1000);
// myDFPlayer.enableLoopAll(); //loop all mp3 files.
// delay(1000);
// myDFPlayer.disableLoopAll(); //stop loop all mp3 files.
// delay(1000);
// myDFPlayer.playMp3Folder(4); //play specific mp3 in SD:/MP3/0004.mp3; File Name(0~65535)
// delay(1000);
// myDFPlayer.advertise(3); //advertise specific mp3 in SD:/ADVERT/0003.mp3; File Name(0~65535)
// delay(1000);
// myDFPlayer.stopAdvertise(); //stop advertise
// delay(1000);
// myDFPlayer.playLargeFolder(2, 999); //play specific mp3 in SD:/02/004.mp3; Folder Name(1~10); File Name(1~1000)
// delay(1000);
// myDFPlayer.loopFolder(5); //loop all mp3 files in folder SD:/05.
// delay(1000);
// myDFPlayer.randomAll(); //Random play all the mp3.
// delay(1000);
// myDFPlayer.enableLoop(); //enable loop.
// delay(1000);
// myDFPlayer.disableLoop(); //disable loop.
// delay(1000);
//----Read imformation----
// Serial.println(myDFPlayer.readState()); //read mp3 state
// Serial.println(myDFPlayer.readVolume()); //read current volume
// Serial.println(myDFPlayer.readEQ()); //read EQ setting
// Serial.println(myDFPlayer.readFileCounts()); //read all file counts in SD card
// Serial.println(myDFPlayer.readCurrentFileNumber()); //read current play file number
// Serial.println(myDFPlayer.readFileCountsInFolder(3)); //read file counts in folder SD:/03
#endif
IO_Init(); // IO初始化
myDFPlayer.playFolder(1, 7); // 播放開機提示音效
Serial.println("READY");
Serial.println(selectFolder);
}
int i = 0;
void loop()
{
//執行Main Function
MainProcess();
delay(50);
}
/****************MAIN FUNCTION****************/
void MainProcess()
{
if( present_state = -1) {
for (int i=0; i<5; i++) {
if(digitalRead(InputPin[i]) == LOW) {
present_state = i;
Btn_Push(present_state);
break;
}
}
if(digitalRead(InputPin[5]) == LOW) {
if (selectFolder == 1) {
selectFolder = 2;
Serial.println("selectFolder 2");
PlayMusic(2,6);
delay(300);
} else if (selectFolder == 2) {
selectFolder = 1;
Serial.println("selectFolder 1");
PlayMusic(1,8);
delay(300);
}
}
present_state = -1;
}
}
//播放指定音樂
void PlayMusic(int folder, int pin)
{
myDFPlayer.playFolder(folder, pin);
}
//LED閃爍
void LED_Flash(int value)
{
for(int i=0; i<5; i++)
{
digitalWrite(ledPins[value], HIGH);
delay(250);
digitalWrite(ledPins[value], LOW);
delay(250);
}
}
void Btn_Push(int pin)
{
myDFPlayer.playFolder(selectFolder, pin + 1); //DFplayer播放與按鈕相對應的音效
LED_Flash(pin); //按鈕被按下時,LED狀態為閃爍
}
//進行IO初始設定
void IO_Init()
{
// INPUT_BTN
for(int i=0; i<6; i++)
{
pinMode(InputPin[i], INPUT_PULLUP);
}
// INPUT
for(int i=7; i<sizeof(InputPin)-6 ; i++)
{
pinMode(InputPin[i], INPUT);
}
// OUTPUT
for(int i=0; i<sizeof(OutputPin); i++)
{
pinMode(OutputPin[i], OUTPUT);
}
}
/****************DFPlayer mini****************/
void printDetail(uint8_t type, int value)
{
switch (type) {
case TimeOut:
Serial.println(F("Time Out!"));
break;
case WrongStack:
Serial.println(F("Stack Wrong!"));
break;
case DFPlayerCardInserted:
Serial.println(F("Card Inserted!"));
break;
case DFPlayerCardRemoved:
Serial.println(F("Card Removed!"));
break;
case DFPlayerCardOnline:
Serial.println(F("Card Online!"));
break;
case DFPlayerUSBInserted:
Serial.println("USB Inserted!");
break;
case DFPlayerUSBRemoved:
Serial.println("USB Removed!");
break;
case DFPlayerPlayFinished:
Serial.print(F("Number:"));
Serial.print(value);
Serial.println(F(" Play Finished!"));
break;
case DFPlayerError:
Serial.print(F("DFPlayerError:"));
switch (value) {
case Busy:
Serial.println(F("Card not found"));
break;
case Sleeping:
Serial.println(F("Sleeping"));
break;
case SerialWrongStack:
Serial.println(F("Get Wrong Stack"));
break;
case CheckSumNotMatch:
Serial.println(F("Check Sum Not Match"));
break;
case FileIndexOut:
Serial.println(F("File Index Out of Bound"));
break;
case FileMismatch:
Serial.println(F("Cannot Find File"));
break;
case Advertise:
Serial.println(F("In Advertise"));
break;
default:
break;
}
break;
default:
break;
}
}
```
---
## 成果展示



## 未來方向
1. 按鍵增加,做成九宮格式
2. 音效卡由讀取SD卡更改為USB,更方便老師進行音效更換