OGIMOノート

7歳の娘と、5歳の息子(脳性麻痺)を持った父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具/ロボット関係の製作記録、勉強記録を残していきます

息子の歩行リハビリを楽しくするメロディ靴 Ver.4 を作ってみた

f:id:motokiinfinity8:20190216161758j:plain

はじめに

昨年7月に息子の歩行リハビリのモチベーションを上げるため、
足を踏み込むと楽しい音の鳴る電子工作靴の試作3号機を製作しました。

ogimotokin.hatenablog.com

作って以降、おうちリハビリで定期的に使ってきましたが、
息子自身の認知反応が薄かった事、足の成長に伴い靴のサイズが合わなくなった事もあり、少し様子見をしていました。
(別の音の鳴る市販おもちゃ等をリハビリ時に使用してなんとかカバーしてました)

そんな中、昨年秋ごろに周囲の環境に対する息子の認識力、好奇心がぐっと上がってきた事を感じ、
『自分の意思で前に進む体験をたくさん得て欲しい!』
という親の想いから、「歩行器練習に適した靴」として再度 メロディ靴を見直す事にしました!

前試作における良かった点/改善点と対応方針

OKだった点

・靴を無線にした事で歩行練習しやすくなった
・「好きな音」+ 「光」「振動」で息子の多少の興味を掴んだ!

NGだった点

・靴を光らせると下ばかり見てしまう、前に注目するモノが必要
・「歩きたい!」と思わせるほどの爆発的な面白さが足りない
・スピーカのボリュームが小さい、音質が悪い

対応方針

以上の事を踏まえて、前試作の靴部分は変更なし(靴のサイズのみ修正)として、
『制御部+スピーカ部をアップデート』する事にしました。
試行錯誤として、単なる足踏みすると楽しい音が鳴る機能に加えて、以下の2種類の追加機能を試しました。

① 液晶画面に好きな映像を表示
 ・息子の大好きなピタゴラスイッチの音源を再生
 ・数歩歩くと「ピタッゴラスイッチ~♪」とフィニッシュ表示
 ・ネタとして、妻や娘が好きなドラクエ・マリオのコイン音を再生

② カラフルLEDイルミネーションを光らせる
 ・右足を踏むとLED右側、左足を踏むとLED左側を光らせる
 ・足の踏み込む力(重さ)に応じて、LED光る量を変える
 ・音源は、息子が好きな妻のピアノ生音に変更
 ・左右交互に足踏みした時だけ正しく音が鳴る。失敗すると失敗のイヤな音

という事で両方を作ってみた
①の動画

②の動画


それぞれを使ってみて息子自身の反応を見たところ、①は画面がちっちゃすぎてあまり惹きつけ効果が薄かったです。
一方で、②の方で特にLEDに息子の目が釘付けだったので、最終的には②を採用して、実際に歩行器に搭載して試しました。

その結果、
不器用ながらも左右交互に足を出せる様に!!

もちろんこの発明の成果だけではなく、冬休み前から地道に歩行器練習を繰り返してきた経験が大きいとは思いますが、


父ちゃん、嬉しいであります!!!


全体ハードウェア

まずは、①の取り組みですが、制御+液晶表示+スピーカ再生手段として【M5Stack】に置き換えました。
過去のスピーカソフト@Arduinoとの互換性、私自身が開発に慣れたデバイスである事、内蔵スピーカ等を自作せずに済む事による開発のスピード感を優先したためです。

ブロック図は以下の通り。
f:id:motokiinfinity8:20190216145633j:plain

M5Stack 1つで素早く色々と実装できるので、やはり便利なデバイスだなぁ~!

一方で、②の取り組みですが、制御にはESP32 DevKit、LED表示にはLEDテープ(NeoPixel)、音再生にはDFplayerMiniモジュールを使用しています。前記事にも書きましたが、液晶ディスプレイを使わない場合、この組み合わせの方が非常にコスパ良く、色々と応用出来て良さそうです!

ブロック図は以下の通り。
f:id:motokiinfinity8:20190216150053j:plain

上記の①②を簡単に入れ替えて試せるのも、靴側は特にハード変更しなくて良い事、両者ともESP32ベースのソフトコードだからです。
モジュール共通化の考え方は、この様に色々と試してみたい場合に向いてますね。

②については、自作スピーカーとして音の改善を少しだけ検討してみました。
結果として、秋月電子に売っていた3W8Ωのスピーカを使い、スピーカ筐体は100均で売ってるプラスチックのタッパを使いました。
プラスチックの筐体内で音の響きあって、なかなか質の良い音が鳴りました。
見た目は悪いですが、コスパは素晴らしいので是非試してみてください。

f:id:motokiinfinity8:20190216162005j:plain


工夫した点は、スピーカ部のTWILIteモジュールとHost(M5stack/ESP32)との接続方法

本試作では、TWILITE DIPからの靴の圧力センサ値をUART信号で受信する方法にしました。
以前の3号機では、有線式試作とスピーカ部を共用させるという設計制約を設けていたので、
 ・靴にある圧力センサ値はスピーカ側のTWELITE DIPからPWMとして出力
 ・途中でRCフィルタを経由してアナログ電圧値に変換、マイコン側のアナログ端子で電圧を図る
という面倒くさいことをやっていました。
しかし、今回のスピーカ側の改定に伴い、一旦再度見直したところ、TWELITE DIPからのUART信号を使うのが簡単&応用しやすそうでした。

全体ソフトウェア

TWILITE DIPからの受信信号

TWELITEからのUART信号は、以下の様な信号が送信されてきます。

:7881150178810000380027D3000C05230000FFFFFFFFFF97
:788115017881000038002813000C02230000FFFFFFFFFF59
:78811501758100003800284F000C02230000FFFFFFFFFF20
:788115017581000038002899000C04230000FFFFFFFFFFD4
:0281150145810D0AFD000567000B171A8000FFFFFF007FE9 [右足]
:018115019C81003C170006F3000CDE18000041FFFFFFFDC2 [左足]

^1^2^3^4^5^^^^^^^6^7^^^8^9^^^a^b^c^de1e2e3e4ef^g
 
データフォーマット
 1: 1バイト:[0-1]送信元の論理デバイスID (0x78 は子機からの通知)
 2: 1バイト:[2-3]コマンド(0x81: IO状態の通知)
 3: 1バイト:[4-5]パケット識別子 (アプリケーションIDより生成される)
 4: 1バイト:[6-7]プロトコルバージョン (0x01 固定)
 5: 1バイト:[8-9]LQI値、電波強度に応じた値で 0xFF が最大、0x00 が最小
 6: 4バイト:[10-17]送信元の個体識別番号
 7: 1バイト:[18-19]宛先の論理デバイスID
 8: 2バイト:[20-23]タイムスタンプ (秒64カウント)
 9: 1バイト:[24-25]中継フラグ(中継回数0~3)
 a: 2バイト:[26-29]電源電圧[mV]
 b: 1バイト:[30-31]未使用
 c: 1バイト:[32-33]D1バイト:I の状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1がOn(Lowレベル)。
 d: 1バイト:[34-35]DI の変更状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1が変更対象。
 e1~e4: [36-37][38-39][40-41][42-43]  AD1~AD4の変換値。0~2000[mV]のAD値を16で割った値を格納。
 ef: [44-45] AD1~AD4の補正値  (LSBから順に2ビットずつ補正値、LSB側が  AD1, MSB側が AD4)
 g: [46-47] 1バイト:チェックサム

要は、":"記号をトリガにして送信される24Byte程度のデータから適切なものを抜き出すイメージです。
今回使うのは、
  1: 送信元の論理デバイスID →右足/左足判別用
 e1: 左足の圧力センサ値
 e4: 右足の圧力センサ値

の3つのデータになるので、これらを抜きとるコードを書けばOKです。
(e1/e2/e3/e4のどれを使うかは、回路構成に依存します)


以下のコードでは、シリアル送信信号(文字列)から左右の圧力センサ値(整数値)に変換するコードの例になります。

void loop() {

  (省略)

  // Serial受信(内部バッファへのコピー)
  rcv_buf_update();

  // Serialバッファからコマンド取得
  String cmdmsg = getCmdmsg();

  if(cmdmsg != ""){
    String device_id = (cmdmsg.substring(0,2)); //送信元の論理デバイスID
    String A1_tmp    = (cmdmsg.substring(36,38)); //左足
    String A4_tmp    = (cmdmsg.substring(42,44)); //右足

    // 左足の場合
    if(device_id.toInt()==0x1){
      //16進数文字列→Int変換
      if(A1_tmp[0] >= 0x30 && A1_tmp[0] <= 0x39)  l_sense_val = (A1_tmp[0]-48)*16*16;
      else if(A1_tmp[0] >= 0x41 && A1_tmp[0] <= 0x46)  l_sense_val = (A1_tmp[0]-55)*16*16;
      else  l_sense_val = 0;
      if(A1_tmp[1] >= 0x30 && A1_tmp[1] <= 0x39)  l_sense_val += (A1_tmp[1]-48)*16;
      else if(A1_tmp[0] >= 0x41 && A1_tmp[0] <= 0x46)  l_sense_val += (A1_tmp[1]-55)*16;

 //右足の場合
    }else if(device_id.toInt()==0x2){
      //16進数文字列→Int変換
      if(A4_tmp[0] >= 0x30 && A4_tmp[0] <= 0x39)  r_sense_val = (A4_tmp[0]-48)*16*16;
      else if(A4_tmp[0] >= 0x41 && A4_tmp[0] <= 0x46)  r_sense_val = (A4_tmp[0]-55)*16*16;
      else  r_sense_val = 0;
      if(A4_tmp[1] >= 0x30 && A4_tmp[1] <= 0x39)  r_sense_val += (A4_tmp[1]-48)*16;
      else if(A4_tmp[0] >= 0x41 && A4_tmp[0] <= 0x46)  r_sense_val += (A4_tmp[1]-55)*16;   
    }
  }

  (省略)
}



//内部バッファからコマンド命令の検索・抽出
String getCmdmsg(){
  String result = "";
  bool incmd = false;
  int start_pos, end_pos = 0;
  int i;

  //Serial.println(recv_buffer.indexOf(':')); 
  
  for( i=0; i<recv_buffer.length(); i++){
    if(incmd == false){
      // ":"捜索
      if(recv_buffer.charAt(i) == ':'){
        //Serial.println(" ");
        incmd = true;
        start_pos = i;
      }
    }else{
      // 改行コード捜索
      if(recv_buffer.charAt(i) == 0x0A){
        incmd = false;
        end_pos = i;
        // メッセージ抽出 & メッセージより前のフレーム破棄
        result = recv_buffer.substring( start_pos+1, end_pos);
        recv_buffer = recv_buffer.substring(end_pos+1, recv_buffer.length());
        break;
      }
    }
  }
  return result;
}

既存発明品の流用の数々

それ以外の制御については、今まで作ってきた工作品での要素技術を組み合わせて実現しました。

(1)については、過去に作ったM5Stackの音声/映像再生部を流用しました
ogimotokin.hatenablog.com
ogimotokin.hatenablog.com

(2)については、クリスマスに子供のために作ったクリスマスツリーのイルミネーション技術
音声再生についてはじゃんけんロボットの音声再生モジュールを転用しました。

ogimotokin.hatenablog.com
ogimotokin.hatenablog.com

今まで短期間でたくさんモノを作ってきたノウハウを組み合わせてます!

開発ソース

別途 Github に公開予定

まとめ

今回は、息子の歩行器練習のモチベーションを上げるためのメロディ靴を作り、実際のリハビリ練習で定期的に使えるものが出来ました!
ただモノを作って終わりにするではなく、
実際に継続して使い続けれること
にとにかくこだわりました。
家族で試行錯誤しながら機能を考えたり、オンラインコミュ、SNS、ピッチイベント等で試作品を公開してこれをベースに一緒に改良アイデアを検討して頂けたり、PT/OT先生と一緒に現物でチューニングを繰り返せたり……

息子という実際に使ってくれるユーザーが目の前にいるからこそ出来る
家族のためのモノづくり

私自身も楽しみながら出来ました!


息子向けとしては、もうしばらく使って貰いながら、必要に応じて機能追加&改善を試みたいと思います。
今のところ、気になっているのは、靴部分の電池。現在はCR2032×2個使いなので、使えば使うほど電池を消費してしまうので、例えば充電タイプのものに変更するなどは検討しています。(とはいえ、子供の足部分にリチウムポリマー電池を置くのはちょっと抵抗あるから、そこは悩みどころ…)

もし息子以外で同様にお困りごとを抱えている方、「作ってみたい」という方がいるならば、改めてもう少し簡単に作れる手順を模索してみようかなぁ~