在「距離偵測」和「人體紅外線偵測」之後,這篇要來介紹「聲音偵測」( 不是語音辨識,比較貼切的應該是指「有沒有聲音」,語音辨識在之後會介紹 )。
這裏我使用的是簡單的聲音偵測傳感器,並不是分貝計無法偵測大小聲,只能透過傳感器本身靈敏度的調整,靈敏度可以透過傳感器上頭的十字旋鈕更改,偵測有沒有聲音的原理主要根據「震動」,當偵測到「有」聲音的時候,會發送「高電位」訊號。
接線的方式只要把 5V 接在 5V 的位置,GND 接 GND,OUT 接訊號腳就可以。
接線完成後,先透過 Webduino Blockly ( https://blockly.webduino.io ) 來測試一下,首先打開內嵌的網頁,選擇「顯示文字」,放入開發板的積木,輸入裝置的 device ID,接著放入聲音偵測傳感器的積木,腳位設定為 10 號腳,設定「有偵測到」和「沒有偵測到」的對應事件。( 其實和人體紅外線偵測幾乎一模一樣 )
點選右上角的執行,在聲音傳感器周圍拍拍手,就會出現「你是在大聲什麼啦」的文字,如果不發出聲音,就會出現「偵測中...」的字樣。
如果近一點看傳感器,可以看到偵測到聲音的時候,上面有個小紅燈會亮起。
知道怎麼接收聲音傳感器的訊號並做動作之後,再來就是要控制智慧插座上的電燈了,如果 GND 只有一個,就必須要用麵包板外接,接線圖如下:
和人體紅外線偵測的做法幾乎一模一樣,一開始先在自己的網頁內引入「 webduino-min.js 」還有「 webduino-blockly.js 」這兩個 JavaScript,這樣我們才有操控開發板以及聲音偵測的 API 可以使用,在 body 的區域放入一個 h2 來顯示一些文字訊息,然後放入兩張燈泡一明一暗的圖片,讓偵測到訊號的時候,網頁上的燈泡也會發生反應。
<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>
再來就看看聲音偵測的使用方法,聲音偵測的宣告使用 getSound(board, pin)
,pin 是數位腳,例如接在 10 號腳就改為 10。
sound = getSound(board, 10);
偵測的方式使用 .on(event, callback)
,event 有兩種,一種是 detected
也就是偵測到訊號,另外一種是 ended
,有別於人體紅外線會有「延遲」,聲音偵測的傳感器是沒有延遲的,所以如果需要延遲,就必須要自己在網頁裡面完成。
sound.on("detected", function(){
//偵測到聲音的時候要做什麼事
});
sound.on("ended", function(){
//結束後會做什麼事
});
了解用法之後,可以按照下面的寫法,在偵測到有聲音就把顯示文字改為「你是在大聲什麼啦!」同時把實際的燈泡以及網頁的燈泡點亮,然後「經過一秒」( 這邊必須要寫在網頁裡 ),沒有偵測到人,就在把訊息換成「偵測中...」,同時把網頁燈泡和實際燈泡關起來。
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 )
因為是 Gif 動畫聽不到啪啪啪的聲音,不過應該看得出來是拍手啦!
每次只要用到聲音傳感器,都會想到金凱瑞演的「王牌天神」還有班。史提勒的「博物館驚魂夜」,裡面都有一個橋段用彈指開燈或是拍手開燈,其實透過聲音傳感器就能夠做到一樣的效果了喔。
參考資料