本教程對(duì)于電子制造商來(lái)說(shuō)將非常令人興奮,因?yàn)槲覀儗⑹褂?Arduino Nano 設(shè)計(jì)我們自己的觸控電容式鋼琴。我們將在我們的鋼琴上加入錄音和回放功能。到目前為止,我們已經(jīng)使用 Arduino 制作了一些鋼琴項(xiàng)目,但這個(gè)項(xiàng)目完全不同,因?yàn)槲覀儗⑹褂秒娙菔接|摸鍵作為我們的鋼琴鍵。因此,在學(xué)習(xí)如何打造有趣的鋼琴演奏的同時(shí),我們還將探索如何在 PCB 上設(shè)計(jì)電容式觸摸鍵,因?yàn)槟梢試L試讓我們的按鍵看起來(lái)像真正的鋼琴鍵。由于其制造商PCBWay ,PCB 看起來(lái)和工作起來(lái)都像鋼琴,我們還將探索我們?nèi)绾卧O(shè)計(jì)和制造此板,但在此之前,讓我們探索電容式觸摸傳感器及其工作原理。
電容式觸摸傳感器如何工作?
我們知道,為了形成一個(gè)具有一定電容值的電容器,我們需要兩個(gè)平行的導(dǎo)電板,由介電材料隔開(kāi)。但是我們?nèi)绾蝺H僅通過(guò)用手指觸摸導(dǎo)電板來(lái)判斷電容是否發(fā)生了變化呢?我們的答案是基于我們對(duì)電容器的基本理解。眾所周知,改變導(dǎo)電板的面積或兩個(gè)平行導(dǎo)電板之間的距離可以改變電容值。在導(dǎo)電板和手指之間,我們有空氣作為電介質(zhì)。結(jié)果,當(dāng)我們用手指觸摸板時(shí),電容的增加不確定,因?yàn)槲覀兊氖种赋洚?dāng)導(dǎo)電物體,兩個(gè)導(dǎo)電物體之間的距離減小了。我們知道平行板電容器的電容的基本公式是,
C = εA/d
其中“A”代表導(dǎo)電板的面積,“d”代表兩個(gè)導(dǎo)電板之間的距離,“ε”代表 AIR 的介電常數(shù)。結(jié)果,增加面積并減小兩個(gè)平行導(dǎo)電板之間的距離會(huì)增加電容值。在我們的例子中,觸摸導(dǎo)電板會(huì)減少距離,同時(shí)增加電容值。我們可以通過(guò)將導(dǎo)電材料連接到電阻器和微控制器的 GPIO 引腳來(lái)檢測(cè)這種變化的電容嗎?答案是,我們不能。是的,將電壓源連接到它會(huì)導(dǎo)致模擬電壓發(fā)生微小變化,但這不是一個(gè)非??煽康慕鉀Q方案。
如何檢測(cè)電容式觸摸傳感器中的電容變化?
那么,我們?nèi)绾闻袛嚯娙葜凳欠癜l(fā)生了變化呢?但是,有更好的方法來(lái)解決它。讓我們看一下下面的框圖。將其視為由微控制器(在本例中為 Arduino Nano)、1 兆歐電阻和導(dǎo)電板組成的基本電路。Arduino Nano 的兩條數(shù)字線連接到帶有 1 兆歐電阻的電阻回路。該電阻器也有一點(diǎn)與導(dǎo)電板相連。雖然這塊板充當(dāng)電容器的單點(diǎn),但它仍然可以引入電容,當(dāng)我們觸摸它時(shí)會(huì)發(fā)生變化。然而,這不能簡(jiǎn)單地通過(guò)檢測(cè)電壓變化來(lái)檢測(cè)。這條線上的電容變化并不像感應(yīng) GPIO 引腳上的值的切換那樣容易。
電容式傳感器庫(kù)如何工作?
這就是 Arduino 庫(kù)派上用場(chǎng)的地方。非常感謝“ CapacitiveSensor ”庫(kù)的作者Paul Bagder和Paul Stoffregen 。當(dāng)我們觸摸那個(gè)導(dǎo)電板時(shí),我們可以使用這個(gè)庫(kù)來(lái)檢測(cè)電容的變化。在這個(gè)庫(kù)中,一個(gè)數(shù)字引腳用作發(fā)送引腳(作為OUTPUT),而另一個(gè)用作接收引腳(作為INPUT)。發(fā)送引腳變?yōu)楦唠娖胶徒邮找_變?yōu)楦唠娖街g的持續(xù)時(shí)間是檢測(cè)電容變化的唯一方法 。 當(dāng)您將發(fā)送引腳設(shè)置為高電平(或5 伏)時(shí),電阻-電容對(duì) 會(huì) 在發(fā)送引腳變?yōu)楦唠娖胶徒邮找_從發(fā)送引腳讀取高值之間產(chǎn)生延遲。CapacitiveSensor 庫(kù)提供了一個(gè)將發(fā)送引腳設(shè)置為HIGH的函數(shù),然后等待并計(jì)數(shù),直到接收引腳被讀取為 HIGH。此函數(shù)返回可用于檢測(cè)電容變化的時(shí)間值。當(dāng)時(shí)間值增加或減少時(shí), 表示電容值發(fā)生了變化。當(dāng)電容較大時(shí),接收引腳達(dá)到高電平所需的時(shí)間較長(zhǎng) ,而當(dāng)電容較小時(shí),接收引腳達(dá)到高電平所需的時(shí)間較短。因此,我們可以確定正常狀態(tài)是什么,然后在每次發(fā)送引腳切換時(shí)檢查更改。
我們將使用“ CapacitveSensor ”庫(kù)來(lái)檢測(cè)電容的變化。但在進(jìn)入編程部分之前,讓我們?yōu)槲覀兊捻?xiàng)目創(chuàng)建電路和 PCB。在這里,我們使用EasyEDA平臺(tái)為我們的項(xiàng)目創(chuàng)建原理圖和 PCB。為了檢測(cè)電容的變化,我們將使用“ CapacitveSensor ”庫(kù)。在開(kāi)始編程之前,讓我們從項(xiàng)目的電路和 PCB 開(kāi)始。我們項(xiàng)目的原理圖和 PCB 是使用EasyEDA平臺(tái)創(chuàng)建的。在EasyEDA平臺(tái)上,我們創(chuàng)建了大量的PCB項(xiàng)目。這些項(xiàng)目可用于獲得如何在 EasyEDA 上設(shè)計(jì) PCB 的概念。
使用 Arduino Nano 構(gòu)建 PCB 鋼琴所需的組件
使用 Arduino Nano 構(gòu)建 PCB 鋼琴需要以下組件。
Arduino納米
電阻器 (1Mega Ohm) X 8
壓電蜂鳴器
18650 電池芯
18650 電池座
18650電池充電模塊
直流到直流電壓升壓器。
使用 Arduino Nano 的 PCB 鋼琴電路圖
在以下電路圖中,八個(gè) 1Mega Ohm 電阻器連接到 Arduino Nano 的數(shù)字引腳 2 。數(shù)字引腳 3 到 10進(jìn)一步連接到每個(gè)電阻的其他連接點(diǎn)。在下圖中,我們有一個(gè)標(biāo)有“RECODINGSWITCH”的滑動(dòng)開(kāi)關(guān)。Arduino Nano 的數(shù)字引腳 12連接到滑動(dòng)開(kāi)關(guān)的“EN”引腳。滑動(dòng)開(kāi)關(guān)的“Vs”引腳連接到 Arduino Nano 的“ 5V”引腳。滑動(dòng)開(kāi)關(guān)的“GND”引腳連接到 Arduino Nano 的“連接到 Arduino Nano 的“A4” 引腳。蜂鳴器的負(fù)極連接到 Arduino Nano 的接地引腳。
我們已將八個(gè) 10uF 電容器連接 到每個(gè)電阻器。每個(gè)電容器的負(fù)極引腳連接到Arduino Nano 的接地引腳。然后我們有一個(gè)電源部分,為Arduino Nano 的“Vin”引腳提供適當(dāng)?shù)?6.6V。18650 電池單元連接到18650 電池充電器模塊,充電器模塊的輸出連接到DC 到 DC 升壓器。升壓器的正輸出引腳( BOUT + ) 連接到 Arduino Nano 的“Vin” 引腳,升壓器的負(fù)輸出引腳(BOUT-)連接到Arduino Nano 的接地引腳。
注:如有需要,我們可以加電容。強(qiáng)烈建議使用小電容器 (20pF - 400pF) 來(lái)穩(wěn)定檢測(cè)到的數(shù)據(jù)。但是,請(qǐng)確保電容器接地,因?yàn)檫@會(huì)降低并聯(lián)體電阻。但是,就我而言,我沒(méi)有使用電容器,因?yàn)闆](méi)有它們對(duì)我來(lái)說(shuō)效果很好。我在上面的示意圖中提到了電容器,因此您可以在實(shí)際實(shí)施過(guò)程中輕松添加它們。按照“ CapacitveSensor ”庫(kù)文檔中的規(guī)定,以下電容器的值必須介于20pF 和 400pF之間。
PCB概述
上述原理圖的 PCB 視圖如下圖所示。您可以從我們的 GitHub 存儲(chǔ)庫(kù)下載項(xiàng)目的 Gerber 文件?;蛘?,您可以訪問(wèn)EasyEDA平臺(tái)上的項(xiàng)目了解更多詳情。黃色用于頂層絲綢層。而綠色代表底部絲綢層。紅色代表頂層,藍(lán)色代表底層。
PCB的頂層:
現(xiàn)在,讓我們逐層查看PCB的每一層。頂層如下圖所示。如您所見(jiàn),頂層是紅色的。我設(shè)計(jì)了每個(gè)導(dǎo)電板,使其看起來(lái)像鋼琴。鋼琴的每個(gè)鍵都分別連接到每個(gè) 1 兆歐電阻上。
我使用了可以在 EasyEDA 的 PCB 工具部分找到的矩形形狀,在下圖中以紅色圈出。確保按鍵的寬度足夠大,以便您可以用手指觸摸每個(gè)按鍵。就我而言,我設(shè)法繪制了寬度為 10 毫米或大于 10 毫米的每個(gè)鍵。
PCB的底層:
在底層,我們有一個(gè)完整的銅層,用于連接所有接地。您可以在 EasyEDA的“PCB Tools”中使用“Solid Region”選項(xiàng)。這被稱(chēng)為 “銅澆注”方法。此步驟會(huì)將底層轉(zhuǎn)換為公共接地層。我們?cè)谶@一層還有一些其他的銅連接。
PCB的頂層絲綢層:
下圖表示 PCB 的 Top-Silk-Layer。我們可以通過(guò)添加一些絲層或非銅層來(lái)設(shè)計(jì)我們的 PCB。我將滑動(dòng)開(kāi)關(guān)標(biāo)記為“ RECORD”和“ PLAY”。這樣我們就可以了解我們使用的是哪種模式。我們?cè)陧攲咏z綢層有 BUZZER 的足跡?!?XL6009E1”是由方形區(qū)域包圍的 DC 到 DC 升壓模塊的封裝。我們可以使用EasyEDA 上提供的相應(yīng)PCB 工具添加文本和圖像。
PCB的底層絲綢層:
在 PCB 的底部絲層,我們有 Arduino Nano、8 個(gè) 1Mega ohm 電阻器、8 個(gè)電容器、一個(gè) 18650 電池座或單節(jié)電池和充電模塊的封裝。
使用 Arduino Nano 對(duì)鋼琴 PCB 進(jìn)行編程
“ CapacitiveSensor ”庫(kù)非常易于使用,并且他們提供了有關(guān)如何使用該庫(kù)的很好的文檔。在進(jìn)入程序之前,讓我們?cè)?Arduino IDE 上安裝“ CapacitiveSensor”庫(kù)。您需要下載庫(kù)的 zip 文件。然后轉(zhuǎn)到Arduino IDE 工具欄下的“ Sketch -》 Include Library ”部分。使用“添加 .Zip 庫(kù)。。.”選項(xiàng)添加 zip 文件,如下圖所示。然后重新啟動(dòng) Arduino IDE。
現(xiàn)在,您可以從我們的 github 存儲(chǔ)庫(kù)中下載該項(xiàng)目的代碼,然后打開(kāi)“?codes ”文件夾中的“?piano_pcb.ino?”文件。我們有一個(gè)名為“?piano_tones.h?”的自定義頭文件。此頭文件包含在主文件中以獲取一些預(yù)定義的自定義鋼琴音色。就像鋼琴一樣,每個(gè)音調(diào)都指的是一個(gè)音符。讓我們看看“piano_pcb.ino”文件里面有什么。
?
#include <電容傳感器.h> #include "piano_tones.h" #define common_pin 2 // 所有鍵的通用“發(fā)送”引腳 #define Buzzer A4 //壓電蜂鳴器的輸出引腳 #define recordbtn 12 // 錄音按鈕 #define CPin(pin) CapacitiveSensor (common_pin, pin)
?
在“?piano_pcb.ino?”文件的開(kāi)頭,我們有“?CapacitiveSensor.h?”和“?piano_tones.h?”頭文件。然后我為各自的 GPIO 引腳定義了三個(gè)宏。“?common_pin”用于將“digital pin 2”設(shè)置為“Send Pin”,?“?buzzer”用于定義模擬pin 4(A4),“recordbtn”用于從“將按鈕”滑入“數(shù)字引腳 12”。然后我創(chuàng)建了“CPin (pin)”宏,這樣我們就不需要傳遞發(fā)送 pin(即common_pin)和CapacitiveSensor(common_pin,pin)中的接收引腳(即各個(gè)電阻器的引腳)多次。
?
整數(shù)注釋[]={NOTE_C7,NOTE_D7,NOTE_E7,NOTE_F7,NOTE_G7,NOTE_A7,NOTE_B7,NOTE_C8}; // 啟動(dòng)時(shí)的聲音 int soundOnStartUp[] = { 注意_E7, 注意_E7, 0, 注意_E7, 0, 注意_C7, 注意_E7, 0, NOTE_G7, 0, 0, 0, NOTE_G6, 0, 0, 0 }; 電容式傳感器鍵[] = {CPin(3), CPin(4), CPin(5), CPin(6), CPin(7), CPin(8), CPin(9), CPin(10)};
?
調(diào)用庫(kù)并定義某些宏后,我們需要?jiǎng)?chuàng)建 3 個(gè)如上所述的數(shù)組。即notes[]、soundOnStartUp[]和keys[]?!?notes[]?”數(shù)組存儲(chǔ)的是鋼琴在一定音階中對(duì)應(yīng)的音符(例如?NOTE_C7、NOTE_D7等)。您可以通過(guò)取消注釋我在代碼中提供的其他“?notes[]?”來(lái)更改比例。soundOnStartUp?[]數(shù)組用于存儲(chǔ)我在鋼琴啟動(dòng)期間使用的一些曲調(diào)。該數(shù)組已在setup()函數(shù)中調(diào)用。電容式傳感器鍵[?]array 用于存儲(chǔ)相應(yīng)的接收引腳,使用我們之前定義的CPin()函數(shù)。
?
無(wú)效記錄按鈕(){ // 設(shè)置傳感器的靈敏度。 long touch1 = keys[0].capacitiveSensor(靈敏度); long touch2 = keys[1].capacitiveSensor(靈敏度); long touch3 = keys[2].capacitiveSensor(靈敏度); long touch4 = keys[3].capacitiveSensor(靈敏度); long touch5 = keys[4].capacitiveSensor(靈敏度); long touch6 = keys[5].capacitiveSensor(靈敏度); long touch7 = keys[6].capacitiveSensor(靈敏度); long touch8 = keys[7].capacitiveSensor(靈敏度); pev_button = 按鈕; // 當(dāng)我們觸摸到傳感器時(shí),按鈕會(huì)記錄相應(yīng)的數(shù)字。 如果(觸摸1 > 靈敏度) 按鈕 = 1; if (touch2 > 靈敏度) 按鈕 = 2; if (touch3 > 靈敏度) 按鈕 = 3; if (touch4 > 靈敏度) 按鈕 = 4; if (touch5 > 靈敏度) 按鈕 = 5; if (touch6 > 靈敏度) 按鈕 = 6; if (touch7 > 靈敏度) 按鈕 = 7; if (touch8 > 靈敏度) 按鈕 = 8; // 當(dāng)我們沒(méi)有觸摸它時(shí),不會(huì)產(chǎn)生音調(diào)。 if (touch1<=敏感度 & touch2<=敏感度 & touch3<=敏感度 & touch4<=敏感度 & touch5<=敏感度 & touch6<=敏感度 & touch7<=敏感度 & touch8<=敏感度) 按鈕 = 0; /****將按下的按鈕記錄在一個(gè)數(shù)組中***/ 如果(按鈕!= pev_button && pev_button != 0) { 記錄按鈕[button_index] = pev_button; 按鈕索引++; 記錄按鈕[按鈕索引] = 0; 按鈕索引++; } /**錄制程序結(jié)束**/ }
?
我們使用“keys[0].capacitiveSensor(sensitivity)”函數(shù)讀取每個(gè)鍵的電容值,并將其與一些指定值進(jìn)行比較,以確定在上述recordButtons()函數(shù)中按下了哪個(gè)鍵。我們還跟蹤在此函數(shù)中按下按鈕的順序。記錄的值保存在記錄的button[]數(shù)組中。我們首先查看是否按下了新鍵,如果是,我們?cè)俅螜z查它不是按鈕 0。但是沒(méi)有按下按鈕,因此按鈕 0 什么都沒(méi)有。我們將值保存在 if 循環(huán)內(nèi)的變量button_index指定的索引位置,然后我們?cè)黾釉撍饕狄员苊飧采w相同的位置。
?
無(wú)效playTone(){ /****Rcord 數(shù)組中每個(gè)按鈕按下之間的時(shí)間延遲***/ 如果(按鈕!= pev_button) { note_time = (millis() - start_time) / 10; 如果(注意時(shí)間!= 0){ 記錄時(shí)間[time_index] = note_time; 時(shí)間索引++; 開(kāi)始時(shí)間 = 毫秒(); } Serial.println(time_index); } /**錄制程序結(jié)束**/ 如果(按鈕 == 0) { noTone(蜂鳴器); } 如果(按鈕 == 1) { 音調(diào)(蜂鳴器,注釋[0]); } 如果(按鈕 == 2) { 音調(diào)(蜂鳴器,注釋[1]); } 如果(按鈕 == 3) { 音調(diào)(蜂鳴器,注釋[2]); } 如果(按鈕 == 4) { 音調(diào)(蜂鳴器,注釋[3]); } 如果(按鈕 == 5) { 音調(diào)(蜂鳴器,注釋[4]); } 如果(按鈕 == 6) { 音調(diào)(蜂鳴器,注釋[5]); } 如果(按鈕 == 7) { 音調(diào)(蜂鳴器,注釋[6]); } 如果(按鈕 == 8) { 音調(diào)(蜂鳴器,注釋[7]); } }
?
使用各種if條件,我們將為 playTone() 函數(shù)中的按鍵播放適當(dāng)?shù)囊粽{(diào)。該函數(shù)的完整代碼顯示在上面。我們還將使用一個(gè)名為recorded time[] 的數(shù)組來(lái)保存按下按鈕的時(shí)間長(zhǎng)度。該過(guò)程類(lèi)似于記錄按鈕序列,因?yàn)槲覀兪褂?millis() 函數(shù)來(lái)計(jì)算每個(gè)按鈕被按下的時(shí)間,然后將該值除以 10 以減小變量的大小。我們?cè)诎粹o 0 的同一時(shí)間段內(nèi)不播放任何音調(diào),這表示用戶沒(méi)有按下任何東西。
?
無(wú)效設(shè)置(){ 序列號(hào).開(kāi)始(9600); // 關(guān)閉所有通道的自動(dòng)校準(zhǔn): for(int i=0; i<8; ++i) { 鍵[i].set_CS_AutocaL_Millis(0xFFFFFFFF); } // 將蜂鳴器設(shè)置為輸出: pinMode(蜂鳴器,輸出); pinMode(recordbtn,輸入); noTone(蜂鳴器); 延遲(10); int sizeed = sizeof(soundOnStartUp) / sizeof(int); for (int thisNote = sizeed; thisNote > 0 ; thisNote--) { 音(蜂鳴器,soundOnStartUp[thisNote]); 延遲(100); } noTone(蜂鳴器); 延遲(10); }
?
在setup?() 函數(shù)中有兩個(gè) for 循環(huán)。在第一個(gè)循環(huán)中,我使用“keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF)?”設(shè)置了鍵。第二個(gè)for 循環(huán)用于通過(guò)使用音調(diào)(蜂鳴器,soundOnStartUp[thisNote])播放soundOnStartUp[]音符。
?
無(wú)效循環(huán)(){ Serial.println(digitalRead(recordbtn)); while (digitalRead(recordbtn) == 1) //如果撥動(dòng)開(kāi)關(guān)設(shè)置為錄制模式 { 記錄按鈕(); 播放音(); } while (digitalRead(recordbtn) == 0) //如果撥動(dòng)開(kāi)關(guān)設(shè)置為播放模式 { for (int i = 0; i < sizeof(recorded_button) / 2; i++) { 延遲((記錄時(shí)間[i])* 10);//等待支付下一曲 if (recorded_button[i] == 0) noTone(蜂鳴器);//用戶沒(méi)有觸摸任何按鈕 別的 音(蜂鳴器,注釋[(recorded_button[i] - 1)]);//播放用戶觸摸的按鈕對(duì)應(yīng)的聲音 } } }
?
然后,要播放錄制的音調(diào),用戶必須在錄制后將滑動(dòng)開(kāi)關(guān)推到另一方向。完成此操作后,程序退出前一個(gè) while 循環(huán)并進(jìn)入第二個(gè) while 循環(huán),在該循環(huán)中,我們按照鍵被擊中的順序播放先前記錄的長(zhǎng)度的音符。上面提供了完成此操作的代碼。您可以觀看下面附加的視頻以獲取更多說(shuō)明。
代碼
#include
#include “piano_tones.h”
#define common_pin 2 // 所有電阻的公共“發(fā)送”引腳
#define buzzer A4 // 壓電蜂鳴器的輸出引腳
#define recordbtn 12 // 錄音button
//這個(gè)宏為每個(gè)電阻引腳創(chuàng)建一個(gè)電容傳感器對(duì)象
#define CPin(pin) CapacitiveSensor(common_pin, pin)
char button = 0;
整數(shù)模擬值;
字符 REC = 0;
int 記錄按鈕[200];
詮釋 pev_button;
int 靈敏度 = 2000;
int 記錄時(shí)間[200];
字符時(shí)間索引;
字符按鈕索引 = 0;
無(wú)符號(hào)長(zhǎng)開(kāi)始時(shí)間;
int note_time;
// 每個(gè)鍵對(duì)應(yīng)一個(gè)音符,這里定義。取消注釋您要使用的比例:
//int notes[]={NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_B4,NOTE_C5}; // C 大調(diào)音階
//int notes[]={NOTE_A4,NOTE_B4,NOTE_C5,NOTE_D5,NOTE_E5,NOTE_F5,NOTE_G5,NOTE_A5}; // A-小調(diào)音階
//int notes[]={NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_C5,NOTE_D5}; // C 藍(lán)調(diào)音階
//int notes[] = {1300, 1500, 1700, 1900, 2000, 2300, 2600, 2700};
整數(shù)注釋?zhuān)郏?{NOTE_C7,NOTE_D7,NOTE_E7,NOTE_F7,NOTE_G7,NOTE_A7,NOTE_B7,NOTE_C8};
//int notes[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
// 啟動(dòng)聲音
int soundOnStartUp[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7,
0, NOTE_C7, NOTE_E7, 0,
注意_G7, 0, 0, 0,
注意_G6, 0, 0, 0
};
// 定義寄存器連接的引腳:
CapacitiveSensor keys[] = {CPin(3), CPin(4), CPin(5), CPin(6), CPin(7), CPin(8), CPin( 9), CPin(10)};
無(wú)效設(shè)置(){
Serial.begin(9600);
// 關(guān)閉所有通道的自動(dòng)校準(zhǔn):
for(int i=0; i<8; ++i) {
keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF);
}
// 設(shè)置蜂鳴器為輸出:
pinMode(buzzer, OUTPUT);
pinMode(recordbtn,輸入);
noTone(蜂鳴器);
延遲(10);
int sizeed = sizeof(soundOnStartUp) / sizeof(int);
for (int thisNote = sizeed; thisNote 〉 0 ; thisNote--) {
tone(buzzer, soundOnStartUp[thisNote]);
延遲(100);
}
noTone(蜂鳴器);
延遲(10);
}
void loop() {
Serial.println(digitalRead(recordbtn));
while (digitalRead(recordbtn) == 1) //如果撥動(dòng)開(kāi)關(guān)設(shè)置為錄制模式
{
recordButtons();
播放音();
}
while (digitalRead(recordbtn) == 0) //如果撥動(dòng)開(kāi)關(guān)設(shè)置為播放模式
{
for (int i = 0; i < sizeof(recorded_button) / 2; i++)
{
delay((recorded_time[i]) * 10); //等待支付下一曲
if (recorded_button[i] == 0)
noTone(buzzer);
//用戶沒(méi)有觸摸任何
其他按鈕 //播放用戶觸摸的按鈕對(duì)應(yīng)的聲音
}
}
}
void recordButtons(){
// 設(shè)置傳感器的靈敏度。
long touch1 = keys[0].capacitiveSensor(靈敏度);
long touch2 = keys[1].capacitiveSensor(靈敏度);
long touch3 = keys[2].capacitiveSensor(靈敏度);
long touch4 = keys[3].capacitiveSensor(靈敏度);
long touch5 = keys[4].capacitiveSensor(靈敏度);
long touch6 = keys[5].capacitiveSensor(靈敏度);
long touch7 = keys[6].capacitiveSensor(靈敏度);
long touch8 = keys[7].capacitiveSensor(靈敏度);
pev_button = 按鈕;F1
// 當(dāng)我們觸摸到傳感器時(shí),按鈕會(huì)記錄相應(yīng)的數(shù)字。
如果 (touch1 〉 靈敏度)
按鈕 = 1;
if (touch2 〉 靈敏度)
按鈕 = 2;
如果 (touch3 〉 靈敏度)
按鈕 = 3;
如果(touch4 〉 靈敏度)
按鈕 = 4;
如果 (touch5 〉 靈敏度)
按鈕 = 5;
如果 (touch6 〉 靈敏度)
按鈕 = 6;
如果 (touch7 〉 靈敏度)
按鈕 = 7;
如果 (touch8 〉 靈敏度)
按鈕 = 8;
// 當(dāng)我們沒(méi)有觸摸它時(shí),不會(huì)產(chǎn)生音調(diào)。
if (touch1<= 靈敏度 & touch2<= 靈敏度 & touch3<= 靈敏度 & touch4<= 靈敏度 & touch5<= 靈敏度 & touch6<= 靈敏度 & touch7<= 靈敏度 & touch8<= 靈敏度)
按鈕 = 0;
/****將按下的按鈕記錄在一個(gè)數(shù)組中***/
if (button != pev_button && pev_button != 0)
{
recorded_button[button_index] = pev_button;
按鈕索引++;
記錄按鈕[按鈕索引] = 0;
按鈕索引++;
}
/** 錄制程序結(jié)束**/
}
void playTone(){
/****Rcord 數(shù)組中每個(gè)按鈕按下之間的時(shí)間延遲***/
if (button != pev_button)
{
note_time = (millis( ) - 開(kāi)始時(shí)間) / 10;
if(note_time!=0){
記錄時(shí)間[time_index] = note_time;
時(shí)間索引++;
開(kāi)始時(shí)間 = 毫秒();
}
Serial.println(time_index);
}
/**錄制程序結(jié)束**/
if (button == 0)
{
noTone(蜂鳴器);
}
如果(按鈕 == 1)
{
音(蜂鳴器,注釋 [0]);
}
if (button == 2)
{
音(蜂鳴器,注釋?zhuān)?]);
}
如果(按鈕 == 3)
{
音(蜂鳴器,注釋 [2]);
}
if (button == 4)
{
音(蜂鳴器,注釋?zhuān)?]);
}
如果(按鈕 == 5)
{
音(蜂鳴器,注釋 [4]);
}
如果(按鈕 == 6)
{
音(蜂鳴器,注釋 [5]);
}
如果(按鈕 == 7)
{
音(蜂鳴器,注釋 [6]);
}
如果(按鈕== 8)
{
音(蜂鳴器,注釋?zhuān)?]);
}
}
評(píng)論