12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-12-05

はじめに

いま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。

12
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?