おもちゃすぐ無くなる問題をどうにかしたかった

## おもちゃ、すぐどっかいかない？

子育てしている方、今うなずきましたよね？
家の中なのに、おもちゃすぐどっかいく。

我が家も同じです。
片付けようとして、あれ、一個ない、、、
大抵、家具の下に転がってるんですよね。


転がってしまったおもちゃを検知して、教えてくれる、
そんな装置あったらいいなと思って、挑戦してみました。

## 使ったもの

*  Node-RED
*  LINE messaging API
*  obniz Board 1Y

###  パーツ

* サーボモータ
* 超音波距離センサー
* ジャンパーワイヤ
* ブレッドボード
* アンパンマンスプーン（おもちゃ）``（※子どもにバレないように拝借）``

**これが**
![S__136986628.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/b7b9be46-9b5b-7633-8cfd-de5eb958e053.jpeg)




**こうじゃ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/f8496914-a0c7-68d7-5b2e-235e34dae798.png)




一旦、**おもちゃレスキュー君**と呼ぶことにする。

## 完成したものがこちら
機能説明の前に、おもちゃレスキュー君を
実際に動かしてみます。（※家具の下想定でご覧ください）
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">昨日も今日も明日も、転がってどっか行ったおもちゃを探してるパパママへ、、<a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a><a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a><a href="https://twitter.com/hashtag/%E3%81%8A%E3%82%82%E3%81%A1%E3%82%83%E3%83%AC%E3%82%B9%E3%82%AD%E3%83%A5%E3%83%BC?src=hash&amp;ref_src=twsrc%5Etfw">#おもちゃレスキュー</a> <a href="https://t.co/LTtzknNj03">pic.twitter.com/LTtzknNj03</a></p>&mdash; そってぃ (@sotan115) <a href="https://twitter.com/sotan115/status/1721128006616506575?ref_src=twsrc%5Etfw">November 5, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


・・・シュールさが伝わったでしょうか。



## 機能説明

フローとポイントはこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/a9dac103-3535-415d-9368-ffaa4f0e3138.png)

JSON形式のコードはこちら
```JSON
[{"id":"6fdcdf499048cd44","type":"tab","label":"距離センサ","disabled":false,"info":"","env":[]},{"id":"8397f37c43316dec","type":"obniz-repeat","z":"6fdcdf499048cd44","obniz":"6302dade429ef22f","name":"","interval":"1000","code":"// 任意の秒数待つことができる関数\nconst sleep = (msec) => new Promise(res => setTimeout(res, msec));\n\nobniz.display.clear(); // クリア\nobniz.display.print('Resucue!'); //displayに表示\n\nmsg.payload = await obnizParts.hcsr04.measureWait();await sleep(2000); //2秒ごとに計測\n\n\nreturn msg;","x":90,"y":160,"wires":[["aa9752a1f08177c7","98ae2d617c6621c9"]]},{"id":"e9c0cc767c0ca9da","type":"debug","z":"6fdcdf499048cd44","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":490,"y":60,"wires":[]},{"id":"017938a4971ce8cb","type":"obniz-function","z":"6fdcdf499048cd44","obniz":"6302dade429ef22f","name":"","code":"msg.payload = \"finish\";\nawait obniz.wait(1000); \nobniz.close();\n\nreturn msg;","x":300,"y":60,"wires":[["e9c0cc767c0ca9da"]]},{"id":"ba5041654dbba1ae","type":"inject","z":"6fdcdf499048cd44","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":60,"wires":[["017938a4971ce8cb"]]},{"id":"1dd20dded68c6ab1","type":"BloadcastMessage","z":"6fdcdf499048cd44","name":"","x":610,"y":160,"wires":[["4ae44abb2ad8cf13"]]},{"id":"782d501e32cb772d","type":"template","z":"6fdcdf499048cd44","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"おもちゃが転がってきたぞ！","output":"str","x":420,"y":160,"wires":[["1dd20dded68c6ab1"]]},{"id":"aa9752a1f08177c7","type":"switch","z":"6fdcdf499048cd44","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"50","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":270,"y":160,"wires":[["782d501e32cb772d"]]},{"id":"5f6d5a7e9a6d0be7","type":"obniz-function","z":"6fdcdf499048cd44","obniz":"6302dade429ef22f","name":"","code":"// サーボモータ起動\r\nlet degrees = context.get('degrees') || 90;\r\ncontext.set('degrees', degrees);\r\n\r\ndegrees = 90.0;\r\n\r\nobnizParts.servo.angle(degrees);\r\n\r\nreturn msg;\r\n","x":220,"y":300,"wires":[["75243273789c256e"]]},{"id":"75243273789c256e","type":"template","z":"6fdcdf499048cd44","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"おもちゃレスキュー！","output":"str","x":480,"y":300,"wires":[["cc502902934414f9"]]},{"id":"400d110782383cdd","type":"obniz-function","z":"6fdcdf499048cd44","obniz":"6302dade429ef22f","name":"","code":"// サーボモータ起動（戻す）\r\nlet degrees = context.get('degrees') || 90;\r\ncontext.set('degrees', degrees);\r\n\r\ndegrees = 10.0;\r\n\r\nobnizParts.servo.angle(degrees);\r\n\r\nreturn msg;\r\n","x":260,"y":440,"wires":[["e6eada88e5d20ce8"]]},{"id":"e6eada88e5d20ce8","type":"template","z":"6fdcdf499048cd44","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"気をつけろよ！あばよ！","output":"str","x":440,"y":440,"wires":[["8fa1b84ec2105bec"]]},{"id":"cc502902934414f9","type":"BloadcastMessage","z":"6fdcdf499048cd44","name":"","x":690,"y":300,"wires":[["42981b72a0abbee6"]]},{"id":"8fa1b84ec2105bec","type":"BloadcastMessage","z":"6fdcdf499048cd44","name":"","x":670,"y":440,"wires":[[]]},{"id":"42981b72a0abbee6","type":"delay","z":"6fdcdf499048cd44","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":420,"y":360,"wires":[["400d110782383cdd"]]},{"id":"4ae44abb2ad8cf13","type":"delay","z":"6fdcdf499048cd44","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":440,"y":240,"wires":[["5f6d5a7e9a6d0be7"]]},{"id":"98ae2d617c6621c9","type":"debug","z":"6fdcdf499048cd44","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":210,"y":240,"wires":[]},{"id":"6302dade429ef22f","type":"obniz","obnizId":"xxxx-xxxx","deviceType":"obnizboard1y","name":"","accessToken":"","code":"obniz.display.clear(); // 画面を消去\r\nobniz.display.print('Hello obniz!'); // Hello obniz! と画面に表示\r\nobnizParts.hcsr04 = obniz.wired(\"HC-SR04\",{ gnd:0, echo:1, trigger:2, vcc:3 });\r\nobnizParts.servo = obniz.wired(\"ServoMotor\",{ gnd:9, vcc:10, signal:11 });"}]
```

前回の記事でも使用した、LINEmessagingAPIも使用しました。

https://qiita.com/sotan115/items/144383af5ed3aab445d8

### ①超音波距離距離センサーでおもちゃを検知

おもちゃレスキュー君を、よくおもちゃが転がる家具の下に設置し起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/f9b6e480-d0be-25d2-b1c4-3aae9d6168aa.png)

超音波距離センサーの前、5センチ以内に物を検知したら、
LINEBotにメッセージを送ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/faa866da-934e-e1a8-b619-759e74c940ad.png)


### ②サーボモータを動かして、おもちゃを救出

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/ebe1935a-c104-ec04-8cc3-365848e06e70.png)

サーボモータの角度を設定することで、くっつけたスプーンが動き、
その動きにより物を押し出し、家具の下から救出します。
同時に、LINEBotにメッセージを送ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/0d1baabd-5b4f-74ad-43d3-0b180939313d.png)

遊び心であの芸人さんのセリフを拝借しました。

### ③サーボモータを戻してLINEBotにメッセージを送る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/a36374a1-caba-611e-876e-ff205747566c.png)

サーボモータの角度を設定し直し、スプーンの位置を戻します。
そして、救出終了を告げるメッセージを送ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569867/e4fce30f-c620-1a09-4e0c-bea465a366aa.png)

遊び心であのタレントさんのセリフを拝借しました。


これで、転がってしまったおもちゃが救出されました。
**おもちゃレスキュー君、ありがとう！**


## どうにかしたかった（無念）

タイトル回収です。
上手くいかなかったことが多々ありました。

:::note alert
**超音波距離センサーが転がるスピードを捉えられず、目の前におもちゃが静止しないと反応しない。**
→センサーの目の前におもちゃを置くという荒業をせざるを得なかった。
:::

:::note alert
**おもちゃをすぐ避けないと、連続してセンサーが反応してしまう。
同じメッセージが連続して送られてしまう。**
→回避策として、計測の間隔を2秒ごとに行うようにしてみたものの、うまくいかず。
:::

:::note alert
**絶望的に工作センスがない。** 
→完成品を見て頂ければ分かる。
しかも、軽いものしか救出できない。
ピタゴラスイッチ的なものは一生無理と思ってる。
:::


命名センスもだろというお声は静かに受け止めつつ、
今回も、初心者の挑戦。
覚えたての知識でモノづくりをやってみました。

 obniz、すごいっすね。

音で知らせてくれたり、もっと広い範囲を検知できたり、
他のパーツと組み合わせたり、色々工夫してパワーアップできれば、
おもちゃを永遠探している私、そして世のパパママの救いになれるかな。。



ここまで、お読みいただきありがとうございました。