Help us understand the problem. What is going on with this article?

obnizと圧電スピーカーを使ってキーボードをキーボード(音楽)に変えてみた

はじめに

いまOTTOというArduinoベースのオープンソースロボットをobnizに移植する個人プロジェクトを進めています(IoTLT vol.54LTしたやつです)。
OTTOには圧電スピーカーも搭載されており、これを使ってロボっぽいピロピロ音を出すことができます。

先日、この圧電スピーカーを使ってobniz版OTTOに今流行りのパプリカを歌わせてみました。

圧電スピーカーで音を鳴らすのは周波数を渡すだけととても単純だったので、これを応用してobnizと圧電スピーカーを使って普段コードを打ち込んでるキーボードをキーボード(音楽用)に変えてみたいと思います。

ハードウェア実装

まずは圧電スピーカーを用意します。
obnizのパーツライブラリページに秋月やSwitch Scienceの通販リンクがあります。
大きさとかで30円~100円と割と種類ありますが、なんでもいいと思います。
私は手元にあったやつを使いました。

IMG_20191204_225038.jpg

このうち左下のやつは飛び抜けて音がでかかったため除外しました。
他のは大体同じ音量ですが、左上のは音が悪かったです。

そしてこれらをobnizに直挿しします。
ブレッドボードを使えば12個繋げられますが、obnizと言えばモーター然り直差しなので、このままいきます。

IMG_20191204_221332.jpg

ソフトウェア実装

キーボードのイベント拾うならHTMLで実装するのが手軽ですが、画面上にキーボードの画像表示してどこが押されてるかとかの描画もないといけない感じがするので、HTMLは使いません。
代わりにNode.jsで実装します。

Node.jsでリアルタイムにキーイベントを拾うには↓のパッケージが良さそうです。
iohook

こんな感じでキーイベントだけでなくマウスポインターとかも拾えます。

index.js
'use strict';
const ioHook = require('iohook');

ioHook.on("mousemove", event => {
  console.log(event);
  // result: {type: 'mousemove',x: 700,y: 400}
});
ioHook.on("keypress", event => {
  console.log(event);
  // result: {keychar: 'f', keycode: 19, rawcode: 15, type: 'keypress'}
});
//Register and stark hook 
ioHook.start();

あとは圧電スピーカーの制御コードをobnizのパーツライブラリからコピって、keydownで音鳴らしてkeyupで音止めるようにすればいいわけですね。

完成したコード

こちらが完成したコードです。
キーボードのキーコードとスピーカーで鳴らす周波数のマップオブジェクトを用意しています。
それと各圧電スピーカーの割当の制御とかも書いてます。
あとは上記で書いたような実装です。

npm install obniz iohookしたうえで、obniz IDと各スピーカーのピン番号を書き換えて実行してみてください。

index.js
"use strict"
const ioHook = require("iohook")
const Obniz = require("obniz")

const keymap = {
    "16": 370,  // F#3
    "30": 392,  // G3
    "17": 415,  // G#3
    "31": 440,  // A4
    "18": 466,  // A#4
    "32": 494,  // B4

    "33": 523,  // C4
    "20": 554,  // C#4
    "34": 587,  // D4
    "21": 622,  // D#4
    "35": 659,  // E4

    "36": 698,  // F4
    "23": 740,  // F#4
    "37": 784,  // G4
    "24": 831,  // G#4
    "38": 880,  // A5
    "25": 932,  // A#5
    "13": 988,  // B5

    "39": 1047, // C5
    "41": 1109, // C#5
    "27": 1175, // D5
    "26": 1245, // D#5
}

const obniz = new Obniz("xxxx-xxxx")
obniz.onconnect = async () => {
    const speakers = []
    speakers.push(  // スピーカーは繋げられるだけここに列挙
        { assign: 0, obniz: obniz.wired("Speaker", {signal: 0, gnd: 1}) },
        { assign: 0, obniz: obniz.wired("Speaker", {signal: 2, gnd: 3}) },
        { assign: 0, obniz: obniz.wired("Speaker", {signal: 4, gnd: 7}) },
    )

    ioHook.on("keydown", event => {
        if (!keymap[event.keycode]) return

        if (speakers.some(speaker => speaker.assign === event.keycode)) return

        for (const speaker of speakers) {
            if (speaker.assign) continue

            speaker.assign = event.keycode
            speaker.obniz.play(keymap[event.keycode])
            return
        }

    })

    ioHook.on("keyup", event => {
        if (!keymap[event.keycode]) return

        for (const speaker of speakers) {
            if (speaker.assign !== event.keycode) continue

            speaker.assign = 0
            speaker.obniz.stop()
            return
        }
    })

    ioHook.start()
}

キー割り当て

こんな感じで音程を割り当てています。

assign.png

演奏してる様子

ひとまずドレミファソラシド。

スピーカー3つ繋いでるので3和音まで出せます。
(直差しじゃなければ12和音まで出せます)

最後に一曲演奏してみます。
なんの曲かわかったらまじ神です。

ちなみに所々音出てないのは回路やパーツやプログラムが悪いわけではなく、多分指を離すのが遅くて3和音鳴ってる状態のまま次のキー押しちゃってるのが問題です。
つまり演奏が下手なだけです。

おわりに

ここまで書いてそもそもこれはIoTなのか疑問になりましたが、obnizはネットにつながってないと動かないのでこれはきっとIoT。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away