CodeZine(コードジン)

特集ページ一覧

Tessel 2で赤外線センサーを使って、人感チャイムを作ってみよう

Tessel 2ではじめるセンサー電子工作入門 第3回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/06/05 14:00
目次

スピーカーでチャイムを鳴らす

 スピーカーは電気信号を音(振動)に変える装置です。次は、このスピーカーをTessel 2のGPIOピンに接続して音を鳴らしてみましょう。ちなみにスピーカーは振動をあたえると電気信号に変換できるため、一種の振動センサーともいえます。

スピーカーとは

 機器の組み込み用途には、電圧をかけると変形する圧電素子を使った圧電スピーカーがよく使われますが、今回は一般的な、磁石とコイルを使ったダイナミック型の薄型スピーカーを利用しました。ダイナミック型スピーカーは、磁場内において電流が流れる導体に力が発生する、フレミングの左手の法則を利用したものです。

スピーカーとの接続

 音を鳴らすだけなら、スピーカーをTessel 2のGNDとGPIOピンに直接つなぐだけで可能です。ただ、今回はTessel 2とスピーカーの保護のために、抵抗とコンデンサを直列に接続しました。

 スピーカーは直流に対しての抵抗が小さく、大きな電流が流れる恐れがあります。そのため、100Ω程度の抵抗を直列に接続します。また、直流電圧はスピーカーを振動させるには不要なため、コンデンサを用いてカットしています。コンデンサとは電荷を蓄えたり放出したりするパーツで、直流を通さずに交流を通すといった性質があります。このような交流電流だけを通過させる目的に使うコンデンサのことをカップリングコンデンサと呼びます。

 今回は手持ちのパーツの都合で、10μFのコンデンサを利用しました。1~10μF程度のものが適当です。なお、F(ファラッド)はコンデンサ容量の単位で、数字が大きいほど容量が大きくなります。

スピーカーとの接続
スピーカーとの接続

 全体の回路図は、次のようになります。

全体の回路図
全体の回路図

音を鳴らすには

 スピーカーは、GPIOに接続して電圧をかけるだけでは音は出せません。音を鳴らすにはコイルを振動させないとならないため、コイルに流す電気信号に変化が必要です。そこで前回も用いたPWM出力を利用します。前回はPWM出力がONになる割合のデューティ比を変更して、LEDの明るさを変化させました。今回はPWM信号の時間間隔であるPWM周期を設定して、特定の周波数の音を発生させます。

 次のサンプルコードはPWM周期を440Hz、デューティ比50%のPWM信号を出力するものです。この出力にスピーカーを接続すると、440Hzの音が発生します。

index2.js
const bucketsJs = require('buckets-js'); // buckets-jsモジュール
const tessel = require('tessel');
const pwd = tessel.port.A.pwm[0]; // PWD対応ピンオブジェクト

// PWM周波数
tessel.pwmFrequency(440);

// デューティ比
pwd.pwmDutyCycle(0.5);

setInterval(() => {}, 1000);

 スマートフォンのチューナーアプリで計測すると、ちゃんと440ヘルツの音になっています。

チューナーアプリの計測表示
チューナーアプリの計測表示

音階のしくみ

 メロディーを奏でるためには音の高さと周波数を変える必要があります。ではどのような周波数に設定すれば、音階となるのでしょうか。

 ある周波数の音を基準として周波数の比で音階を定めることを音律といいます。今回は1オクターブを12等分する音律(平均律)を使って、周波数を設定します。平均律では先ほどの440Hzの音を音階のA(ラ)の音と定め、他の音の周波数を決定します。周波数の計算方法は、MIDI tuning standardなどを参考にしてください。

メロディーを奏でる

 音階の周波数がわかったところで、音階を鳴らしてみましょう。次のコードは0.5秒単位でドレミと鳴らすサンプルです。指定する周波数は計算では小数となりますが、Tessel 2では整数値でしか周波数を指定できないため、小数点以下を切り捨てた値にしています。

index3.js
const tessel = require('tessel');
const pwd = tessel.port.A.pwm[0]; // PWD対応ピンオブジェクト

tessel.pwmFrequency(261);         // ド(C4)
pwd.pwmDutyCycle(0.5);
sleep(500).then(() => {
  tessel.pwmFrequency(293);       // レ(D4)
  pwd.pwmDutyCycle(0.5);

  sleep(500).then(() => {
    tessel.pwmFrequency(329);     // ミ(E4)
    pwd.pwmDutyCycle(0.5);
    sleep(500);
  });
});

// 指定時間後にresolveが実行されるPromiseオブジェクトを返す(1)
function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

 このコードのポイントは2つあります。

 1つは、周波数を変更する処理です。必ずpwmFrequency、pwmDutyCycleメソッドの順にセットで実行する必要があります。

 2つ目は、Node.jsでの同期処理の書き方です。サンプルでは指定時間後にコールバックされるようなPromiseオブジェクトを返すsleepメソッド(1)を定義しています。Promiseオブジェクトのthenメソッドで次の処理を指定することにより、処理が同期的に実行されるようにしています。

人感センサーでチャイムを鳴らす

 では最後に、人を検知するとチャイム(メロディー)を鳴らすようにしてみましょう。サンプルコードは次のようになります。

 サンプルではメロディーのデータ保存用に、buckets-jsモジュールのQueueクラスを使用しています。サンプルコードを実行する前に、コマンドプロンプトからnpm install buckets-jsと実行して、モジュールをインストールしておきます。

index4.js
const bucketsJs = require('buckets-js');  // buckets-jsモジュール
const tessel = require('tessel');
const pin = tessel.port.A.pin[2];         // ポートAの2番ピンのオブジェクト
const pwd = tessel.port.A.pwm[0];         // PWD対応ピンオブジェクト

// 演奏用キュー
var play_queue = null;

// ピンの入力電圧ONでチャイムを鳴らす(1)
setInterval(() => {
    pin.read(function(error, value) {
    if ((value==1) && !play_queue) {      // 入力電圧ONかつ演奏中でないなら
      play_queue = set_melody();          // メロディーデータの設定
      play(play_queue);                   // 演奏
    }
  });
}, 1000);

// メロディーデータ(周波数と長さのセット)のキューを返す(2)
function set_melody() {

  // 四分音符の長さの定義
  const bpm = 60*1000/160;

  // メロディーデータの設定
  const melody = new bucketsJs.Queue();
  melody.enqueue([740,1*bpm]); // F#5
  melody.enqueue([587,1*bpm]); // D5
  melody.enqueue([440,1*bpm]); // A4
  melody.enqueue([587,1*bpm]); // D5
  melody.enqueue([659,1*bpm]); // E5
  melody.enqueue([880,3*bpm]); // A5
  melody.enqueue([659,1*bpm]); // E5
  melody.enqueue([740,1*bpm]); // F#5
  melody.enqueue([659,1*bpm]); // E5
  melody.enqueue([440,1*bpm]); // A4
  melody.enqueue([587,4*bpm]); // D5

  return melody;
}

// 指定時間後にresolveが実行されるPromiseオブジェクトを返す
function sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// キューからデータを取り出し、1音の周波数、長さをPWMに設定する(3)
function play(q) {
  if (q.isEmpty()) {            // キューが空なら
    pwd.pwmDutyCycle(0);        // PWM出力を停止する
    play_queue = null;
    return;
  }
  var note = q.dequeue();
  tessel.pwmFrequency(note[0]); // 周波数を指定する
  pwd.pwmDutyCycle(0.5);
  sleep(note[1]).then(() => {
    play(q);                    // 再帰的に呼び出す
  });
}

 人感センサーの出力状態をsetIntervalで1秒ごとに判定し検知した場合は、演奏中でない(変数play_queueがnull)なら、メロディーデータを設定して演奏を開始してます(1)。キューのモジュールを使うと、onメソッドがうまく動作しなかったため、このような形にしています。

 メロディーデータは、周波数と1音の長さを1組として、キューに保存しています(2)。

 playメソッドではキューからデータを取り出し、1音の周波数、長さをPWMピンに設定しています(3)。このメソッドのポイントは、再帰呼び出しです。Promiseオブジェクトのthenメソッドでplayメソッド自身を指定することにより、キューのデータを同期的に処理するようにしています。キューが空になった時点で、再帰呼び出しを終了します。

 サンプルを実行すると次の動画のようになります。

最後に

 今回利用した赤外線センサーモジュールは、まさにスイッチ代わりなので、チャイムを鳴らすだけでなく、いろいろなものに使えそうです。例えばUSBカメラを接続して、人を感知したときだけ画像を撮影するようにすれば、防犯カメラにもなるでしょう。この連載で紹介したように、Tessel 2に標準モジュールだけでなく、さまざまなセンサーを接続すれば、IoTデバイスとしての活用範囲が大きく広がるのではないでしょうか。

参考資料



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Tessel 2ではじめるセンサー電子工作入門

著者プロフィール

  • WINGSプロジェクト 高江 賢(タカエ ケン)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5