OGIMOノート~家族のためのモノづくり~

OGIMOテックノート ~家族のためのモノづくり~

重度障害の息子を持つ父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具/ロボット関係の製作記録、思った事を残していきます

ワンスイッチ操作で演奏できる 「打楽器ハンド(効果音付)」を作ってみた

f:id:motokiinfinity8:20200301215940j:plain

はじめに

今年の目標の一つである
『友達と一緒に楽器演奏するためのサポート機器作り』

製作のきっかけは、障害を持ったお子さんのご家族・友人らのSNS投稿。
「お友達と一緒に楽器演奏をしたがっている」
「手を上手に使えなくても、タンバリンやドラムを叩ける様になりたい!」
「自分の力でリモコンのスイッチを押したい」

を実現すべく市販機器を改造して試行錯誤されている様子を何度も拝見してきました。

「自分の意志でモノを押したい、自分で音を奏でる体験を作りたい」

当たり前にモノを押せる人達には気づきにくいニーズ。だからなのか、、、それを実現する様な市販品ってあまり見かけない……


一方で、電子工作の世界では、モノを叩く技術ってサーボモーターという基礎技術で実現できる可能性があります
(電子工作のスタートでLEDの次に使うのがサーボモーターだと思ってるくらい)

せっかくMaker業界では当たり前に実現可能な技術があるのに身近な生活の場面に浸透していないのが課題、と思って……

それならいっそ作ってしまおう!

というのが、製作モチベーションでした!

そこで、様々な楽器の中でも、まずは一番シンプルかつ全身でリズムを感じらる打楽器にチャレンジしたいと思います!


要求仕様

ただ「楽器を叩く」だけではなく、
「キレイな音を出せる」「設置設定がかんたん」「子供がつい遊びたくなる」体験を目指して
・重いバチも保持できる様な強力さ
・楽器&本体を簡単に取り付け & 位置調整できる
・叩いたときに、面白い効果音や光効果を加える遊び心

を実現ターゲットにしたいと思います。


完成品

上手に手が動かない子供でも、スイッチを使ってタンバリン・ハンドベル等を演奏できる簡易打楽器ハンドを作ってみました!

アーム部のアタッチメントを変更すれば
・タンバリン
・ドラムセット
・ドラム缶
ハンドベル

など、比較的 重たい楽器でも叩いたり振ることも出来ます!

また、音を奏でる楽しさを感じて貰うため、叩く瞬間に【楽しい効果音】を加える様な遊び心も加えてみました♪
効果音をうまく使えば、笛やブブゼラ、法螺貝など実際に吹くのが難しい楽器も雰囲気吹いてる感も出せるかも(笑)


あとは、設置の工夫として、
・楽器の位置調整を簡単にするため、アームの打点位置を調整する機能を追加
車椅子用ユニバーサルアーム/ビックグリップ/カメラ用三脚を取り付け出来る様にして、自由な角度・位置調整を簡単に出来る様にした
・車椅子に取付けできる様に単3電池駆動に変更
など、「使いやすさ」を意識して改良してみました。


また、あわせて、OriHimeと組み合わせた『遠隔楽器演奏システム』への活用も検討中です。
一旦、Blynkアプリを使って 4G回線経由でスマホから遠隔操作できる様にしてみましたが、我が家以外で活用してもらう事を想定した場合、ソースコード内にアカウント情報を埋め込まなければならない現手段では限界があるので、そこは改善を検討しています。
今後をお楽しみに(^-^)

全体システム

まず、「叩く機能の根幹であるサーボモータは以下を選定しました。

akizukidenshi.com

11kg/cm(6.0V)で価格1000円台というコスパの良いサーボモータ。ただし、副作用としては動作時に大電流(1A)を流してしまうので、マイコンと同一電源にした場合にラッシュ電流により電圧降下が発生してしまい、マイコンハングを起こしてしまう事が実際に起こります。
それを防ぐため、マイコン電源にピークホールド回路(電圧を長時間保持する回路)を組みます。
具体的には、マイコン側電源にダイオード追加+1000uF以上(今回は4700uF)のコンデンサ追加」を実施します。


[参考記事]
hiyokko-hard.com


マイコンは今回、スマホ非対応版 : Arduino Pro Mini(3.3V)」「スマホ対応版: ESP32 Dev-Kit C」を使用しました。
音源再生は、いつもの「DFPlayer Mini+スピーカ」になります。


回路図イメージは以下になります。

f:id:motokiinfinity8:20200302014951j:plain


ハードウェア

今回工夫したのは筐体設計です。使い方としては、以下の様な車椅子に取り付け可能なユニバーサルアームへ付ける事を想定しました。

調査した結果、取り付け先端としては大きく以下の3つに対応したら良さそうです。
・車椅子用アームスマホホルダー
横幅110mm以内
・大型クリップを付ける事ができる
厚み25mm以内
・カメラ用三脚ネジ
三脚ネジ(メス)を追加できるスペース

上記を満たす形になる様にFusion360で筐体を製作しました。

f:id:motokiinfinity8:20200302021042p:plain

なお、三脚ネジは以下を使用して、インサートナットの様にして埋め込みます。


スマホホルダーへ取り付け
f:id:motokiinfinity8:20200301220237j:plain
f:id:motokiinfinity8:20200301220251j:plain

・大型クリップへの取り付け
f:id:motokiinfinity8:20200301220325j:plain

・カメラ三脚ネジへの取り付け
f:id:motokiinfinity8:20200301220351j:plain

・筐体内部の手作り基板
f:id:motokiinfinity8:20200301220514j:plain




まとめ

息子氏に使って貰ってみたところ、いろんなモノを楽器にして叩いて遊んでくれていました!
また、モニターとして数名の方(障害を持ったお子さんの家庭)へ試作品を提供して、実際に効果検証を進めているところです!

身体をうまく使えず楽器を上手く鳴らせなくても、この様な支援機器を使えば、
「できない」を「できる」に変える
「友達と同じ体験を共有できる嬉しさ」を作る可能性を秘めた、
『シンプルなHuman Augmentation技術』なのかもしれないなぁ、と思います。


そして、最初は「サーボーを動かしたら簡単に実現できるんだろうな」と思って始めましたが、
実際は「キレイな音を鳴らす」「簡単に設置できて使える」には多くのハードルがある事もよく実感出来ました!
頭の中の想像で終わらせるのでなく、実際に手を動かしてみたからこそ分かる課題、この積み重ねがノウハウになるんだと思います。
(やはり、「自分の手を動かす事」は大事ですね)


今後ですが、モニター数名による実証効果がありニーズがありそうならば、
キット化などの手段で困ってる方々の手元にご提供できるレベルまで進化させて見ようかと思います! (手段は検討中ですが)


もしご興味のある方がいれば、ご連絡頂けますと大変嬉しいです!

知育玩具「くるくるチャイム」をデジタルおもちゃに改造してみた

f:id:motokiinfinity8:20200215164412j:plain

はじめに

今年の開発テーマの一つである
「息子の好きな斜面転がしを活かした遊びを考える」


現在、リハビリで長期入院中の息子。毎日、自由時間は病院内のおもちゃで遊んでますが、さすがに同じものを繰り返しになると飽きてきてる様子…
   
その中でも、今はボールを転がすおもちゃ等が大好き!!
ただ、息子は好きすぎると興奮してしまい、積み木等で作ったレーンもすぐ破壊、最後までボールが転がらないので、息子もストレスたまる様子。。。
  
そこで、「ボールが確実に転がる(レーンを壊さない)おもちゃ」として目を付けたのが、
『くるくるチャイム』という昔からあるおもちゃ

くもん くるくるチャイム (リニューアル)

くもん くるくるチャイム (リニューアル)

  • 発売日: 2017/05/31
  • メディア: おもちゃ&ホビー
    
これならボールをいれると確実に最後まで転がる!!

しかし……
このおもちゃは ただ転がるだけ、最後にベルが「チーン」と鳴るだけという刺激も少なめな仕様。息子も数回すると飽きてしまっていた……

惜しい!!
これにせめて、楽しい音が鳴れば……

妻と二人で頭を悩ませたところ、妻が「作って欲しいなぁ…」と一言。

そう
なければ自分で作るしかない!!
   
という訳で、「くるくるチャイム」の良さを活かしながら、息子好みの刺激たっぷりのおもちゃにアップデートするべく試行錯誤しました!



要求仕様

刺激を加える要素として、

・「光」と「音」のエフェクトを追加
・ボールの転がり状態を強調した様な演出

完成品

斜面+光+音楽 という、息子の大好物の三コンボを取り込んだ新しいおもちゃが誕生しました!

一時退院中に息子に使って貰ったら、めちゃくちゃ気に入ってくれて、気がつけばエンドレスで遊び続けてくれてた!
なかなかのヒット製品になって、これはすごく嬉しい!
   
こういう個人の好みにダイレクトに突き刺す事ができるのは、イカーものづくりの最大の強みですね!



全体システム

一番の悩みは、くるくるチャイムの限られた空間内でのボール位置検出

本オモチャですが、ボール幅と筐体サイズがちょうどキレイに収まる設計になっています。そのため、レーン沿いに配線一本を追加で通すだけでボールが転がらなくなるという点に悩みました。その結果、ボールの転がらない底面のみで回路系を完結させる手段を取りました。くるくるチャイムの底部にToFレーザー型の測距センサーを埋め込み、ボール高さを検知して、その高さに応じてLEDテープ& 効果音を変更するという追加工作を実施。幸いな事に底面内部は筐体内にスペースあったので、電池以外の全回路を埋め込む様に小型化しました。

f:id:motokiinfinity8:20200215165446j:plain

ハードウェア

回路図は以下になります。

f:id:motokiinfinity8:20200215171402j:plain

技術そのものは過去に製作したモノの組み合わせで、個人的に定番デバイスの組み合わせになります。


・ボール位置検出 : ToFセンサ LX53V0
・音声再生 : DF Player Mini
・LEDテープ : NeoPixel WS2812B

■ToFセンサ/LEDテープを使った過去作成例
ogimotokin.hatenablog.com
■音声再生モジュールを使った過去作成例
ogimotokin.hatenablog.com


これらを束ねるマイコンですが、今回は、
無線非対応でOKな事、筐体内に格納できるコンパクトさを踏まえて
Arduino Pro Micro」を使う事にしました。

その結果、以下の筐体内に収める事ができました。

f:id:motokiinfinity8:20200215173145p:plain

Arduino Pro Micro

私は以下の5V16MHz品を良く使います。安いものであれば、1個500円以下なので気軽に試せるのが魅力です。
マイコンはATmega32U4で、USBコネクタを備えているので、気軽にUSB HIDデバイスを使うのに適しています。

Arduino Pro Microの書き込み方法等は以下のサイトを参考にしています。

ht-deko.com

書き込みはArduino Leonardo」を選択してやればOKです。


ソフトウェア

ソースコードは以下のGithubにアップしてます。

github.com

5つの距離閾値(START_DIST /MODE*_DIST)を設定してやって、その距離閾値を跨いだ場合にモードが遷移するというシンプルな仕組みになっています。

終わりに

普通の市販品おもちゃの特徴・良さを生かしつつ、その子の大好きな音や演出にちょっとだけ手を加えてやるだけで、「その子専用の魅力あふれるおもちゃ」が出来上がります!
市販品がうまく使えない息子がいたからこその、新しいメーカー的なおもちゃの可能性を感じる事をができました。

他のおもちゃでも同じ様な取り組みは展開していけそうなので、おもちゃ屋で色々と次のネタを探してみたいと思います!

【まとめ】2019年ふりかえり ~家族のためのモノづくり~


棚卸しの意味も込めて、作ったモノ観点で 2019年を振り返り。
 
『息子のために、家族のために、誰かのために、
 自分の技術を生かしたモノを作りたい!』

 
という決意をした2年目。
とにかく手を動かし続け、気が付けばメジャーなモノだけで
【29個】ほど作りました。

1カ月で2~3作品というハイペース。ちなみに、2018年は【21個】だったので、去年より製作ペースが上がってる!

たくさん数を作る事自体は目的ではないけど、
子供向け(特に息子向け)の機器は何が本人にヒットするか分からないため、
「作っては試すを高速に繰り返して息子の出来るを見つけよう」
という方針で取り組んできたので、その取り組みに対する一つの定量値と考えると素直に良かったかなぁ、と思ってます


以下、2019年度の製作物について、ジャンルごとに分類してみました。

★は特に思い入れ深いモノ


息子のためのモノづくり ~移動/モビリティ編~

(1-1)歩行リハビリを楽しくするメロディ靴 [1月] ★

息子の歩行リハビリのモチベーションを上げるために開発した「歩くと息子の好きな音が鳴る&光る靴」
2018年初頭から取り組み改良を続けて1年。
何度も試行錯誤を続けた結果、息子が歩行器に乗り足を左右交互に出せる様になりました!!

製作記事は以下
ogimotokin.hatenablog.com

また、本内容に関して、8月放送の『めざましテレビで放送頂きました (別記事にてご紹介)



(1-2) 息子用電動モビリティMottoy改造 [8月]

足の不自由な息子が電動機器を使って自由に動くための練習環境を作る取り組み。
子供用電動機器"Mottoy"を息子が気に入る様に改造。
2月に低速対応改造、6月に電車コントローラ対応、8月にLED+音声搭載 と随時バージョンアップしていった。


製作記事はこちら
ogimotokin.hatenablog.com

製作には、ESP32 dev C を使ってます



(1-3) バギー電動化のための車椅子 on 台車ユニット製作 [9月] ★

息子の電動車椅子の操作練習のため、普段の椅子を電動移動機器にする取り組みをしてみた。
椅子(後輪)を台車に乗せ、無線コントローラで操作すれば、お気に入りの椅子に乗ったまま自分の意志で移動できる!

ずっと作りたかったモノの一つ。モビリティ製作の経験がなく、作り方が分からず手が止まってしまってましたが、後述する『木材DIYで作った車椅子 on 車椅子』の製作に携わったおかげで、心のハードルが下がり、無事に自作製作までたどり着けました! 人とのご縁、本当にありがたい…

製作には、ESP32 dev C を使ってます



(1-4) 電動車椅子のワンスイッチ化ユニット [10月] ★

(1-3)は屋内限定のため、屋外でもスイッチ操作による電動移動機器の練習をするため、市販の電動車椅子の操作スティックを物理ハックするユニットを製作しました!

サーボモータの制御というシンプルテクノロジーで作る新たな価値! 一部では評判になっている様です。
このおかげで息子も少しずつ電動移動に慣れてきた! 良い感触のため、どんどん改良&実証中です!

製作には、Arduino Pro Microを使ってます



(1-5) 動くと光る&楽しい音が鳴るイルミネーション歩行器 [6月~]

(1-1)で製作したメロディ靴の簡易版。こちらは歩行器の移動有無を加速度センサで検出して動いた時だけ音が鳴る&光る機能を搭載。(1-1)で一旦は左右交互に足を出せる様になったものの、モチベーションが上がらない時は相変わらず歩行器は嫌がる息子。歩行器で動きたくなる様なモチベーションを更に高めるための試行錯誤を実証中。

こちらは現在も進行形。メロディを変えたり、光を変えたり、と、奮闘中!
製作には、M5Stack を使ってます




息子のためのモノづくり ~おもちゃ/スイッチ/ゲーム編~

(2-1) 息子の好きなおもちゃ二輪走行ロボットをハック改造 [4月] ★

息子のジョイスティックの操作練習を楽しく進めるため、息子の大好きな二輪走行ロボット「バイリンガルモビ」を無線コントローラで操作できる様に改造しました。

製作して以降、息子は気に入ってくれて、良くスティックを触って、ロボットを動かしてくれてます!
製作には ESP32 dev kitxを使ってます。



(2-2) ジョイスティック以外の操作感実験/ やわらかリモコン[5月]

やわらかい触感のするコントローラでロボット操作を行う実験取り組み。妻の羊毛フェルト製作とのコラボ。息子へのウケはいまいちだったが、MFKにて展示したところ、女性陣のウケは良かった~

製作には、M5Stack + ショッカクポット を使ってます



(2-3) 電車でGo!で動くプラレール[6月]

最近電車&プラレールが好きになった息子が「自分の意志で操作する」機会を広げる事を狙った製作物。改造した「電車でGo!コントローラ」でプラレールの加減速を制御してます!

製作には、M5StickC(プラレール側) + ESP32 dev C (コントローラ側) を使ってます




(2-4) オモチャコントローラの本気ハック [9月]

息子の愛してやまない『ゲームコントローラ風おもちゃ』で、ロボットやモビリティ等を操作できる万能コントローラに改造!

製作には、ESP32 dev C を使ってます




(2-5) 100均グッツで作る自作スイッチ一式 [10月]

スイッチ製作の勉強も兼ねつつ、息子が押しやすいスイッチを色々と試行錯誤してみた。12月には障害児のきょうだいによるスイッチ製作ワークショップの実験もしてみた。

製作記事の一例はこちら
ogimotokin.hatenablog.com




(2-6) ボタンを押すと暴走するワンワン改 [8月]

息子が自分の意志でスイッチを押したくなる様な、刺激倍増のおもちゃ改造!

展示会に出展しても、何気にいつも一番人気だったりします!シンプルテクノロジー万歳。

製作記事はこちら
ogimotokin.hatenablog.com




(2-7) 壊れたおもちゃを再復活!? 二足歩行ベアビーボ君 [2月]

息子が遊び倒して壊してしまったおもちゃを二足歩行できる様に魔改造してみた。残念ながら息子の食いつきはいまいち(笑)しかし、他の子供たちには人気! やはり二足歩行は見てて楽しいよね。

しかし、最終的には、MFK展示会での出展中に壊れてしまい、そのまま部品取りしました。 いつかリベンジしたいなぁ。
製作には、V-duino を使ってます





(2-8) 物理スイッチで操作できるNintendo Switchコントローラ [11月] ★

Nintendo Switch大好きな母&娘に混ざり、息子も一緒にゲームで遊べる事を目指して、色んなスイッチを取り付けれるNintendo Switchコントローラを作った。

ゲームの楽しみ方を広げる可能性の秘めたコントローラ、2020年でも色々と実証してみよう!

製作記事はこちら
ogimotokin.hatenablog.com

製作には、M5Stackを使ってます




(2-9) 楽器の『音』がスイッチになる! タンバリンスイッチ [12月]

(2-8)のNintendo Switchゲームコントローラの楽しい遊び方の実験の一つ。『太鼓の達人』をタンバリンで遊んじゃえ!

リアルな楽器→ゲーム上の楽器音に変換される新鮮な体験が面白い!

製作記事はこちら
ogimotokin.hatenablog.com

製作には、M5StickCを使ってます



家族のためのモノづくり

(3-1) お父さん予定をリビングに表示するスケジューラロボット [3月]

単身赴任中のお父さんの大阪↔東京の滞在予定(google Calendar)をリビングに表示・通知するシステムを作りました。

製作記事はこちら
ogimotokin.hatenablog.com

製作には、M5Stackを使ってます



(3-2) 「今から帰る」の帰宅連絡を簡易化する遠隔通知システム [4月]

会社から帰宅する際の「帰る」のメッセージ連絡を自動化&簡易化するため、スマホから「帰宅ボタン」を押す or GPSで自宅近くに戻ってくるとリビングにある液晶ロボットがお知らせしてくれるシステムを製作しました。

初めてBlynkアプリを使ってみた事例になります。ここからM5Stack+Blynkの連携をいくつか試していく事になりました!

製作記事はこちら
ogimotokin.hatenablog.com





(3-3) 分身ロボット操作時の遠隔呼出しシステム [5月]

昨年11月から使わせて頂いている分身ロボットOriHime。足の骨を折ってしまい外出できなくなった妻に分身ロボットによるMaker Faire Kyotoでの展示説明員をお願いした際、会場から自宅への『呼び出し』を簡易に実施するためのBlynkを使った呼び出しシステムを製作しました。

製作記事はこちら
ogimotokin.hatenablog.com

製作には、M5Stackを使ってます



(3-4) 分身ロボットOriHimeの全方位移動オムニ台車 [6月]

単身赴任先から娘&息子と遠隔操作で鬼ごっこ等をするために製作しました。カメラ&音声通信は分身ロボットOriHimeを使用し、移動台車+遠隔制御部を自作。Blynkを使いスマホで台車を操作できる様にしました。


この機体を使って、Maker Faire Tokyoでサッカーで遊んでみたり、分身ロボットサッカーの集まりに混ぜて貰いました。

製作には、M5Stackを使ってます



(3-5) 息子の刻み食を簡単にするためのハサミ&キャップ

噛む事が苦手な息子の「刻み食」を特に外出先で簡単に調理するための工夫。100均ショップで購入したシュレッダーはさみに加えて、はさみ間に詰まった食材を簡単に取り除けるキャップを3Dプリンタで作りました。

3Dプリンタがあれば、個人のニーズに適したその人専用自助具が作れる! 3Dプリンタによる障害支援具の可能性を感じました!


友達のためのモノづくり

(4-1) ワンボタンで操作できるじゃんけん義手ロボット [1月] ★

スイッチ一つでじゃんけんをする事が出来る義手ロボットを、ご縁あって分身ロボット研究者 吉藤オリィさんと、脊髄性萎縮症 (SMA)の女の子&お母さんと一緒に製作しました。


自分の息子以外のために何かを作る初めての体験。
1ボタンでグー/チョキ/パーを選択できる。手が動かなくても、指一つで自分の意志をロボ義手に表現できる!

2018年末から取組みを始め、実際の使用者(小学生の女の子)のおうちに集まって原理プロトを作ったり、その原理プロトを実際に学校で使って貰ってフィードバックを貰ったり、使い手(ユーザー)と作り手(メイカー)が一緒になってモノづくりする面白さを実感出来た取り組みでした!



(4-2) パーティ映え イルミネーション車椅子 [5月] ★

車椅子ユーザー TK君の「普通の車椅子、カッコ悪い」という一言に対して、パーティ映えする様なイルミネーション車椅子を改造製作してみました。

ただLEDテープで光らせるだけではなく、加速度センサーによる走行検出により走行中のみレインボーに光る、時間に応じてイルミネーションモードを変更する等の工夫を入れています。後の(4-3)へ繋がる取り組み。

製作には、M5Stackを使ってます



(4-3) 車椅子をワクワク新幹線に! WHEELCHAIR TRAIN [8月] ★

8月に開催された特別支援学校の特別おもしろ祭りに向けた製作。普段の車椅子を、少年心をくすぐる新幹線に変身させました!


見た目だけでなく、走行時に電車発射音、走行方向に応じてエフェクトが変わる面白仕様。

製作記事はこちら
ogimotokin.hatenablog.com

こちらのご縁で、8月放送の『めざましテレビで放送頂いたりと、活動の幅が広がった印象的な製作物でした。
また、実際に、本イベントで知り合ったお子さんに個人的に1台製作してお渡ししたところ、大変喜んで貰い、愛用してくれてるとの事、本当に嬉しいです!

製作には、M5Stackを使ってます



(4-4) スイッチを押すと魔法をかけるハロウィンロボット [10月]

息子の通う療育園でのハロウィンパーティで「スイッチを押して子供達を喜ばせたい」という妻の願いに賛同して、前日に製作。

思い付いたら、100均グッツ+手元部品で突貫で作り、子供達に試してもらう! 今年の取り組みを象徴する様な取り組みでした!(^^)

製作には、Arduino Unoを使ってます



(4-5) スイッチで鳴らすハンドベル演奏装置 [12月]

息子の通う療育園のクリスマス会、肢体不自由の同級生8人で想い出になる事をしたいという想いで製作しました。
8個のスイッチを使ってハンドベルを手動/自動で簡単に鳴らせます。


電気回路(ソレノイド) / 筐体設計(3Dプリンタ) / 台製作(木材DIY) など今年の数々のモノづくりで経験したノウハウを駆使して
わずか2週間分(深夜時間のみ)で実現できました。

イベント用として製作した本演奏システムですが、評判良さそうなので、今後のイベントでも活用を検討したいと思います。
機能アップデート検討中。



その他 未発表分(5件)

大人の事情(?)で、公開できませんが

(5-1) 普段の掃除をワクワク楽しくさせる改造掃除機プロト
(5-2) 本業で使っている移動ロボットを遊園地乗り物仕様に改造
(5-3) カレーを食べる際に本格感を拡張させる気持ち拡張プロト
(5-4) 障がい者向けの新調理機器のプロト
(5-5) スイッチで叩くタンバリン演奏マシンプロト

なども個人製作の延長として作ってみました。




製作手伝い

(6-1) 車椅子ごと乗れる視線入力台車システム ver1 [5月]

姿勢保持の困難な重度の方でも自分の車椅子ごと乗車可能な台車システムの試作製作に関わらせて貰いました。

木材DIYの加工自体が未経験だったため、ここで基本的な工具の使い方、台車製作における勘所を学びました。
その結果、(1-3)の製作を個人で実施する事ができました。

(6-2) 車椅子ごと乗れる視線入力台車システム ver2 [9月]

(6-1)で製作した台車システムの改良版の製作にも関わらせて貰いました。

板金やアルミフレームを用いた台車製作を初めて体験し、木材に比べて加工やメンテナンスしやすい事を学びました。
アルミを用いた個人製作は2020年に検討中。息子用モビリティ製作に活かします!

終わりに

とにかく「手を動かして試す」ことを繰り返してきた2019年。手を動かし続けたことで見えた世界がたくさんありました。
2020年も、変わらず 息子や家族、誰かのために手を動かし続けたいと思います!

特に、『音楽演奏』『ゲーム』『電動移動モビリティ』『支援ロボット』を重点に開発を続けたいと思いますので、引き続き暖かく見守って頂いたり、アドバイス等いただければ大変嬉しいです!

M5StickCを使ったタンバリン型スイッチを作ってみた

はじめに

Nintendo Switchコントローラを改造して、手の不自由な息子も一緒に家族でゲームを楽しめるための取り組み!

ogimotokin.hatenablog.com

前記事にて物理スイッチで操作できるゲームコントローラを製作しました。
これにより、様々なスタイルでNintendo Switchのゲームを楽しむ事が出来ます!

息子の操作サポートのために作ったコントローラですが、
単なる福祉用途としてだけでなく、きょうだい達も思わず使いたくなる面白い遊び方の可能性を秘めたコントローラにしていきたいと思い、どんな面白い拡張が出来るかを実験しています。

今回のターゲットは、上の娘がはまりつつある太鼓の達人
最初は体験版で遊んでたらすっかりハマり、普通のコントローラで楽しく遊んでいます。

今年のクリスマスプレゼントは、『太鼓の達人』をサンタさんにお願いしているハマり具合!


その姿を見ているうちに
「太鼓コントローラは実際に音は鳴らない。
 もしこれが、コントローラでなく実際に音の鳴る楽器で遊べたら、、、
 楽しいかも!」


太鼓の達人」は少ないボタンで遊べるので、肢体不自由な息子でも遊びやすいゲームやと思います。
そして、タンバリンは大きな面なので手を当てやすいので、息子の興味を引く事が出来るかもしれない!
楽器演奏がうまく出来ない息子でも、きょうだいで楽しく演奏する体験して欲しい!


という訳で、

Nintendo Switch太鼓の達人」に対応した
タンバリン型スイッチ

を製作してみました。

[要求仕様]
・タンバリンを鳴らすと、それに同期して実際の『太鼓の達人』ゲームに判定が入る事
 またLEDを光らせる等の簡易フィードバックもある事
・他のスイッチ機器でも使える事
・タンバリンのどこを叩いても反応する事
(力の弱い息子でも使える事が望ましい)

製作物

上記要求仕様を踏まえた結果、一番お手軽な実装方法として、
「M5StickCのマイク機能を使った音量反応型スイッチ」
という方針で、スイッチデバイスを開発しました。

f:id:motokiinfinity8:20191224224948j:plain

マイクの入力音量に応じてスイッチON/OFF制御を行うというシンプル構造。
タンバリン音源とチューニング(入力判定閾値の調整)のみで、しっかりとタンバリン音だけ反応してくれます。
また、音検出した際のフィードバックとして、M5StickCのLEDと「どんちゃん(赤い太鼓のキャラクタ)」っぽいイラストも表示してみた(笑)

なお、これを応用すれば、タンバリンだけでなく、例えば「呼び鈴」などもコントローラに出来ます(笑)


非常に広い応用が期待できそう!

ハードウェア

ハードウェア構成は非常にシンプルです。

f:id:motokiinfinity8:20191224235242j:plain

M5StickC内部にマイクが搭載されているおかげで、外部回路としてはスイッチON/OFFのためのフォトカプラがあればOK。
ただし、M5StickCはご存じの様にバッテリー容量が80mAHと少なく、子供が遊びたい時に充電切れてて遊べないのは致命傷になりかねないので、電池パックを取り付けれる様に配慮しました。


上記の様に、3cm×7cmの基板上でM5StickC含めてすべて収まります。

音量反応型のスイッチの場合、当然ながら他の雑音の影響を受けやすいのが欠点なのですが、
 ・タンバリンのすぐ近くにM5Stickを配置
 ・スイッチOFF→ONの音量判定閾値を高めに設定する

工夫により、多少の雑音ノイズの影響を抑える事ができました!

ソフトウェア

実は、ソフトウェアもそこまで開発工数を使いませんでした。
というのも、コードの多くは 以下のサイトにもある様な、M5StickCのマイク入力のサンプルコードを流用しているからです。

lang-ship.com


後は、音量入力の閾値決めになるのですが、ある程度は実験値を使いつつ、合わせて「ON→OFF時の判断音量閾値」と「OFF→ON時の判断音量閾値」を分ける(=ヒステリシス性を持たせる)事で、より精度の上げた判定条件にしています。

#include <M5StickC.h>
#include <driver/i2s.h>
#define PIN_CLK  0
#define PIN_DATA 34
#define READ_LEN (2 * 256)
#define GAIN_FACTOR 1
uint8_t BUFFER[READ_LEN] = {0};
uint16_t oldy[160];
int16_t *adcBuffer = NULL;

#define SWON_MIC_THMAX   2000
#define SWON_MIC_THMIN  -5000
#define SWOFF_MIC_THMAX   0
#define SWOFF_MIC_THMIN  -3000
#define MIC_AVRAGE   -1500
#define PIN_SWOUT 26

bool g_sw = 0;
bool g_sw_old = 0;

void i2sInit()
{
   i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
    .sample_rate =  44100,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
    .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 2,
    .dma_buf_len = 128,
   };

   i2s_pin_config_t pin_config;
   pin_config.bck_io_num   = I2S_PIN_NO_CHANGE;
   pin_config.ws_io_num    = PIN_CLK;
   pin_config.data_out_num = I2S_PIN_NO_CHANGE;
   pin_config.data_in_num  = PIN_DATA;
   
   i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
   i2s_set_pin(I2S_NUM_0, &pin_config);
   i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
}



void mic_record_task (void* arg)
{   
  size_t bytesread;
  while(1){
    //50ms分のバッファを読み出す
    i2s_read(I2S_NUM_0,(char*) BUFFER, READ_LEN, &bytesread, (50 / portTICK_RATE_MS));
    adcBuffer = (int16_t *)BUFFER;
    showSignal();
    vTaskDelay(50 / portTICK_RATE_MS);
  }
}

void setup() {
  M5.begin();
  M5.Axp.ScreenBreath(8);
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(TFT_BLACK);

  // LED ON(GPIO_NUM_10 or M5_LED)
  pinMode(GPIO_NUM_10, OUTPUT);
  pinMode(PIN_SWOUT, OUTPUT);
  digitalWrite(GPIO_NUM_10, HIGH);  //LED OFF
  digitalWrite(PIN_SWOUT, LOW);  //SW出力 OFF

  i2sInit();
  xTaskCreate(mic_record_task, "mic_record_task", 2048, NULL, 1, NULL);
}

void loop() {
  int g_sw_now = g_sw;

  //OFF→ON判定時は「どんちゃん」を表示
  if(g_sw_old == 0 && g_sw_now == 1){
    M5.Lcd.fillCircle(100, 40, 36, 0xFFF0);  //クリーム色
    M5.Lcd.fillCircle(100, 40, 30, 0xF800);  //赤
    M5.Lcd.fillCircle(83,  35,  7, BLACK);  //右目
    M5.Lcd.fillCircle(117, 35,  7, BLACK);  //左目
    M5.Lcd.fillTriangle(90, 45, 110, 45, 100, 65, BLACK);
    M5.Lcd.fillTriangle(93, 48, 107, 48, 100, 62, 0x7800);  //ダークレッド
  }
  if(g_sw_old == 1 && g_sw_now == 0){
    M5.Lcd.fillScreen(TFT_BLACK);
  }

    // バッテリ電圧表示
  float vbat      = M5.Axp.GetVbatData() * 1.1 / 1000;
  //バッテリ残量[%]
  M5.Lcd.fillRect(0, 0, 60, 20, BLACK);
  M5.Lcd.setCursor(6, 0, 2);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.printf("%.2f V",vbat);

  g_sw_old = g_sw_now;
  vTaskDelay(100 / portTICK_RATE_MS); // otherwise the main task wastes half of the cpu cycles
}


void showSignal(){
  int y;
  int s_max = INT16_MIN;
  int s_min = INT16_MAX;
  for (int n = 0; n < 160; n++){
    y = adcBuffer[n] * GAIN_FACTOR;
    // 最大,最小更新
    if(y >= s_max) s_max = y;
    if(y <= s_min) s_min = y;
    
    y = map(y, INT16_MIN, INT16_MAX, 10, 70);
    oldy[n] = y;
  }

  //スイッチ判定
  //OFF→ON判定
  if(g_sw==0 && s_max >= SWON_MIC_THMAX  && s_min <= SWON_MIC_THMIN){
    g_sw = 1;
    digitalWrite(GPIO_NUM_10, LOW);   //LED ON
    digitalWrite(PIN_SWOUT, HIGH);  //SW出力 ON
  }
  //ON→OFF判定
  if(g_sw==1 && s_max <= SWOFF_MIC_THMAX  && s_min >= SWOFF_MIC_THMIN){
    g_sw = 0;
    digitalWrite(GPIO_NUM_10, HIGH);  //LED OFF
    digitalWrite(PIN_SWOUT, LOW);  //SW出力 OFF   
  }

  Serial.print("s_max:");
  Serial.print(s_max);

  Serial.print("  s_min:");
  Serial.println(s_min);
}

終わりに

タンバリンや呼び鈴など、実際の楽器の音を『太鼓の達人』をコントローラにしてしまうアイデアを具現化してみました。
無改造な何のヘンテツもないタンバリンなのに、それがゲームコントローラになる体験は新鮮で楽しかった!

ただ、一番の課題は「入力の遅延」
音が鳴るタイミング=入力判定となるで、少し早めに叩かないといけないので、そこがコツがいりました。(なので、本気の音ゲー用途にはむいておらず、子供の興味を引くため体験用と割り切る必要はありそうです)

ただ、ある意味、楽器演奏という観点としては
【音が鳴るタイミングに拍を合わせるため早めに叩くのが正しい姿】なので、
ある意味 本質的な音ゲーコントローラなのかもしれませんね。

ゲーム以外の用途としても音検出型スイッチとして応用できないか、他にも試してみたいと思います!

Nintendo Switchゲームを物理スイッチで操作できるコントローラを作ってみた

f:id:motokiinfinity8:20191205212426j:plain

はじめに(製作動機)

ゲーム好きな我が家族、妻と娘は時間を見つけてはNintendo Switchのゲーム(スプラトゥーンマリオカートなど)で毎日楽しく遊んでいます! 息子もその横で、楽しそうに画面を見て喜んでいます。

しかし、見てるだけで、操作できない。

ゲーム依存が社会問題になっている様ですが、我が家はゲームから多くを学んでます。
消極的だった娘はゲームをやる様になって、チャレンジ精神、失敗する事の大切さを学び、学校の友達とも積極的に遊ぶ様になりました!

なので、息子にも息子もゲームを通して、
「自分で操作する楽しさ」「失敗してやり直せる楽しさ」を感じて欲しい!


まず最初の関門は、市販のコントローラでは「手の不自由な息子は操作できない」という事。
・ボタンが多すぎて、どれを押せばいいか分からない
・コントローラを持てないので、狙ったボタンを押せない

という訳で、まずは第一歩として

「息子でも操作できる様な物理スイッチで操作できる
 Nintendo Switchコントローラの開発」

の自作に取り組みました!


[要求仕様]
3.5mmジャック対応スイッチで操作できる事
 また、我が家で使っている無線対応ジョイスティックでも操作できる事
・操作ボタンはゲームごとに変更できる事
・操作ボタンは最小限として、
 それ以外の操作は自動 or 介助者による代替操作でフォローできる事
 (ただし、本人が操作してる感覚になれる事)
・介助者によるサポート操作が同時にできる事


製作物

上記要求仕様を踏まえた結果、効率良い手段として、
「市販品のNintendo Switchコントローラを改造して外部ハックする」
という方針で、ハックモジュールを開発・改造しました。

f:id:motokiinfinity8:20191205212259j:plain


操作イメージを以下の動画にまとめました。


今のところ、息子でも遊べそうなゲーム(少ボタンでも出来るゲーム)として、
マリオカート
ゼルダの伝説 ~夢を見る島~
太鼓の達人

に対応しております。

製作方法

材料

改造するコントローラとしては、安価なコントローラとしてHORI製有線コントローラを使いました。

【Nintendo Switch対応】ホリパッド for Nintendo Switch

【Nintendo Switch対応】ホリパッド for Nintendo Switch

  • 作者:
  • 出版社/メーカー: ホリ
  • 発売日: 2017/07/13
  • メディア: Video Game

これに、お馴染みの無線対応マイコンモジュール"M5Stack" 及び 周辺デバイスを使います。
筐体は 3Dプリンタで作成しました。

部品名 個数 購入先 値段
M5Stack Basic 1 Switch Science ¥3575
M5Stack プロトモジュール 1 Switch Science ¥1300
GPIO拡張IC MCP23017 1 秋月電子 ¥110
3.5mmステレオジャック 4 秋月電子 ¥60
全体システム

システムイメージは以下の図になります。

f:id:motokiinfinity8:20191216222436j:plain

市販のコントローラ内の基板上のボタン入力信号&ジョイスティック入力信号に外部から配線を追加接続して、外部マイコンから強制的に信号を切り替えるやり方です。ボタン制御用には8本接続し、ボタン押し制御を実施する際は外部からL(GND)信号を印加してやります。
ジョイスティックの場合、1つのジョイスティックに上下用と左右用の2本を接続します。この場合、ジョイスティックの制御がない場合は、信号は1.65V(中間値)になっていますので、
 上 or 左に設定する場合 → H(3.3V)信号を出力
 下 or 右に設定する場合 → L(0V)信号を出力
 設定しない場合  → Hi-Zにする = 入力設定にする
 
という事で対応しました。これだとアナログジョイスティックならではの中間値が表現できませんが、まぁゲーム精度を求める事が目的ではないので、今回は妥協しました。
(こういう妥協も、スピード感あるモノづくりでは結構大事ですよね)


これは前職(家電関連の電気設計)でのエージング試験用としてよく行っていた手法です。
家電のリモコンを改造して、定期的な信号を発行し続けさせて、耐久性試験の効率化として活用していました。
ここにきて、前職での設計スキルが役に立ったー!

ハードウェア

それでは、HORI製のコントローラを分解してみる。裏側のネジを外すと、緑色の基板が出てきます。
f:id:motokiinfinity8:20191223235302j:plain

この基板の上で、比較的はんだ付けしやすそうな場所を選んで半田をつけていきます。
f:id:motokiinfinity8:20191224001643p:plainf:id:motokiinfinity8:20191224001651p:plain


A/B/X/Yボタンは残念ながら裏面にはんだ付けしやすそうな場所がなかったので、
表面側に直接付けます。(上級者であれば、配線のところのレジストを削る手段を取る方がラクかも)
ただし、ボタン面はコーティングされているので、カッターの刃裏面を使い、コーティング部を削っていきます。
f:id:motokiinfinity8:20191224002134j:plain

キレイな銅のピカピカした色が見えてきたら、その上にはんだを乗せてみて、無事にひっつけばOKです

配線するとこんな感じになります。(汚くてスイマセン)

f:id:motokiinfinity8:20191224002321j:plainf:id:motokiinfinity8:20191224002328j:plain


また、ハックユニット側には、3.5mmジャック用スイッチを4つ筐体に並べます。
残念ながら、M5Stack プロトモジュールの一端面には4つ並ばなかったので、専用筐体を3Dプリンタで製作してみました。

f:id:motokiinfinity8:20191224003358p:plainf:id:motokiinfinity8:20191224003828j:plain

ソフトウェア

GPIO拡張IC MCP23017

今回の様に8本以上のスイッチ入力やON制御出力を実施する場合、信号本数が足りなくなる事が想定されます。
そんな時に便利なのが、『GPIO拡張IC MCP23017』です。

チップの詳細は以下のサイトをご覧ください。

project59.blog.fc2.com


※使う際の注意
 ・ICのリセット端子が必ずPU抵抗になっているか?
 ・アドレス信号(A0/A1/A2)は必ずGND or PU抵抗で接続されているか?

私は上記を忘れていた結果、不安定動作(IC近辺を手で触ると挙動が変わる)に悩まされました…


制御については、Arduinoライブラリとして提供されています。
これを使えば、通常GPIOと近いソフトウェアの記述イメージで製作できます。

github.com

ソースコード

全体を公開すると冗長になるため、必要部のみ抜粋します

#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include "esp_system.h"
#include "Adafruit_MCP23017.h"

//MCP23017 (GPIOエキスパンダ)のピン割り当て
#define L_H_JOY  7
#define L_V_JOY  6
#define R_H_JOY  5
#define R_V_JOY  4
#define A_BTN    8
#define B_BTN    9
#define X_BTN   10
#define Y_BTN   11
#define R_BTN   12
#define RZ_BTN  13 
#define L_BTN   14
#define LZ_BTN  15 
#define INPUT1_BTN   0
#define INPUT2_BTN   1
#define INPUT3_BTN   2
#define INPUT4_BTN   3

#define RENDA_JUDGE_TIME 250
#define RENDA_KANKAKU_MS 60

Adafruit_MCP23017 mcp;

void setup()
{
  M5.begin();
  Serial.begin(115200);
  M5.Lcd.fillScreen(BLACK);
  
  mcp.begin();      // use default address 0

  //PIN設定
  mcp.pinMode(L_V_JOY, INPUT);
  mcp.pinMode(L_H_JOY, INPUT);
  mcp.pinMode(R_V_JOY, INPUT);
  mcp.pinMode(R_H_JOY, INPUT);
  
  mcp.pinMode(A_BTN, OUTPUT);
  mcp.digitalWrite(A_BTN, 1);
  
  mcp.pinMode(B_BTN, OUTPUT);
  mcp.digitalWrite(B_BTN, 1);
  
  mcp.pinMode(X_BTN, OUTPUT);
  mcp.digitalWrite(X_BTN, 1);
  
  mcp.pinMode(Y_BTN, OUTPUT);
  mcp.digitalWrite(Y_BTN, 1);
  
  mcp.pinMode(L_BTN, OUTPUT);
  mcp.digitalWrite(L_BTN, 1);
  
  mcp.pinMode(LZ_BTN, OUTPUT);
  mcp.digitalWrite(LZ_BTN, 1);
  
  mcp.pinMode(R_BTN, OUTPUT);
  mcp.digitalWrite(R_BTN, 1);
  
  mcp.pinMode(RZ_BTN, OUTPUT);
  mcp.digitalWrite(RZ_BTN, 1);

  mcp.pullUp(0, HIGH);
  mcp.pullUp(1, HIGH);
  mcp.pullUp(2, HIGH);
  mcp.pullUp(3, HIGH);
}


void loop(){
  
   M5.update();
   if(M5.BtnA.wasPressed()){  
      //現時点では3モードのみ
      game_idx = (game_idx-1)%3;     
   } 
   if(M5.BtnC.wasPressed()){  
      //現時点では3モードのみ
      game_idx = (game_idx+1)%3;     
   }

   
  //ゲームモード選択
  if(game_idx != game_idx_old){
    //モード0 : マリオカート
    if(game_idx == 0){
      M5.Lcd.drawJpgFile(SD, "/mariocart.jpg");
      M5.Lcd.drawJpgFile(SD, "/mc_accel.jpg", 0, 180);
      M5.Lcd.drawJpgFile(SD, "/mc_item.jpg", 80, 180);
      M5.Lcd.drawJpgFile(SD, "/mc_left.jpg", 160, 180);
      M5.Lcd.drawJpgFile(SD, "/mc_right.jpg", 240, 180);
   }
    **** 中略 ****
    game_idx_old = game_idx;
  }

  //外部ボタンからのハック分をマージ
  int jyuji_val_update = jyuji_val;
  int btn_val_update = btn_val;
  int input_val = mcp.digitalRead(INPUT4_BTN)*8+mcp.digitalRead(INPUT3_BTN)*4+mcp.digitalRead(INPUT2_BTN)*2+mcp.digitalRead(INPUT1_BTN);

  // Mode0 マリオカートの場合
  if(game_idx == 0){
    // ボタン入力
    if(mcp.digitalRead(INPUT1_BTN) == 0){
      btn_val_update |= 0b00000001; //Aボタンを1にする
    }
    if(mcp.digitalRead(INPUT2_BTN) == 0){
      btn_val_update |= 0b01000000; //Lボタンを1にする  
    }
    if(mcp.digitalRead(INPUT3_BTN) == 0){
      jyuji_val_update |= 0b0010; //左ボタンを1にする    
    }
    if(mcp.digitalRead(INPUT4_BTN) == 0){
      jyuji_val_update |= 0b0001; //右ボタンを1にする   
    }

    // ボタン表示変更
    if((input_val & 0b0001) != (input_val_old & 0b0001)){
      if((input_val & 0b0001) == 0) M5.Lcd.drawJpgFile(SD, "/mc_accel_on.jpg", 0, 180);
      else M5.Lcd.drawJpgFile(SD, "/mc_accel.jpg", 0, 180);
    }
    if((input_val & 0b0010)  != (input_val_old & 0b0010)){
      if((input_val & 0b0010) == 0) M5.Lcd.drawJpgFile(SD, "/mc_item_on.jpg", 80, 180);
      else M5.Lcd.drawJpgFile(SD, "/mc_item.jpg", 80, 180);
    }
    if((input_val & 0b0100) != (input_val_old & 0b0100)){
      if((input_val & 0b0100) == 0) M5.Lcd.drawJpgFile(SD, "/mc_left_on.jpg", 160, 180);
      else M5.Lcd.drawJpgFile(SD, "/mc_left.jpg", 160, 180);
    }
    if((input_val & 0b1000) != (input_val_old & 0b1000)){
      if((input_val & 0b1000) == 0) M5.Lcd.drawJpgFile(SD, "/mc_right_on.jpg", 240, 180);
      else M5.Lcd.drawJpgFile(SD, "/mc_right.jpg", 240, 180);
    }

   *** 中略 *****
   ////////////////////////////
   // コントローラボタン制御
   ///////////////////////////
   // 上下ボタン
   if((jyuji_val_update & 0b1000) >> 3){ //上の場合
      mcp.pinMode(L_V_JOY, OUTPUT);
      mcp.digitalWrite(L_V_JOY, 0); 
      Serial.println("push UP");
   }else if((jyuji_val_update & 0b0100) >> 2){ //下の場合
      mcp.pinMode(L_V_JOY, OUTPUT);
      mcp.digitalWrite(L_V_JOY, 1); 
      Serial.println("push DOWN");  
   }else{
      mcp.pinMode(L_V_JOY, INPUT);
   }

   
    // 左右ボタン
   if((jyuji_val_update & 0b0010) >> 1){ //左の場合
      mcp.pinMode(L_H_JOY, OUTPUT);
      mcp.digitalWrite(L_H_JOY, 0);
      Serial.println("push LEFT");
   }else if(jyuji_val_update & 0b0001){  //右の場合
      mcp.pinMode(L_H_JOY, OUTPUT);
      mcp.digitalWrite(L_H_JOY, 1);
      Serial.println("push RIGHT");
   }else{
      mcp.pinMode(L_H_JOY, INPUT);
   }

    // X(青)ボタン
   if((btn_val_update & 0b00000100) >> 2){
      mcp.pinMode(X_BTN, OUTPUT);
      mcp.digitalWrite(X_BTN, 0);
      Serial.println("push X");
   }else{
      mcp.pinMode(X_BTN, INPUT);
   }

   // B(黄)ボタン
   if((btn_val_update & 0b00000010) >> 1){
      mcp.pinMode(B_BTN, OUTPUT);
      mcp.digitalWrite(B_BTN, 0);
      Serial.println("push B");
   }else{
      mcp.pinMode(B_BTN, INPUT);
   }

   // Y(緑)ボタン
   if((btn_val_update & 0b00001000) >> 3){
      mcp.pinMode(Y_BTN, OUTPUT);
      mcp.digitalWrite(Y_BTN, 0);
      Serial.println("push Y");
   }else{
      mcp.pinMode(Y_BTN, INPUT);
   }

   // A(赤)ボタン
   if(btn_val_update & 0b00000001){
      mcp.pinMode(A_BTN, OUTPUT);
      mcp.digitalWrite(A_BTN, 0);
      Serial.println("push A");
//   }else if(digitalRead(INPUT1_BTN) == 0){
//      pinMode(A_BTN, OUTPUT);
//      digitalWrite(A_BTN, 0);
//      Serial.println("push A (Outside)");
//   
   }else{
      mcp.pinMode(A_BTN, INPUT);
   }
    // LZボタン
   if((btn_val_update & 0b10000000) >> 7){
      mcp.pinMode(LZ_BTN, OUTPUT);
      mcp.digitalWrite(LZ_BTN, 0);
      Serial.println("push LZ");
   }else{
      mcp.pinMode(LZ_BTN, INPUT);
   }

   // Lボタン
   if((btn_val_update & 0b01000000) >> 6){
      mcp.pinMode(L_BTN, OUTPUT);
      mcp.digitalWrite(L_BTN, 0);
      Serial.println("push L");
   }else{
      mcp.pinMode(L_BTN, INPUT);
   }

    // RZボタン
   if((btn_val_update & 0b00100000) >> 5){
      mcp.pinMode(RZ_BTN, OUTPUT);
      mcp.digitalWrite(RZ_BTN, 0);
      Serial.println("push RZ");
   }else{
      mcp.pinMode(RZ_BTN, INPUT);
   }

   // Rボタン
   if((btn_val_update & 0b00010000) >> 4){
      mcp.pinMode(R_BTN, OUTPUT);
      mcp.digitalWrite(R_BTN, 0);
      Serial.println("push R");
   }else{
      mcp.pinMode(R_BTN, INPUT);
   }

  // データ更新
  input_val_old = input_val;
  delay(20);
}

終わりに

肢体不自由な息子でも簡単にゲームを楽しむ体験を創るためのコントローラハック。
今後は、画像認識と組み合わせて息子の苦手な操作を自動化する事や、視線入力モジュールと組み合わせる等の簡易入力も視野に入れつつ、使いながら必要な応用例を考えてみたいと思います~

合わせて、他のゲームにも対応できる様に応用例を検討中。
できれば、妻&娘が大好きなスプラトゥーンに対応させたいですが…素直にボタンを割合すると数が多くて操作が大変そうなので、どうやって簡易化&マイコンでのサポート機能を使うかは悩み中~

息子でも遊べそう&家族で楽しめそうなおすすめのゲームあれば教えて下さい~(^-^)

【かんたん工作】100均グッツで可愛く光る意思伝達スイッチを作ってみた

f:id:motokiinfinity8:20191124235613j:plain

はじめに

障害を持った子供達が
自分の意志を表現・伝達するための手段である「スイッチ」

www.rehab.go.jp

「電気を流す/流さないを切り替える」という電気工学観点だけではすごくシンプルなのですが、
「人の意思を表現する手段」として人間工学観点でのスイッチは実際には非常に奥が深く、
特に障害を持つ方にとっては
「どうやったら自分の力で上手に押せるのか」
その人の障害の特性に応じた個別カスタマイズノウハウが重要です。

しかし、個別カスタマイズになったり、個人一品モノになるとどうしても高価になる。
実際に、福祉スイッチで有名なパシフィックサプライさんのスイッチ等は、1個で1万円近くします。

www.p-supply.co.jp

どうしても数が出ないモノは高くなる。ハード作りをした人なら良く分かる感覚ですね。

そこで一品モノであるならば、身近にあるモノを使って、簡単なスイッチを作ってみようという取り組みに今回チャレンジしてみました。
作業療法士さんの世界では当たり前に行われている取り組みかもしれませんが)

コンセプトは、
 ・100均ショップに売っているモノを使い
 ・子供達が喜んで触りたくなる様な遊び心も加えて
 ・工作初心者でも作れるシンプルさ

を目指してみたいと思います。

完成品

100均グッツ+電子部品のみで製作したスイッチ。動画はこちら。

勉強も兼ねて、初めてのスイッチ作りとして以下の3パタンを作りました。
①押すとキティちゃんのほっぺが光るスイッチ
②押すとボタン全体が光るスイッチ
③くまさん型コンパクトスイッチ

上記動画では、ロボットを前進させる意志表現として紹介しましたが、他にもゲームコントロール機器や車椅子操作ボタン、音声選択など
様々な機器の動作スイッチとして使用できます。


ちなみに、福祉業界では、「3.5mmモノラルジャック」をI/Fにしたスイッチが一般的です。
確かに、それだと部品入手も簡単(100均ショップでも購入可)というのが特徴
どうしても一品対応になり、市販品がそのまま適用しずらい福祉機器ならではの工夫ですね。
(私が初めてスイッチを知った時、その創意工夫アイデアに「なるほど!」と感心しました)

①ほっぺが光るキティちゃんスイッチ

購入部品

f:id:motokiinfinity8:20191121214504j:plain

部品名 個数 購入先 値段
キティちゃんイヤホンケース 1 キャンドゥ/ダイソー ¥100
タクトスイッチ(大) 1 秋月電子 ¥300(10個)
3.5mmジャック+基板 1 秋月電子 ¥150
3.5mmステレオ(オス-オス)ケーブル 1 秋月電子 or ダイソー ¥150
赤色LED 2 秋月電子 ¥20
フォトカプラ 1 秋月電子 ¥130
薄両面ユニバーサル基板 1 秋月電子 ¥100
CR2032用電池ホルダー 1 秋月電子 ¥50
CR2032用電池 1 秋月電子 ¥200(5個)

配線は上記リストから省略してますが、
耐熱電子ワイヤー 2m×7色 外径1.22mm(UL3265 AWG24): パーツ一般 秋月電子通商-電子部品・ネット通販
ポリウレタン銅線(0.29mm 20m): パーツ一般 秋月電子通商-電子部品・ネット通販
辺りを良く使っています。

ちなみに、「3.5mmジャック+基板」ははんだ付け苦手な人が3.5mmジャック(オス)のケーブルを接続させるための工夫です。
(秋月限定の変換基板)

はんだ付け経験者であれば、「3.5mmステレオ(オス-オス)ケーブル」の片側をカットして配線を剥いて、本体基板に直接取り付けるやり方でもOKです。

製作イメージ(回路図)

以下が回路図イメージになります。
f:id:motokiinfinity8:20191124192232j:plain

「フォトカプラ(=フォトリレー)」が本スイッチ回路の肝になっています。
「左側の1Pin→2Pinに電流が通過したら、3Pin-4Pin間のスイッチをONにする」というシンプル技術です。
1-2Pin側と3-4Pin側は電気的には分離しているので、汎用的なメカスイッチと同じイメージで考えられます。

なお、本来は赤色LEDには電流制限用の抵抗を入れるのですが、今回は3V電池(CR2032)を使っていて電圧がギリギリのため、抵抗なしとしました。
(もし3V以上の電池を使うならば、抵抗は入れた方がよいですね)

製作方法(簡易)

写真をベースに製作のポイントを記載したいと思います。
(本当はもっと詳細に記載した方が分かりやすいのですが、手順書を作るのが苦手なので…)

ダイソーで購入したイヤホンジャックのフタのひっかけ部をニッパーで切って、開閉しやすくします。
f:id:motokiinfinity8:20191121214236j:plain
f:id:motokiinfinity8:20191121214254j:plain

・また、3.5mmジャック配線が通る様にケース上面に穴を開けてください
f:id:motokiinfinity8:20191121220109j:plain

・上の回路図に従って、基板上に部品を半田付け&配線していきます。ちょうどキティちゃんのホッペ位置にLEDを微調整するため、LEDは基板に密着させず、少し間を開けてください。
f:id:motokiinfinity8:20191121214741j:plain
f:id:motokiinfinity8:20191121214847j:plain

・スイッチづくりの一番のポイントであるクリック感。
ホットボンドを使って、ふた上面にボンドの山を作り、タクトスイッチとちょうど接地する様に調整してください。
ケースの蓋が閉まるところで、ちょうどタクトスイッチをクリックできる高さがベストです。
f:id:motokiinfinity8:20191121215154j:plain
f:id:motokiinfinity8:20191121215302j:plain


②ボタンを押すと全体が光るスイッチ

購入部品
部品名 個数 購入先 値段
LEDライト 1 ダイソー ¥100
タクトスイッチ(大) 1 秋月電子 ¥300(10個)
3.5mmジャック+基板 1 秋月電子 ¥150
3.5mmステレオ(オス-オス)ケーブル 1 秋月電子 or ダイソー ¥150
赤色LED 3 秋月電子 ¥20
抵抗510Ω 3 秋月電子 ¥100(100個)
フォトカプラ 1 秋月電子 ¥130
薄両面ユニバーサル基板 1 秋月電子 ¥100
単三電池 3 秋月電子 ¥200(5個)

基本的には、「①キティちゃんスイッチ」と同じです。ただし、本スイッチはLEDライト自体に、「単三電池×4」ケースが付いているので、
そちらの構造をそのまま利用したいと思います。

製作イメージ(回路図)

以下が回路図イメージになります。

f:id:motokiinfinity8:20191124225212j:plain

「①キティちゃんスイッチ」と原理は全く同じです。ただし、このスイッチでは、赤色で光らせるのは点ではなく面にしたいため、
LED個数を3個に増やしたことと、単三電池×4=6.0Vと電圧を上げたため、LED手前に電流制限抵抗510Ωを追加しました。

※赤色LEDで2.1Vドロップするので、(6V-2.1V)/510Ω=約10mAくらいのLED光量を狙ってます

製作方法(簡易)

ダイソーで買ってきたLEDライトの中のフタを開け、中身の回路基板をすべて廃棄します。
 また、3.5mmジャック配線が通る様にケース上面に穴を開けてください
f:id:motokiinfinity8:20191121215752j:plain
f:id:motokiinfinity8:20191121215947j:plain

・上の回路図に従って、基板上に部品を半田付け&配線していきます。LEDは光が分散する様に、中央から120度ずつ外辺に向けて設置します。
f:id:motokiinfinity8:20191121215827j:plain
f:id:motokiinfinity8:20191121215844j:plain
f:id:motokiinfinity8:20191121215859j:plain


・スイッチづくりの一番のポイントであるクリック感。
ホットボンドを使って、タクトスイッチの高さを調整します。フタ側には特にホットボンドによる加工は行わず、スイッチ土台側をホットボンドで持ち上げる事で高さ調整を行います。
f:id:motokiinfinity8:20191121215919j:plain
f:id:motokiinfinity8:20191121220018j:plain



③くまさん型コンパクトスイッチ

購入部品
部品名 個数 購入先 値段
くまさん型シャワーカバー 1 セリア ¥100
ゲームスイッチ 1 秋月電子 ¥150
3.5mmステレオ(オス-オス)ケーブル 1 秋月電子 or ダイソー ¥150
製作方法(簡易)

製作方法はいたって簡単!
ゲームセンター等で使われているゲームスイッチボタンに、3.5mmステレオケーブルをカットした配線をはんだ付け。
その後に、くまさん型シャワーカバーをスイッチにはめるだけ(笑)

終わりに

3種類ほど簡単な100均グッツを使ったスイッチを試作してみました。
いずれもタクトスイッチをベースに、指の力が少しでもある子を前提にしたスイッチを作りました。

もちろんこれ以外にも、例えば 触っただけで反応する「静電スイッチ」や「棒スイッチ」、「振動検知スイッチ」など、いろんなバリエーション製作の可能性もありそうです。

最近では、作業療法士の方々との交流も増えてきたので、様々な事例を勉強させて頂きつつ、有意義なスイッチ機器も自作検討してみたいと思います。

Blynk(Bridge機能)で、宅外~宅内のM5Stack間で呼び出しシステムを作ってみた

f:id:motokiinfinity8:20191117191046j:plain

製作動機

我が家のリビングに設置された「予定通知ロボット」

M5Stackに加えてBlynkというアプリで連携すれば、スマホからリビングにある通知ロボット(M5Stack)との情報連携が簡単にできます。しかし、欠点としては、「常にスマホが必要となる事」です。

例えば、子供にスマホを奪われている時であったり、自分以外の人に操作してもらう場合などでスマホを渡せない状況もあったりします。

それが特に露見したのは、2019/5に参加したMaker Faire Kyoto でした。
この時は、もともと展示説明員として当てにしていた妻が、なんと足の骨を折ってしまい、外出そのものが困難になってしまいました。

私一人で2日間、ブースを回せる自信がなかったため、ちょうど我が家で使っていた分身ロボットOriHimeを駆使して、
妻に自宅から遠隔説明員として参加してもらう事でヘルプに入って貰いました。

ogimotokin.hatenablog.com


しかし、ここにきて課題なのは、会場から妻への簡易的な連絡手段
OriHimeは自宅のタブレットから映像/音声で通信するイメージなのですが、
朝から夕方まで常にタブレットを見続ける事は出来ないので、
用事のある時やブースにお客さんが来た時に応対してもらう様にしました。

そんなガヤガヤした会場から自宅へ簡単に呼び出し通知を行う仕組みが必要でした。
(OriHimeからの呼びかけだとガヤガヤ音等でかき消される事もあったので)

Blynkを使ってスマホアプリ上に呼び出しボタンを作ろうとしたけど、さすがに自分のスマホを公共の場に置きっぱなしにできないなぁ、と悩んでいたら…

Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事を見つけました!
これを使えば、会場のM5Stackから、自宅リビングにあるM5Stack間へ呼び出し通知が出来る

と思い、製作に取り掛かりました。

完成動画

OriHimeに搭載したM5Stackからの自宅リビングにあるM5Stackへ通知

実験的には同じ室内ですが、当然ながらOriHime+M5Stackを宅外に持っていっても同様に、
宅内のM5Stackに通知ができます

ブロック構成

本システムの簡易ブロック図は以下です。

f:id:motokiinfinity8:20191113213512j:plain

すごくシンプルなんです!
それぞれのM5Stackが WIfiを介して外部ネットワークと繋がる環境であれば、Blynkサーバーを介して情報を伝送してくれるイメージです!

しかし、Blynk内のプロジェクトは「1プロジェクト1デバイス」の様で、2つのデバイスをBlynk上で連携させるにはもう一工夫必要。

そこで活躍するのが「Bridgeウィジット」です。
このウィジェットはどうやら「プロジェクト間の通信をBridgeする」イメージの様ですので、2つのデバイス用に割り当てたBlynkプロジェクト間を本ウィジェットで繋げてやります!

ソフトウェア(

前文でも書いた通り、2つのプロジェクトを作成します。
今回は『 auth_orihime(ロボット側)』 と 『 auth_living (リビング設置側)』の2種類を用意しています。

Blynkアプリ設定

プロジェクト間での通信をしたい側にBridgeウィジェットを配置します。
今回は、auth_orihimeからの一方向通信のため、auth_orihime側にBridgeウィジェットを置きます。

f:id:motokiinfinity8:20191117192220j:plain
f:id:motokiinfinity8:20191117192228j:plain

画面上に置くだけで特にアプリ上からは設定不要です。(auth_living側は特にアプリでの設定不要)

送信側(OriHime呼び出し側) Arduinoコード

ロボット側のコードは、
「M5Stackのボタンが押されたらauth_livingプロジェクトのV3ピンをHに上げる」
内容になります。

#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include "time.h"
#include <BlynkSimpleEsp32.h>
#define BLYNK_PRINT Serial

// Audio speaker
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioOutputI2S.h"
#include "AudioGeneratorWAV.h"
AudioGeneratorWAV *wav;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;

const char* auth_orihime   = "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //OriHime側(call側)Blynkアプリ Auth コード
const char* auth_living   = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //リビング側(receive側) Auth コード
const char* ssid     = "xxxxxxxxxxxxxxxxxxxxxxx";   //ポケットWifi等のSSID
const char* password = "xxxxxxxxxxxxxxxxxxxxxx";  // ポケットWIfi等のSSIDパスワード

// Bridge widget on virtual pin 0
WidgetBridge bridge1(V0);   // OriHime側BlynkアプリのV0を使用

void setup() 
{
  M5.begin();
  Serial.begin(115200);

  // M5Stackによる名札機能
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.drawJpgFile(SD, "/okan.jpg");

  // M5Stackによるスピーカ再生機能設定
  out = new AudioOutputI2S(0,1); 
  out->SetOutputModeMono(true);
  out->SetGain(0.8); 
  wav = new AudioGeneratorWAV();

  // Blink起動
  Blynk.begin(auth_orihime, ssid, password );  // OriHime側Blynkサーバーと通信
}

int nafuda_num = 0;
bool display_flag = 0;

int orihime_num = 0;

void loop() {
    // Blynk更新
   Blynk.run();

   M5.update();

   if(M5.BtnB.wasPressed()){  

         M5.Lcd.drawJpgFile(SD, "/call_real.jpg");
         Serial.println("本体を呼び出し中");

         //本体呼び出し音を再生
         file = new AudioFileSourceSD("/call_real.wav");
         wav = new AudioGeneratorWAV(); 
         wav->begin(file, out);
         while(wav->isRunning()){
           if (!wav->loop()) wav->stop();
         }

         // リビング
         bridge1.virtualWrite(3, HIGH);   //リビング側(receive側) のV3ピンをHに
         Serial.printf("V3 : H");
         delay(1000);

         bridge1.virtualWrite(3, LOW);  //リビング側(receive側) のV3ピンをLに
         Serial.printf("V3 : L");
         delay(5000);
         display_flag = 1;
   }
}

BLYNK_CONNECTED() {
 bridge1.setAuthToken(auth_living);  // リビング側Blynkサーバーと通信
}
受信側(リビング通知側) Arduinoコード

リビング側のコードは、
『V3ピンがHighに上がったらお知らせ映像&音声を再生する』
だけのコードを実装します。

#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <HTTPClient.h>
#include "time.h"

// Audio speaker
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioOutputI2S.h"
#include "AudioGeneratorWAV.h"
AudioGeneratorWAV *wav;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;

#include <BlynkSimpleEsp32.h>
#define BLYNK_PRINT Serial
const char* auth_living   = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //リビング側(receive側) Auth コード
const char* ssid     = "xxxxxxxxxxxxxxxxxxxxxxx";   //自宅Wifi等のSSID
const char* password = "xxxxxxxxxxxxxxxxxxxxxx";  // 自宅WIfi等のSSIDパスワード

void setup(){
  M5.begin();
  Serial.begin(115200);
  delay(10);

  // WiFi設定
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //WAVの場合
  out = new AudioOutputI2S(0,1); 
  out->SetOutputModeMono(true);
  out->SetGain(0.8); 
  wav = new AudioGeneratorWAV(); 

  // Blink起動
  Blynk.begin(auth_living, ssid, password );
}


void loop(){

    // Blynk更新
    Blynk.run();
}

// BLYNKサーバーからお父さん呼び出し通知(v3)を受けた場合
BLYNK_WRITE(V3){
  int val = param[0].asInt();

  if(val == 1){
    display_information("calll_orihime");

  delay(3000);
  view_change = 1;
  }
}

void display_information(String str){
  M5.Lcd.drawJpgFile(SD, String("/" + str + ".jpg").c_str());
  file = new AudioFileSourceSD(String("/" + str + ".wav").c_str()); 
  wav = new AudioGeneratorWAV(); 
  wav->begin(file, out);
  while(wav->isRunning()){
         if (!wav->loop()) wav->stop();
  }
}

最後に

Blynkは無料ながらも簡単にクラウド経由で宅外通信が出来るのが魅力です。
そして、今回のBridgeウィジェットでデバイス間の宅外通信が出来るなら、
例えば、実家↔自宅の簡易通信(ライフログ確認)などを簡易マイコンのみの低コストで実現できるのはとても魅力です。

また、OriHime等の遠隔コミュニケーションロボットの外付けオプション機器としてうまく使っていけそうです。

最近では Obniz OSという新たなクラウド開発ツールもでてきたので、こことの使い勝手比較もやっていきたいですね。