はじめに
いまOTTOというArduinoベースのオープンソースロボットをobnizに移植する個人プロジェクトを進めています(IoTLT vol.54でLTしたやつです)。
OTTOには圧電スピーカーも搭載されており、これを使ってロボっぽいピロピロ音を出すことができます。
先日、この圧電スピーカーを使ってobniz版OTTOに今流行りのパプリカを歌わせてみました。
OTTOにパプリカ歌って踊らせてみた pic.twitter.com/6W8Zq1ncjT
— 田中みそ@LINE API Expertになりました! (@miso_develop) November 23, 2019
圧電スピーカーで音を鳴らすのは周波数を渡すだけととても単純だったので、これを応用してobnizと圧電スピーカーを使って普段コードを打ち込んでるキーボードをキーボード(音楽用)に変えてみたいと思います。
ハードウェア実装
まずは圧電スピーカーを用意します。
obnizのパーツライブラリページに秋月やSwitch Scienceの通販リンクがあります。
大きさとかで30円~100円と割と種類ありますが、なんでもいいと思います。
私は手元にあったやつを使いました。
このうち左下のやつは飛び抜けて音がでかかったため除外しました。
他のは大体同じ音量ですが、左上のは音が悪かったです。
そしてこれらをobnizに直挿しします。
ブレッドボードを使えば12個繋げられますが、obnizと言えばモーター然り直差しなので、このままいきます。
ソフトウェア実装
キーボードのイベント拾うならHTMLで実装するのが手軽ですが、画面上にキーボードの画像表示してどこが押されてるかとかの描画もないといけない感じがするので、HTMLは使いません。
代わりにNode.jsで実装します。
Node.jsでリアルタイムにキーイベントを拾うには↓のパッケージが良さそうです。
iohook
こんな感じでキーイベントだけでなくマウスポインターとかも拾えます。
'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と各スピーカーのピン番号を書き換えて実行してみてください。
"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()
}
キー割り当て
こんな感じで音程を割り当てています。
演奏してる様子
ひとまずドレミファソラシド。
obnizと圧電スピーカーでキーボードをキーボード(音楽)化した。 pic.twitter.com/zwrHBUTPmE
— 田中みそ@LINE API Expertになりました! (@miso_develop) December 4, 2019
スピーカー3つ繋いでるので3和音まで出せます。
(直差しじゃなければ12和音まで出せます)
スピーカー3つ繋げてるので3和音まで可。
— 田中みそ@LINE API Expertになりました! (@miso_develop) December 4, 2019
(3つめのスピーカー音悪し) pic.twitter.com/YmWEjWEhkQ
最後に一曲演奏してみます。
なんの曲かわかったらまじ神です。
ちなみに所々音出てないのは回路やパーツやプログラムが悪いわけではなく、多分指を離すのが遅くて3和音鳴ってる状態のまま次のキー押しちゃってるのが問題です。
つまり演奏が下手なだけです。
一曲弾いてみた。
— 田中みそ@LINE API Expertになりました! (@miso_develop) December 4, 2019
なんの曲か分かったらまじで神。
(所々音出てなかったりミスってたり…) pic.twitter.com/2KwPZphHS8
おわりに
ここまで書いてそもそもこれはIoTなのか疑問になりましたが、obnizはネットにつながってないと動かないのでこれはきっとIoT。