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

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

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

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という新たなクラウド開発ツールもでてきたので、こことの使い勝手比較もやっていきたいですね。

息子向けポータブルモリビリティを改造してみた③ (速度可変+音声イルミ対応)

f:id:motokiinfinity8:20191007003312j:plain

製作動機

元の製作動機自体は、以前の記事を参照頂ければ、と思います。

ogimotokin.hatenablog.com


歩けない息子の足の代わりの移動手段としての電動機器
その操作練習を早めに始めるための機体として購入した子供用電動移動機器「Mottoy」

操作コントローラの課題については、前回記事の通り対応してジョイスティック等の各種コントローラで操作できる様にしました。
しかし、それでも息子はずっと怖がっていてなかなか練習が進みませんでした。

よく観察してみたところ、原因の一つは、
「突然動き出す等、移動速度が速すぎて怖がってる」
という事でした。

普段のおもちゃでは激しいのが好きなのですが、自分が動くモノについてはまだ不慣れな事もあり、激しい動きに過敏に反応してしまい、そこから拒否反応に繋がっている様です。

その拒否反応を何とか取り除きたいと思い、
今回の開発目標は
「Mottoyの移動速度を遅く変更すること(可変させること)」
を目指します。
それに加えて、
「乗ってて楽しくなる様なまるで遊園地の様な楽しい乗り物化」
も目指します。

完成品

速度可変した時のMottoyはこちら


更に 様々なコントローラ(電車でGoコントローラ/ Nintendo Laboバイク/ジョイコン)などにも対応させてみて、息子が好きそうなコントローラを模索してみます。


そして、息子に使って貰った様子はこちら


改造概要

先に言っておくと……
最終的には外装とモーター以外は全改造になってしまいました(笑)

f:id:motokiinfinity8:20191006233936j:plain

元々は、前回記事で製作したハードウェア回路を元に、Mottoyマイコンに繋がっている4本の制御信号(右モータ前 / 右モーター後 / 左モータ前 / 左モータ後ろ)を別マイコンからPWM制御する事で速度変更する構想でした。

しかし、、

Mottoy制御ユニットにPWM入力
→ うまく動かん。制御ユニットの仕様が不明

Mottoyマイコン変更、専用2chモータドライバに置き換え
→ うまく動かん。Mottoy搭載バッテリの電圧不足?

バッテリー変更(ラジコン用Ni-MH電池/7.4V)
→ 無事に動いた!

更に、Mottoy制御マイコンをなくした事で、Mottoyの元機能にあったイルミネーション、音声再生がなくなってしまったため、ハック用のESP32マイコンで制御可能なMP3モジュール/イルミネーションLEDを接続しました。

その結果、Mottoyの中身は完全に入れ変わってしましました。

f:id:motokiinfinity8:20191007003358j:plain


ソフトウェア

基本的には、以下の記事で記載したソフトウェアと同構成です。(細かいところは異なりますので、後日Githubに上げる予定)

ogimotokin.hatenablog.com


課題

一番悩んだのは、「モーター動作中のマイコン電源ノイズによるリセット」です。

特にモーターに負荷が掛かった際に突然ESP32マイコンがハングするという現象が多発しました。
オシロスコープで確認したところ、ESP32モジュールの5V電源がモーター負荷時に4V以下まで電圧降下するという現象が観測されました。電源ノイズを緩和するため、

 ・5V電源にバイパスコンデンサー追加(4700uFまで追加)
 ・モーター信号ラインにトロイダルコイル追加(470uHを追加)

をトライしてみましたが、現象は改善せず。。。

うーん、対策方法が分からない。。。なんでだ。。。

という訳で、暫定対策として、
マイコンボードにUSBバッテリーを接続し補助電源として使用」を導入しました。


※ 誰か詳しい方、改善方法についてご教示ください!(涙)


終わりに

今回、Mottoyの速度を遅くした効果からか、息子が怖がる様子が減ってきて、ようやく電動乗り物を受け入れてくれる様になりました!
ただ、やはりMottoyで残った課題は「シーティング(座位固定)」ですね。息子の様に単独で座れない子供にはもう一工夫いりそうです。
こちらの解決策としては、Mottoy専用の座位固定シートを開発 or 購入する事で解決できないか、と思います。


この様な「Mottoyの座位保持開発」と並行して、「座位保持可能な専用シート自体を乗せる電動台車を作る」という取り組みも進めていきたいと思います。

【メディア掲載】 歩けない息子のために「発明」を続ける父の想い (2019/9/18 デイリーポータルZ 掲載分)


障害を持った息子や家族のための個人メイカー活動をデイリーポータルZ様に取材頂き、2019/9/18に同サイトで掲載頂きました。

当事者目線×試行錯誤×ひと笑い

モノづくりにかける私の想いを等身大で存分に表現頂いており、また一笑いを加えた発明品の数々も紹介頂いております。

私の自己紹介として、ご一読頂ければありがたいです。

dailyportalz.jp






なお、本記事に記載されている発明品の一部は弊ブログに製作過程等を載せていますので、
ご興味のある方はリンクから参照頂ければ嬉しいです。

■車椅子をワクワク新幹線に変える自作モジュール
ogimotokin.hatenablog.com


■電動カートMottoy改造
ogimotokin.hatenablog.com
★本サイトで記載のある第二段の製作過程は現在執筆中


■車椅子を乗せる自作電動台車の製作
★現在執筆中


■息子の歩行リハビリ用光るメロディ靴
ogimotokin.hatenablog.com
ogimotokin.hatenablog.com
ogimotokin.hatenablog.com


■ボタンを押すと暴走するニャンニャン
ogimotokin.hatenablog.com


朝顔水やりロボット
ogimotokin.hatenablog.com



■息子の背中を伸ばす電子工作ピタゴラ装置
ogimotokin.hatenablog.com



■ワンボタンで出来るじゃんけん義手
★現在執筆中

【かんたん工作】 おもちゃ改造してワンワンぬいぐるみを暴走させてみた

本記事で伝えたいこと:大事なのは技術力じゃなくて「解決したい課題」に対する着眼力・アイディア力
f:id:motokiinfinity8:20191002194703j:plain

製作動機

f:id:motokiinfinity8:20190916094422j:plain

知的にも遅れのある息子氏。4歳を過ぎても周囲に対して鈍感で、何もせずぼーっとしている様な印象でした。

子供にとって好奇心こそ重要!
好奇心があってこそ、子供の成長は一気に加速する!

そう考えた我々両親は息子の好奇心をこじ開けるため、お気に入りのオモチャを探しまくってました。
そんな中、ようやく好みのおもちゃが見つかってきたのですが…
特に触りにいく事もなく、ただ見ているだけ…

息子に限らず重度障碍を抱えた子供は、ハンデがあり自分で体をうまく動かせないが故に人に介助してもらう機会が多いため、どうしても受け身がちになってしまう
やはり、そこから次の世界へ進み、
自分の意志を出していくきっかけを親として作っていきたい!

そんな試行錯誤の中で、
「息子が手を出すきっかけを作ってみよう!」
という取り組みで、息子のお気に入りの「ワンワン鳴くぬいぐるみおもちゃ」を改造してみました。

ベースはこのおもちゃシリーズ

あかちゃんシリーズ ビーグル ぬいぐるみ

あかちゃんシリーズ ビーグル ぬいぐるみ

  • メディア: おもちゃ&ホビー



[改造ポイント]
・ボタンを押した時だけワンワン鳴く
→ 「ボタンを押す」という自分のアクションで、動きが変わるという体験を楽しんで学んでもらう
・ただ動くのではなく激しく動く
→ 子供は「静」と「動」の変化が激しいほどウケる傾向があるので、これをもっと明確にしたら鈍感な息子でも反応するかも


物理スイッチを通して、本人のやる気スイッチを引き出す!

これを目指して取り組みました!



完成品

ボタンを押すと高速で動きだすワンワンおもちゃが出来ました!
普段の150%~200%の元気さで叫びます!


ちなみに、ワンワンぬいぐるみだけでなく、ニャンニャンぬいぐるみ等への応用も可能です。


息子の反応もものすごく良好で、1年経った今でも一番のお気に入りオモチャとしてずっと使ってくれています。
また、気軽に持っていけるので、療育園でお友達と一緒に遊んだりもあるし、展示会で出展しても非常に人気な改造おもちゃになりました。

製作方法

まず、「どうやってワンワンを激しく動かしたか?」と疑問に思う方も多いですが、仕組みは簡単です!

単三電池2個で動くおもちゃを
単三電池4個に増やしただけ
です


この発想は、一度ワンワンぬいぐるみを分解した時にひらめきました。

まさかのマイコンなしで、モーター1つで3つのアクションを切り替えるという神設計でした。
そこで分解して気付いたのは
「ん?モーター一つだけという事は……電圧を上げるだけで簡単に速度上がるやん」
という事でした。

※注意
今回は分解の結果、該当おもちゃがマイコンICを使わず、モーターのみを使用していた事が判明したため、上記の様に電池を増やすアイデアが適用できました。
万が一マイコンICが付いているおもちゃの電池を増やしてしまうと、最悪の場合 マイコンICが壊れてしまいますので、ご注意ください。

製作詳細

改造前後の製作図は以下です。

f:id:motokiinfinity8:20191002011222j:plain

部品名 個数 購入先
あかちゃんシリーズ ワンワンぬいぐるみ 1 Amazon
押しボタンスイッチ(モーメンタリ)赤 1 Marutsu
ケース(プラスチック製タッパ) 1 ダイソー
ELPA スイッチ&カバー付電池ボックス単3形*2本 UM-SC32NH 2 Amazon


以下は各部分の加工写真です。


・スイッチ端子に半田付けで配線を接着します
f:id:motokiinfinity8:20191002014334j:plain

・ボックスの構成。灰色線の中に2本配線が入っており、
 片側(線A)をスイッチへ、片側(線B)を電池ボックスの黒線に繋げています。
f:id:motokiinfinity8:20191002014428j:plain

・半田付けした場所は、絶縁テープなどでグルグル巻きします。
f:id:motokiinfinity8:20191002014530j:plain

・ぬいぐるみは、電池用のフタを開けて、おしりの方の単三電池プラス端子を線A、単三電池マイナス端子を線Bで半田付けします。
f:id:motokiinfinity8:20191002014820j:plain

・端子は面積が大きくて半田が溶けにくいので、はんだごてでじっくり熱を与えて、先に端子上にはんだの山を作るとやりやすいです!
f:id:motokiinfinity8:20191002015009j:plain



終わりに

本記事で書いた内容は、電気技術者にとってはすごく簡単な内容ですし、技術的にはなんら難しくはありません。だからこそ、初心者の方でも
「これなら、自分でも作れるかも」
「自分の子供にも作ってあげよう!」

と思えて、モノづくりの最初の一歩に繋がればいいなぁ、
と実験的に書いてみました。

…とはいえ、半田ごてを使ってる時点で初心者にはハードル高いかもしれないなぁ、と気付いてしまい、
そこは反省です。。。

技術者って、ついつい『高度な技術を使ってる方が価値がある』と手段前提の発想
になりがちなんですよね。
私自身もその発想に陥る事もありますし、実際にそれが勉強や研修目的であるならば非常に有効だと思います。


しかし、実際に誰かのためのモノを作る事を考えた時には
高度な技術が不要な事も多いし、
何より短期間で価値(本当に喜んでもらえるか)を確認する事が大事!

なので、
解決したい課題にダイレクトにつながりつつ
技術難度が低く、シンプルに、誰でも簡単に作れるモノ

もまた、非常に価値になると思います!

それに気付かせてくれた「暴走ワンワンおもちゃ」

是非とも一度作ってみてください!(^^)!

単身赴任の寂しさ解消!? 分身ロボットによる遠隔家族団らんチャレンジ

f:id:motokiinfinity8:20190915193059j:plain

私自身の活動テーマである「家族のためのモノづくり」

その一環として、昨年11月より使用させて頂いております
分身ロボットOriHimeの活用事例
について、OriHimeの製作元である
オリィ研究所 | オリィ研究所。株式会社オリィ研究所はOriHime-分身ロボットを開発・提供しています。様の公式ブログに執筆させて頂きましたので、
本ブログでも紹介!

・私の簡単な自己紹介 (「家族のためのモノづくり」に至った経緯)
・分身ロボットを使う事になったきっかけ
・活用事例①
 単身赴任生活において分身ロボットを活用した遠隔団欒は成立するか?

について、昨年11月での取り組みを記載しました。
今後、分身ロボットの我が家での活用事例について公式ブログ様で紹介させて頂ければ、と思います。


avatarworld.info


Twitter等で「家族のためのモノづくり」としての活動を発信し続けていった中で繋がった分身ロボットとのご縁、
大変ありがたいです!