數字制造講義08-Arduino聲音應用2

數字制造講義01-成為數字世界的建造者
數字制造講義02-Arduino入門
數字制造講義03-電路基礎
數字制造講義04-負責輸入和輸出的智能元件
數字制造講義05-軟硬件數據通信
數字制造講義06-MIDI 和 OSC 數據傳輸練習
數字制造講義07-Arduino聲音應用

(本系列為 00 在星海音樂學院的課程講義)

回顧

還記得上一周 完成的三個練習嗎:

  • 讓蜂鳴器發聲
  • 蜂鳴器發出交替的報警聲
  • 用按鍵觸發聲音
image

這一周我們繼續來完善,做出一個簡單的旋律控制器。

挑戰4:用電位計控制音高

既然蜂鳴器可以發出不同的音高,那我們可不可以用旋鈕控制音高,做一個 mini 的極簡控制器呢?

在之前第四周的課程中,我們已經建立起比較完整的輸入輸出元件的概念。在項目練習時就可以慢慢養成習慣:在動手之前,先構想出輸入部分是什么、輸出部分是什么、從輸入到輸出要完成什么樣的轉換。

這里,輸入部分是電位計(的位置),輸出部分是蜂鳴器(的音高),中間的連接就是電位計的數值轉換為蜂鳴器的音高。

接線部分,使用的元件包括:蜂鳴器,電位計。

image

當我們還是編程新手,每次要開始自己寫代碼時,容易兩眼一抹黑,不知道該從哪里下手。

其實,每次寫代碼時,并不是直接打開 Arduino IDE 就開始噼里啪啦敲代碼了。在這之前,我們需要現在腦子里構思這個代碼要做什么,怎么做到。

大家會想一下,怎么把大象放進冰箱里呢?

不要笑,這就是所謂的「算法」:做一件事情的步驟。

所以在還沒有清晰思路的時候,我們可以先把程序要完成的大致步驟寫下來:

  • 需要用一個模擬端口讀取電位計的數值
  • 需要用一個數字(輸出)端口給蜂鳴器發出指令
  • 找一個辦法讓蜂鳴器發出不同音高
  • 將電位計數值控制音高

接著,我們再想辦法把每一個步驟都轉化成對應的變量、語法、庫。所以學會搜索和查看官方文檔就很重要的了。

代碼如下:

// connect a potentiometer to pin A0

int buzzerPin=8; 
int potPin=A0;

void setup() {  
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  int freq = analogread(A0);
  freq = map (freq,0,1023,20,20000); //map the value read from the potentiometer into the audible range
  tone (buzzerPin,freq); 
}

上面的代碼中,最核心的一行,是把從電位計讀取的模擬信號數值(范圍是 01023),映射到人耳可感知的聲音的頻率范圍(2020000):freq = map (freq,0,1023,20,20000); 其中 map() 函數的作用就是數值映射。

挑戰5:播放連續音高

這個挑戰一定會更吸引你:用蜂鳴器播放一段旋律。

這個挑戰的難度主要在代碼上,從這里開始,我們會開始接觸并深入理解函數、循環、頭文件、庫等概念。

比較復雜的代碼不可能一下子就能寫出來。所以我們要經歷一個重要的練習:看懂別人的代碼。

我們在官方網站上找到教程 Arduino - ToneMelody。仔細研讀它給出的代碼,尤其是代碼的注釋:

/*
  Melody

  Plays a melody

  circuit:
  - 8 ohm speaker on digital pin 8

  created 21 Jan 2010
  modified 30 Aug 2011
  by Tom Igoe

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Tone
*/

#include "pitches.h"

// notes in the melody:
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

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

void setup() {
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < 8; 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(8, 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(8);
  }
}

void loop() {
  // no need to repeat the melody.
}

把注釋部分全部替換成自己的理解,這個代碼看起來就不再那么復雜和難懂了。但是這個過程一定要自己完成。

當在代碼里看到不熟悉的函數,例如 delay() , noTone() ,就可以到官方文檔中搜索并閱讀,一般文檔都會給出例子,這些例子就是最好的學習材料。

最后,留給大家的作業,是用兩個壓電片觸發兩段不同的旋律,大家動手試試吧!

<iframe frameborder="0" src="https://v.qq.com/txp/iframe/player.html?vid=p08632k4vzj" allowFullScreen="true"></iframe>

Arduino Melody_騰訊視頻


00 的文集

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容