arrow-righthamburgerlogo-marksocial-facebooksocial-githubsocial-twitter
2019.01.30

Let's 顔面製造!第二弾! 歌うサンタ顔面ロボットを作ろう

へっぽこまるこ

まるこのロボット制作
 
   

みなさん、こんにちは!へっぽこまるこです!

今回は、クリスマスをいい感じに盛り上げてくれるサンタ(っぽい)ロボットを obnizとgoogle home miniでつくってみました!

少し遅めの(めっちゃ早めの)サンタクロースをご覧あれ〜!

以前に「Let’s 顔面製造!ダンボールとサーボモータで喋る顔面ロボットを作ろう」でつくった顔面ロボット(的なもの)を改造して作ってみます!

  1. 完成イメージ
  2. つくってみよう
    • サンタデバイス準備
    • ライブラリやら準備
    • 音源準備
  3. へっぽこプログラム
  4. 実行
  5. まとめ

完成イメージ

画像が表示できません

※LEDが結構強めに光っているので閲覧にはご注意ください

obnizでgoogle-home-notifierを使ってgoogle home miniから音源を再生します。 google-home-notifierは、スキル開発なしでgoogle homeにテキストを読ませたり、MP3などの音源が再生できたりするnode.jsのライブラリです。

再生された曲に連動して下唇に仕込んだサーボモータを動かして、 歌ってる感じにしてみます。

つくってみよう

### + obniz + sg90(顔面ロボの流用) + LED(顔面ロボの流用) + 顔デバイス(顔面ロボの流用) + ジャンパワイヤー(顔面ロボの流用) + 切ないクリスマスソングの音源 + 白のファー生地や赤いフェルトなど(デバイス装飾用)

macOS High Sierraの環境で進めます。

サンタデバイス準備

顔面デバイスをデコります。 毛足10cm程度のファー生地を裂いたものと、 赤いフェルトで適当につくった帽子をくっつけます。 IMG_2790.JPG

サーボモータとLEDをobnizに接続します。

obniz_servo_led.png

ライブラリやら準備

node.jsがインストールされてる前提で進めます。

ターミナルで以下のコマンドを叩きます。

1
2
3
4
5
6
7
8
9
10
11
12
13
//ディレクトリ作成&移動
$ mkdir santa
$ cd santa

//google-home-notifierとobnizのライブラリをインストール
$ npm install google-home-notifier
$ npm install obniz

//メインのプログラムファイルを作成
$ touch face.js

//音源格納用ディレクトリを作成
$ mkdir audio 

audioフォルダには音源のkurisumasusong.mp3を格納しておきます。

音源準備

google-home-notifierを使って簡単に曲を再生するには、 クリスマスソングが入ったMP3をネットにアップして、 URLを取得する必要があります。

今回は、n0bisuk先生のハンズオンで教えてもらった ngork+pythonを使った方法でホスティングします。

santa ディレクトリ配下で作業します。

$ python -m SimpleHTTPServer 8080

別タブで以下を実行します。

1
2
$ cd santa
$ ngrok http 8080

実行結果です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ngrok by @inconshreveable                                                                                                                (Ctrl+C to quit)

Session Status                online
Account                       nougami (Plan: Free)
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://84019d5b.ngrok.io -> localhost:8080
Forwarding                    https://84019d5b.ngrok.io -> localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              57      0       0.00    0.00    6.51    8.91

HTTP Requests

https://84019d5b.ngrok.io/audio/kurisumasusong.mp3 が音源ファイルのURLになります。

へっぽこプログラム

node.jsでプログラムを書きます。 (async/awaitはまだ勉強中・・・)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

const googlehome = require('google-home-notifier');
const language = 'ja';
const Obniz = require("obniz");

const obniz = new Obniz("××××-××××");

obniz.onconnect = async function () {
	var mouth = obniz.wired("ServoMotor", {signal:0, vcc:1, gnd:2});
	var leftLed = obniz.wired("LED", { anode:3, cathode:4 });
	var rigthLed = obniz.wired("LED", { anode:5, cathode:6 });

	mouthMove = async function (maxDeg, maxDegWait, minDeg, minDegWait) {
		await mouth.angle(maxDeg);
		await obniz.wait(maxDegWait);
		await mouth.angle(minDeg);
		await obniz.wait(minDegWait);
	}

	singMouth = async function () {
		//init
		await mouthMove(0.0, 1300, 0.0, 0);

		//く
		await mouthMove(40.0, 400, 0.0, 100);
		//り
		await mouthMove(40.0, 400, 0.0, 100);
		//す
		await mouthMove(40.0, 400, 0.0, 100);
		//ま
		await mouthMove(30.0, 80, 0.0, 100);
		//す
		await mouthMove(30.0, 80, 0.0, 100);
		//きゃ
		await mouthMove(50.0, 100, 0.0, 100);
		//ろ
		await mouthMove(30.0, 100, 0.0, 100);
		//る
		await mouthMove(30.0, 120, 0.0, 100);
		//が
		await mouthMove(40.0, 900, 0.0, 500);
	
		//な
		await mouthMove(40.0, 400, 0.0, 100);
		//が
		await mouthMove(40.0, 400, 0.0, 100);
		//れ
		await mouthMove(40.0, 400, 0.0, 100);
		//る
		await mouthMove(40.0, 400, 0.0, 100);
		//こ
		await mouthMove(40.0, 100, 0.0, 100);
		//ろ
		await mouthMove(40.0, 100, 0.0, 100);
		//に
		await mouthMove(40.0, 100, 0.0, 100);
		//は
		await mouthMove(50.0, 1300, 0.0, 500);
		
		//き
		await mouthMove(40.0, 100, 0.0, 100);
		//い
		await mouthMove(40.0, 100, 0.0, 100);
		//と
		await mouthMove(40.0, 200, 0.0, 100);
		//ぼ
		await mouthMove(40.0, 100, 0.0, 100);
		//く
		await mouthMove(40.0, 100, 0.0, 100);
		//の
		await mouthMove(40.0, 100, 0.0, 100);
		//こ
		await mouthMove(40.0, 170, 0.0, 100);
		//た
		await mouthMove(40.0, 170, 0.0, 100);
		//え
		await mouthMove(40.0, 170, 0.0, 100);
		//も
		await mouthMove(30.0, 1000, 0.0, 500);
		
		//き
		await mouthMove(40.0, 100, 0.0, 100);
		//い
		await mouthMove(40.0, 100, 0.0, 100);
		//と
		await mouthMove(40.0, 500, 0.0, 100);
		//で
		await mouthMove(40.0, 100, 0.0, 100);
		//て
		await mouthMove(40.0, 100, 0.0, 100);
		//い
		await mouthMove(40.0, 100, 0.0, 100);
		//る
		await mouthMove(40.0, 100, 0.0, 100);
		//だ
		await mouthMove(40.0, 100, 0.0, 100);
		//あ
		await mouthMove(40.0, 100, 0.0, 100);
		//ろ
		await mouthMove(40.0, 800, 5.0, 600);

		//く
		await mouthMove(40.0, 400, 0.0, 100);
		//り
		await mouthMove(40.0, 400, 0.0, 100);
		//す
		await mouthMove(40.0, 400, 0.0, 100);
		//ま
		await mouthMove(30.0, 80, 0.0, 100);
		//す
		await mouthMove(30.0, 80, 0.0, 100);
		//きゃ
		await mouthMove(50.0, 100, 0.0, 100);
		//ろ
		await mouthMove(30.0, 100, 0.0, 100);
		//る
		await mouthMove(30.0, 120, 0.0, 100);
		//が
		await mouthMove(40.0, 900, 0.0, 500);
	
		//な
		await mouthMove(40.0, 400, 0.0, 100);
		//が
		await mouthMove(40.0, 400, 0.0, 100);
		//れ
		await mouthMove(40.0, 400, 0.0, 100);
		//る
		await mouthMove(40.0, 400, 0.0, 100);
		//こ
		await mouthMove(40.0, 100, 0.0, 100);
		//ろ
		await mouthMove(40.0, 100, 0.0, 100);
		//に
		await mouthMove(40.0, 100, 0.0, 100);
		//は
		await mouthMove(50.0, 1300, 0.0, 500);
		
		//だ
		await mouthMove(40.0, 100, 0.0, 100);
		//れ
		await mouthMove(40.0, 100, 0.0, 100);
		//を
		await mouthMove(40.0, 400, 0.0, 100);
		//あ
		await mouthMove(40.0, 100, 0.0, 100);
		//い
		await mouthMove(30.0, 100, 0.0, 100);
		//し
		await mouthMove(30.0, 100, 0.0, 100);
		//て
		await mouthMove(30.0, 100, 0.0, 100);
		//る
		await mouthMove(30.0, 100, 0.0, 100);
		//の
		await mouthMove(40.0, 100, 0.0, 100);
		//か
		await mouthMove(30.0, 1000, 0.0, 500);
		
		//い
		await mouthMove(40.0, 100, 0.0, 100);
		//ま
		await mouthMove(40.0, 100, 0.0, 100);
		//は
		await mouthMove(40.0, 500, 0.0, 100);
		//み
		await mouthMove(40.0, 100, 0.0, 100);
		//え
		await mouthMove(40.0, 100, 0.0, 100);
		//な
		await mouthMove(20.0, 100, 0.0, 100);
		//く
		await mouthMove(20.0, 100, 0.0, 100);
		//て
		await mouthMove(40.0, 100, 0.0, 100);
		//も
		await mouthMove(40.0, 100, 0.0, 100);
		//お
		await mouthMove(50.0, 5000, 50.0, 0);
		for (i=49; i>=0; i--){
			await mouth.angle(i);
			await obniz.wait(80);
		}
	}
	
	google_home = async function() {
		googlehome.device('Google-Home', language);	
		await googlehome.play('http://×××××.ngrok.io/audio/kurisumasusong.mp3', function(res) {
			console.log(res);
			leftLed.on();
			rigthLed.on();
			singMouth();
		});
	}

	await google_home();
}

for (i=49; i>=0; i–){  await mouth.angle(i);  await obniz.wait(80); } ↑はこだわった部分なので、 注目してみてもらえると嬉しいです。

実行

サンタデバイスにgoogle home miniをそっと添えて、 以下のコマンドで実行します。

$ node face.js

サンタが歌ってる感じになります。

まとめ

哀愁漂うサンタクロースができたのではないでしょうか。

私にとって、スマートスピーカーは電子部品的存在なので、 今後も色々な作品に仕込んで、へっぽこなモノづくりに一役買ってもらおうと思っています。

よかったら是非「スマスピ + デバイス」挑戦してみてください!