聲音偵測

在「距離偵測」和「人體紅外線偵測」之後,這篇要來介紹「聲音偵測」,聲音偵測並不是語音辨識,比較貼切的應該是指「有沒有聲音」,語音辨識在之後會介紹。

聲音偵測傳感器

這裏使用簡單的聲音偵測傳感器,並不是分貝計無法偵測大小聲,只能透過傳感器本身靈敏度的調整,靈敏度可以透過傳感器上頭的十字旋鈕更改,偵測有沒有聲音的原理主要根據「震動」,當偵測到「有」聲音的時候,會發送「高電位」訊號。

聲音偵測傳感器

接線的方式把 5V 接在 5V 的位置,GND 接 GND,OUT 接訊號腳。

馬克一號與聲音偵測傳感器接線圖

接線完成後,先透過 Webduino Blockly ( https://blockly.webduino.io ) 測試,打開內嵌的網頁,選擇「顯示文字」,放入開發板的積木,輸入裝置的 device ID,接著放入聲音偵測傳感器的積木,腳位設定為 10 號腳,設定「有偵測到」和「沒有偵測到」的對應事件。

設定聲音偵測積木

點選右上角的執行,在聲音傳感器周圍拍拍手,就會出現「你是在大聲什麼啦」的文字,如果不發出聲音,就會出現「偵測中...」的字樣。

相關教學:聲音偵測


範例:https://goo.gl/2gntcR

顯示聲音偵測結果

如果近一點看傳感器,可以看到偵測到聲音的時候,上面有個小紅燈會亮起。

聲音偵測傳感器偵測到聲音亮燈

Webduino 程式用法

聲音偵測的宣告使用 getSound(board, pin),pin 是數位腳,例如接在 10 號腳就改為 10。

sound = getSound(board, 10);

偵測的方式使用 .on(event, callback),event 有兩種,一種是 detected 也就是偵測到訊號,另外一種是 ended,有別於人體紅外線會有「延遲」,聲音偵測的傳感器是沒有延遲的,所以如果需要延遲,就必須要自己在網頁裡面完成

sound.on("detected", function(){
  //偵測到聲音的時候要做什麼事
});
sound.on("ended", function(){
  //結束後會做什麼事
});

網頁控制

再來就要來控制智慧插座上的電燈了,如果 GND 只有一個,就必須要用麵包板外接,接線圖如下:

智慧插座與聲音偵測傳感器接線圖

在自己的網頁內引入「 webduino-min.js 」還有「 webduino-blockly.js 」這兩個 JavaScript,這樣我們才有操控開發板以及聲音偵測的 API 可以使用,在 body 的區域放入一個 h2 來顯示一些文字訊息,然後放入兩張燈泡一明一暗的圖片,讓偵測到訊號的時候,網頁上的燈泡也會發生反應。

HTML:

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>Webduino</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script src="https://webduino.io/components/webduino-js/dist/webduino-all.min.js"></script>
  <script src="https://blockly.webduino.io/webduino-blockly.js"></script>
</head>

<body>
  <h2 id="show"></h2>
  <img src="http://example.oxxostudio.tw/it2016/it2016-day05-on.jpg" id="on">
  <img src="http://example.oxxostudio.tw/it2016/it2016-day05-off.jpg" class="show" id="off">
</body>
</html>

CSS 的部分很陽春,就只是寫個簡單的控制燈泡圖片有沒有出現而已。

img{
  display:none;
}
.show{
  display:block;
}

JavaScript 的說明直接寫在程式碼裡,主要多設定一個變數初始值是 0,在每一次偵測到訊號的時候都會「加 1」,這樣就可以判斷是否為「一秒內」的「第一次」所偵測到的訊號 ( 因為如果連續偵測,這個變數的數值就不會是 1 ),接著透過 setTimeout 來延遲,在延遲之後再把這個變數設為 0 就可以了。

$(function(){
  var sound,
      led,
      $show=$('#show'),
      $on = $('#on'), 
      $off = $('#off'); 

  var a = 0; //設一個變數,判斷是不是在一秒內偵測的訊號

  boardReady('你的裝置 ID', function (board) {
    board.systemReset();
    board.samplingInterval = 250;
    sound = getSound(board, 11);  //設定聲音偵測傳感器為 11 號腳
    led = getLed(board, 10); //設定 LED 為 10 號腳
    $show.text('偵測中...');
    sound.on("detected", function(){
      a = a + 1;
      if(a === 1){
        light_On(); // 一秒內的第一次偵測,就執行點燈的流程
        setTimeout(function(){
          a = 0;  //過一秒之後就把 a 變回 0
          light_Off();   //同時把燈熄滅
        }, 1000);
      }
    });
    sound.on("ended", function(){
      if(a === 0){
       light_Off();
      }
    });

    //這是點燈的流程
    function light_On(){
      $show.text('你是在大聲什麼啦!');
      led.on();
      $on.addClass('show');
      $off.removeClass('show');
    }
    ////這是熄燈的流程
    function light_Off(){
      $show.text('偵測中...');
      led.off();
      $on.removeClass('show');
      $off.addClass('show');
    }
  });

});

完整程式碼:http://bin.webduino.io/jerip/1/edit?html,css,js,output

最終結果動畫:

聲音偵測傳感器偵測到聲音啟動智慧插座燈泡開關

小結

每次只要用到聲音傳感器,都會想到金凱瑞演的「王牌天神」還有班。史提勒的「博物館驚魂夜」,裡面都有一個橋段用彈指開燈或是拍手開燈,其實透過聲音傳感器就能夠做到一樣的效果了喔。

參考資料