はじめに
スノードームという、手で動かして雪が降っているような様子を楽しむ置物ありますよね。あの雪(っぽい物)をobnizを使い、手を動かずに降らすことができないか挑戦しました。
作るぞ
まずはスノードームを作る
100均で購入したツリーの木とプラスチックの容器でスノードームを作りました。
雪っぽいものがなかったのでスパンコールにしました。そのため、雪ではなく星を降らします。
スノードーム ver 1.0 試運転①
さきほどのスノードームをLEGOで作成した回転台に設置し動作テストを行います。
想定通りの動作をしました、いい感じです。
スノードーム ver 1.0 試運転②
スノードームにおくメインの木を設置しての動作テストです。12月なのでクリスマスっぽいものにしました。
出力を上げての動作テストです。問題なさそうです。
スノードーム ver 1.0 本番
動作テストがおわったので本番です。出力50%でやってみます。
う~ん、星にみたてたスパンコールが底面にたまって水中を舞ってくれない。これではモーターで回転させている意味がない。
出力100%でモーターを回転します。
だめだ、スパンコールが底面でゆらゆら動くだけ。星にみたてたスパンコールが落ち葉に見えてきた。
スノードーム ver 2.0
もっと水をかき混ぜるよう、木のおもちゃを変更しました。おもちゃを変更した影響で容器も一回り大きくなりました。弱回転で試運転します。
出力50%、少し回転を上げます。スパンコールが木の葉のようにゆらゆらとゆれてます。
出力80%、容器の半分くらいまでスパンコールが舞いました!でも、構造が耐えられずグワングワンしてる。
スノードーム ver 3.0
出力100%でモーターを回しても耐えられる構造に作り直しました。容器の中に水を入れずに試運転します。
スノードーム ver 3.5
構造を少し変更。動力部(モーター)と制御部(obniz)を上部に移動し、容器の中の水が漏れても被害を最小限にします。
スノードーム ver 3.5 『水100%』 で運転
容器に水をいれての運転です。動画後半は出力100%でモータを回転させています。構造を強化したおかげで軸があまりぶれていません(よかった)。
スノードーム ver 3.5 『水のり1本追加』 で運転
水中に舞ったスパンコールがふわっと落ちるようにしたく水のりを1本分追加しました。水の粘性が上がったためか、構造が若干グラグラしています。スパンコールの滞水中時間はあまり変わってないような、、
スノードーム ver 3.5 『水のり2本追加』 で運転
1本で足りなかったので、2本目投入です。
運転してみます。スパンコールの滞水中時間が"気持ち"長くなった気がします。連続運転すると構造が壊れてしまうため、水のりのこれ以上の投入はやめました。また、定期的にモーターを停止し、スパンコールのヒラヒラを楽しめるようにしました。
[完成] 常に星ふるスノードーム
クリスマスっぽくライトアップして完成です。
ソースコード
ソースコードです。obnizの制御プログラムを作成はWebサイト https://obniz.com/ja/console で作成/実行ができるので便利です。
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"
></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"
></script>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
/>
</head>
<body>
<h3 id="bploading" style="text-align:center;">ロード中...</h3>
<div id="OBNIZ_OUTPUT"></div>
<br />
<script
src="https://unpkg.com/obniz@latest/obniz.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/iothome/index.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/airobot/index.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ui/index.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/howler2.1.2/howler.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/opencv3.4/opencv.js"
crossorigin="anonymous"
></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.3.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet@2.1.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/posenet@2.2.2"></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/clmtrackr/clmtrackr.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/clmtrackr/emotion_classifier.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/clmtrackr/emotionmodel.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/clmtrackr/model_pca_20_svm.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/ai/index.js"
crossorigin="anonymous"
></script>
<script
src="https://unpkg.com/obniz-parts-kits@0.16.0/storage/index.js"
crossorigin="anonymous"
></script>
<script>
$("#bploading").text("実行中");
(async function(){
var obniz, dcmotor, rotateFlg, lpFlg, slider, targetVal;
obniz = new Obniz('{{obnizのID}}');
await obniz.connectWait();
obniz.display.clear();
obniz.display.print('Hello, World!')
dcmotor = obniz.wired("DCMotor",{"forward":0, "back":1});
rotateFlg = 1;
lpFlg = 0;
slider = new ObnizUI.Slider();
while (true) {
await ObnizUI.Util.wait(0);
targetVal = slider.getValue();
for (var count = 0; count < 2; count++) {
await ObnizUI.Util.wait(0);
obniz.display.clear();
obniz.display.print(targetVal)
if (rotateFlg == 1) {
dcmotor.move(true);
} else {
dcmotor.move(false);
}
dcmotor.power(targetVal);
await ObnizUI.Util.wait(300);
}
lpFlg = (typeof lpFlg == 'number' ? lpFlg : 0) + 1;
rotateFlg = rotateFlg * -1;
if (lpFlg == 5) {
dcmotor.stop();
await ObnizUI.Util.wait(2000);
lpFlg = 0;
}
}
})();
</script>
</body>
</html>
おわりに
『星降る』というより『落ち葉舞う』の方がふさわしい出来になりました。また、モーター音がうるさくスノードームの優雅な雰囲気にはなりませんでした。と、いろいろ課題はありますが及第点はとれたことにします。
スノードームみたいに静かで優雅にひらひらと雪が落ちる仕組みを思いついたらまた挑戦しようと思います。