2023年4月29日土曜日

介護ベッドの就寝・離床の見守りセンシング

これは、2021年10月の日誌を纏めたものです。
色々と思い出すので今頃になってしまいました(T_T)

隣の実家に居る母上、ベッドから自分で起きれるのですが、
トイレの介助とか、転倒しないようにとか見守りが必要なのです。
が、ベッド柵にワイヤレスチャイムの送信ボタンを置いてても
認知症が進んできて、起きる時にボタン押すのを覚えれないので
今は、頃合いを見て看に行っています。
時間がぴったし決まっているわけではないので
ベッドから起き上がったことを検出してチャイムを鳴らしたいのです。
試行錯誤ほぼ全部の記録なので、また長~いです^^;

この手の介護用品は、探せばあるのでしょうが
製品となると見逃しは許されないので、数万~十数万円と高価です。
それに「起き上がった」を検出・判定するのは
人それぞれに異なりますからね~

早速、モノタロウを探していると、パッド類は高価なものが多い中、
おっ!安い感圧シートがあるではないですか!
品番: 918-4756
大きさ:595 x 170mm 厚み:3mm
サイトの写真を見る限り、足で踏むには耐久性がなさそうだし、
枕の下だと頭の重さでは無理そうだし、
お尻や背中辺りに敷けばいけるかも?
ダメ元でポチりました^^;

で、到着前にある程度スケッチを作っておきます。
検出回路は、当ブログで人気No.1のATTINY85を使うことにします。
のスケッチのボタン操作部を改造すれば
手っ取り早くいけそうです。

まだ、圧力パッドスイッチが届いてなくて
圧力によって抵抗値が変わるのかわかりません。
変わってもいいように、アナログ入力で受けることにします。

仕様を考えます。
<離床チェックモード>
・1sec間隔で感圧チェック
・感圧抵抗が設定値以上で十数秒続いたら「離床」と判断
・「離床」の判断でワイヤレスチャイムを2回鳴らす
<就寝チェックモード>
・1sec間隔で感圧チェック
・感圧抵抗が設定値以下で十数秒続いたら「就寝」と判断
・「就寝」したら「離床チェックモード」に戻る

ちょっとスケッチを改造していたら
ピカッと閃いて^^;
CapacitiveSensing(容量検知センサー)でできるんじゃないか?
タッチパッド代わりのアルミ箔を枕の下に敷くだけでいいかも?
の時に小さいアルミ箔で実験したやつです。
すっかり忘れてますが、そういう時にブログが役に立ちます^^;

その時の動画はこれです。
もう5年も経ったのか~(・o・)

まずは、小型にしたいので上でやったのをATTiny85に移植しようと
DigisparkのPINアサインは、
Digistump CreatedのDigispark回路図は、このPDFを見て
Board内に何もぶら下がっていないPB0、PB2、PB5を使おう!
と、配線図とスケッチ書いて~

いざ、書き込もうとしたら・・・問題が!(´-﹏-`;)
ATTiny85は、チップ内にSerialを積んでないので
スケッチに記述が必要で、かなり遠回りになることを思い出し
UNOでやることにします^^;
PB2:センシング  PB2~PB4:10MΩにします。
・Send Pin:PB4
・ReceivePin:PB2
として
・PB2:10KΩ(耐静電気、抵抗の先にタッチパッド)
・PB2~GND間:56pF
・PB4 ~ PB2:10MΩ(※ 最終:1MΩ)
・LEDはLED_BUILTINを使ってます。
※ 実は、後で判ったのだが、PB4 ~ PB2:10MΩと思い込んでて
ずっと 1MΩをつけて実験してたのです(-_-;)
最終的には、1MΩの方がよいという結果になったのですが・・・

配線図
LED(図の極性が逆かな)は、後で使います^^;

実物!

参考にしたplayground.arduino.ccのサイトの下の方にある
「Example code: Threshold」のを少し変えただけで
まだ、反応をみて設定値を調べるためのスケッチです。
マーティーの解釈で日本語コメントを入れてます^^;
赤文字が変更・追加した箇所。

*****
#include <CapacitiveSensor.h>
CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2);
     //2pin:センシング  2-4pin:10MΩ
unsigned long csSum;
int LED_State = LOW;

void setup() {
    Serial.begin(9600);
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
    CSread();
}

void CSread() {
    long cs = cs_4_2.capacitiveSensor(80);
      //a: Calibration時の読取値からの増分をサンプル数80でサンプリングした合計値
 if (cs > 200) {
      //b: csが200を超えるとSerialに数値を出力する
   csSum += cs;
      //csがb(200)を超えている間は、LOOPする毎にcsSumに加算していく
// Serial.println(cs);
    Serial.print(cs); 
    Serial.print("\t");
    Serial.println(csSum); 
     if (csSum >= 50000)
      //c: csがb(200)を超え続けて加算されたcsSumがc(50000)を超えるとTriggerと判定する
     {
        Serial.print("Trigger: ");    //Serialに"Trigger"文字を出力
        Serial.println(csSum);        //Triggerした時のcsSum値をSerialに出力

        if (LED_State == LOW){ // Current State LOW
          digitalWrite(LED_BUILTIN, HIGH);
          LED_State = HIGH;
        } else { // Current State HIGH
          digitalWrite(LED_BUILTIN, LOW);
          LED_State = LOW;
        }

          if (csSum > 0) { csSum = 0; } //Triggerしたら一旦csSumをClear(Reset)
            cs_4_2.reset_CS_AutoCal();    //読み取り停止してCalibration実行
     }
  } else {
    csSum = 0;
     //パッドから離れてcsがb(200)を下回るとcsSumをClear
     //又は、抵抗がなかったり、容量が大き過ぎて読み取りがTimeoutした場合
  }
}

*****

この時の実際の動画ではないけど、同じ機材&スケッチでの動画です。
Sensing端子の抵抗の足に指を接近(0.5~1mm)していくと
左の cs が200を超えれば数値を表示して、
右の csSum が加算されて、50000を超えるとTriggerになります。
離れるとカウントしなくなり、csSumをClearします。
指を接触すると、一気に50000を超えてTriggerになります。
TriggerでUNO基板の「L」LEDがトグルでON/OFFします。

ひとまず、5年前のお試し状態が再現できたので
タッチパッドの代わりに、調理用アルミ箔だと薄くて破れ易いので、
キッチン用の油よけのアルミシートを百均でゲット!
酸化膜をちょっと磨いてから、みのむしクリップで繋ぎます。

でかいアルミシート単体では、先の動画と同等に動作したので
まずは、テーブルの上にアルミシート
その上に自分の蕎麦殻の枕(約10cm厚)をの上に置きます。
10cm厚なので cs値が小さく積算に時間が掛かるので
if (csSum >= 2000) にすると
枕の上に手を置いて、2~3秒毎にTriggerがかかり
頭を置くと、0.5~1秒毎にTriggerがかかり、いい感じのようです。

所が、実際に使うプラパイプ入りの枕(約10cm厚)でやると
予感はしてたのですが、感度がかなり低下するのです(T_T)
cs や csSum の条件判断を色々変えてるも
頭を置いた瞬間の1回だけTriggerさせるのが関の山(T_T)
瞬間でなく、置いた状態を検出できないといけないのですが・・・
枕を変えると誰でも寝れなくなるしですね~(´・ω・`)

そもそも静電容量の変化を利用しているので
アルミシートから10cmも離れてれば、頭の接近の変化は微小です。
変化が微小でも値が安定していれば、検出できるけど
揺らぎ成分が判定の邪魔をして誤動作を回避できないのです(T_T)
たぶん揺らぎは、AC電源(60Hz)の誘導が原因でしょう。

変化微小と揺らぎの問題を解決すべく、スケッチと格闘します。

まずは、
   long cs = cs_4_2.capacitiveSensor(80);
のサンプル数「80」を
   long cs = cs_4_2.capacitiveSensor(800);
と大幅に上げてみるも、csの挙動はさほど変化なし(T_T)
どうも積算ではなく、マクロ内で平均化されてるご様子・・・却下!

・・・色々やったあげく

参考にしたスケッチでは、
cs >200が継続しないと csSumに積算されない仕様なので
   long cs = cs_4_2.capacitiveSensor(80); 
常時50回積算してから csSumを判定するようにしたら
「変化の増幅」と「揺らぎ軽減」できそうになった。
   csSum>7000・・・何も置かない時、たまにトリガーがかかる。
   csSum>7500・・・いい感じで枕の頭を認識してくれるようになった。
7500を微調整すれば、うまくいきそう(^^)
1回ルーチン(判定)に0.7秒程かかるが問題ないだろう。
***BedSensing_CAP-Sens_UNO_2021-1023C.ino***
 ~
void CSread() {
   for (short i=0; i<=50; i++){  //50回の積算化
    cs = cs_4_2.capacitiveSensor(80);
 ~
//if (cs > 200) {  //判定止め
   csSum += cs;
 ~
   if (csSum >= 7500
 ~
******

ちょっと集中力が不調で頭が働かず
一時は、1秒寝て、頭を1秒起こしてもチャイムが鳴ってしまったり
枕を整えて、手を離すと、十数秒後に鳴ってしまったり
就寝と起床の判定にだいぶ悩んだ末
(今気づくに、いつの間にか 離床 ⇒ 起床 に変わってます^^;)
・・・・・
で、変数を追加
CountUp_SLEEP
  頭を置いてからのカウント値
で頭を指定時間以上置いてれば、就寝と判定してFlagを立てる。
一旦、就寝Flagが立って、
CountDown_WAKE
  就寝Flag:Trueで、頭を上げてから減算カウント値
頭を上げ続け、CountDown_WAKEがゼロになったら起床と判定して、
Trigger信号を出す!
就寝後ちょっと頭を上げても、起床と誤判定しないようにできた。
・・・どうやら、できたみたい(^^)
スケッチは、最後に載せま~す^^;

やっとできそうになってきた所で、突然、UNOの調子が悪くなり_| ̄|○
今は、治す余裕がないので、NANOに移植することに^^;
で、NANOでの配線図!
(黄色クリップでアルミシートと接続しています)

NANOに換えて、まだ、テーブルの上での実験状態です^^;
実際のに近いプラパイプ入り枕をアルミシートに乗せてます。

所が、極端にセンシングの更新が遅くなったのです(T_T)
PORTを変えみたりしてもダメ(T_T)
調べていくと、何と!
PB4 ~ PB2間の抵抗の推奨値が10MΩなので
UNOの時、10MΩのハズだった抵抗が、1MΩ!(・o・)
NANOでは、10MΩをつけていたのです。
下の写真の差なのです。
マーティーの眼(脳かな)が、緑を青だと誤認してたようです。
分かってしまえば、見分けが付くのですが、と言い訳^^;
しばらく、推奨値の10MΩで検討したけど、1MΩで速いサンプリングの方が
揺らぎが断然少ないので、1MΩで進めます。
まあ、NANOに変更して、これに気づいて
結果的によい勘違いだったということで・・・^^;

やっと、UNOと同じと思われる状態になりました(^^)
しか~し、実験セットをテーブルから移動して
実際のベッドとプラパイプ枕でやると、反応がかなり変なのです。
手を置くと、逆にcs値が下がったりします。
枕の中のプラパイプが静電気を帯びて状態が変わったのか?
別の種類のプラパイプなのか?
・・・・・
そうだ、頭じゃなくて、足にすればいいんじゃ?
シーツ(厚手の毛布調)1枚なので、10cm厚の枕より断然薄くなり
確実に接近を検出できるハズ!
幸い、いつも足を伸ばして寝てるので、いけそうです。
レンタルの介護用ベッドの足側です。

そこの毛布調シーツの下にアルミシートを敷いて

NANOのセンシング端子に繋いで、シーツを元通りに被せます。
NANOの電源は、AC~USB電源アダプタで供給してます。
この状態でアルミシート部の上に手を乗せると
うまく反応してくれ、乗せた時だけLEDが点灯しました。

所が、いざ全身をベッドに横たえると、全く反応しません(T_T)
足or手が畳に接触してないと、うまく反応しないのです。
靴下を履いてても畳に立ってれば、反応するのです。
築50年超えの古い建築なので、畳の下は薄い板、床下は土です。
ん~ん、これは困りました~(´-﹏-`;)
ちなみに、ベッド柵(金属)を手で握ってもダメ。
ベッド足のプラカバーと敷物で、床と絶縁状態になってるからか?

NANOをPCに接続して、csとcsSumをモニターします。
ベッドに全身だと、足を畳につけてる時より全体的に値が低めの様子。
電池駆動PCのUSBからNANOに給電すると
ベッドに全身では、極端に値が小さくなる。
AC~USBアダプタでNANOに給電してもACプラグの極性に影響しない。
結局、AC~USBアダプタ給電で、調整すればいけそうです!^^;

で、以前からこのワイヤレスチャイムを使ってて
送信ボタンをトイレ、ベッド脇、廊下の途中とかに貼付け
受信機は、マーティー工房住居の2部屋に置いてました。
20mほど離れた隣家と壁を何枚も隔てた部屋でも通信できます。
ただ送信機をアルミサッシの枠に張付けると飛距離が少し落ちました。
昨今は、送信機に電池のいらない自己発電タイプもありますね~
回路は知りませんが、今回の様な用途には向かないかも?
執筆中の今は、もう黒しか残ってないな~
Amazonのここから


マーティーが所持してるのは、この白タイプ。
白が先に売れるのはわかる気がします^^;

送信ボタン側を開けます。
CR2032 3Vの電池駆動です。

ビスで留まってた基板を取り出して~

ボタンはポロッと外れます。
基板中央にタクトスイッチがあるので、パターン追って

電源(赤)、GND(白)、ボタン押下線(黄)を引き出します。
ボタンを押すと黄色線がGNDに落ちるLOWアクティブです。

ケースに戻して

裏蓋を被せて、NANOに結線して、完了!

配線図は、これ!
ボタンは、LOWアクティブなので、検出時にD3がLOWに下がり
ダイオードを介して送信ボタンの黄色線をLOWに下げます。
ダイオードは、送信ボタンの電源を3.3Vにしてるので
NANOのHIGH 5Vに対して逆流防止の役目です。

スケッチは、これ!
アルミシートでの容量検知センサーの最終版です。
***BedSensing_CAP-Sens_NANO_2021-1025H***
#include <CapacitiveSensor.h>
CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2);
     //2pin:センシング  2-4pin:10MΩ⇒1MΩに間違っていた

#define nCHIME 3 // PB3 for チャイム制御出力、LOW Active

unsigned long csSum;
int LED_State = LOW;
long cs = 0;

short StateThresh = 6000; // WAKE、SLEEPの閾値、全身ベッド上

short CountDown_WAKE = 0; // WAKEした時のカウントダウン
short LastCountDown_WAKE = 0; // 直前のCountDown_WAKE値
short WateTime = 10;          // このカウントWAKEしたらチャイムを鳴らす、約1sec/count

short CountUp_SLEEP = 0; // 就寝したかのカウントアップ
short SleepTime = 12;  // このカウントSLEEPしたら寝たと判断する、約1sec/count

short SleepFlag = 0; // 1:SLEEP、0:none
short WakeFlag = 0; // 1:WAKE、0:none

void setup() {
    Serial.begin(9600);
    pinMode(nCHIME, OUTPUT);  //  チャイム制御出力
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
    digitalWrite(LED_BUILTIN, HIGH);  // 内蔵LED
    digitalWrite(nCHIME, HIGH);  // チャイム制御出力
    CSread();
}

void CSread() {

   for (short i=0; i<=100; i++){   // 全身ベッドではかなり値が小さくなる為
      cs = cs_4_2.capacitiveSensor(80);
      //Calibration時の読取値からの増分をサンプル数80でサンプリングした合計値
      //80 ⇒ 8000や80000にしても変化が認められなかった
      //forで積算した方が感度が顕著に上げられた
      Serial.println(cs);
      csSum += cs;
   }
    Serial.print(cs); 
    Serial.print("\t");
    Serial.print(csSum);
    Serial.print("\t");
    Serial.print(CountDown_WAKE);
    Serial.print("\t");
    Serial.print(LastCountDown_WAKE);
    Serial.print("\t");
    Serial.print(CountUp_SLEEP);
    Serial.print("\t");
    Serial.println(SleepFlag);
    
   if (csSum >= StateThresh){  // 超えるとSLEEPと判定する
          StateCountUpSLEEP(); // 就寝時間をカウント
          CountDown_WAKE = WateTime;  // カウントダウン値をRESET
      
          Serial.print("Trigger: ");    //Serialに"Trigger"文字を出力
          Serial.println(csSum);        //Triggerした時のcsSum値をSerialに出力

          digitalWrite(LED_BUILTIN, HIGH);
          digitalWrite(nCHIME, HIGH);  // チャイム出力OFF
         
            if (csSum > 0) {
              csSum = 0; //Triggerしたら一旦csSumをClear(Reset)
            }
          cs_4_2.reset_CS_AutoCal();    //読み取り停止してCalibration実行
       }
    else {
          //csSumが(StateThresh)未満だとWAKEと判定する
          StateCountDownWAKE();  // WAKE検出した時のカウントダウン
          for (short j=0; j<=3; j++){
              // 離床時 内蔵LEDを点滅
              digitalWrite(LED_BUILTIN, LOW);
              delay(50);
              digitalWrite(LED_BUILTIN, HIGH);
              delay(50);
          }
          
              if ( CountDown_WAKE == 0 && LastCountDown_WAKE == 1 && SleepFlag == 1 ) {
              // WateTime時間のカウントダウンが終わったらWAKEした判定
                  WakeFlag = 1; // WAKEフラグを立てる・・・使ってない
                  SleepFlag = 0;  // SLEEPフラグRESET
                  LastCountDown_WAKE = 0;  // 不要かも?
              // チャイムボタンを2回押す
                  digitalWrite(nCHIME, HIGH);
                  delay(100);
                  digitalWrite(nCHIME, LOW);
                  delay(300);
                  digitalWrite(nCHIME, HIGH);
                  delay(1000);
                  digitalWrite(nCHIME, LOW);
                  delay(300);
                  digitalWrite(nCHIME, HIGH);
              } 

           CountUp_SLEEP = 0; // ちょっとでも起きたらSLEEPカウントをRESET

    }

    csSum = 0;
    cs_4_2.reset_CS_AutoCal();    //読み取り停止してCalibration実行
     //抵抗がなかったり、容量が大き過ぎて読み取りがTimeoutした場合

}


void StateCountUpSLEEP() { // SLEEP状態 
  // 就寝を検出したらSleepTimeまでカウントUP
  if ( (0 <= CountUp_SLEEP && CountUp_SLEEP < SleepTime) ){
    CountUp_SLEEP++ ;
    if (CountUp_SLEEP == SleepTime){
    // CountUp_SLEEP == SleepTime で就寝フラグを立てる
      SleepFlag = 1;
    }
    else {
    }
  }
}


void StateCountDownWAKE() { // WAKE状態
   // 1 以上 ~ WateTime以下:減算
  if ( (1 <= CountDown_WAKE && CountDown_WAKE <= WateTime)){
    LastCountDown_WAKE = CountDown_WAKE;
    CountDown_WAKE-- ;
  }
}
******

ひとまず、NANOと送信ボタンは、箱に入れてベッドの下へ
電源は、AC~USBアダプタです。
母上がデイケアから帰ってきたので、寝てもらいました。
が、マーティーが寝て設定したのから閾値を変えないとうまくいかず(T_T)
掛け布団の影響か、身体の水分が少ないからか?
寝た状態でNANOをRESETするとダメなのかも?
csSum判定の閾値をVR調整できるように改造するのは面倒だし・・・
PCに繋いで閾値を変更を何度か繰り返し、なんとか閾値を調整して
完璧じゃないけど、ひとまず動くようにしました。
誤判定でチャイムが鳴ることも多々ありましたが
数日間は、無いよりはマシ程度の役に立ちました^^;

そこへ冒頭のモノタロウの感圧シートが届きました!
品番: 918-4756

大きさ:595 x 170mm 厚み:3mm(ものさしは30cm)
足元に敷くのにちょうど良さげな大きさです(^^)

袋には、このラベルだけ

当時、メーカーサイトに大型タイプのDatasheetがあったのですが
執筆中には、消え去って、
そのPDFのSpecificationsに
「25Kg over 50mm² actuation pressure」とあります。
50mm² (≒直径8mmの円)以上に25Kgという意味か?
やけに重みが必要なようですが、意味が違うのだろうか?

外殻は、PVC(ポリ塩化ビニール)でやや厚手な感じ
手のひらで押さえると

2.5Ω  x1レンジです。
それほど強く押さえてないので
Datasheetの「25Kg over 50mm² actuation pressure」は
「作動圧 50mm² 以上に25Kg」という意味ではなさそうですね~

線は4本出てますが、内2本はダミー
たぶん、Datasheetの大型タイプので使うのでしょう。

感圧抵抗のようなので
グラフでも作ってみようかと、この軽量計でやってみます。

そのまま乗せると、両側は地についているので、59g

TAREしてゼロにします。

小石を乗せて、490g

振れません

石2つで1300g

まだ振れません

石3つ 1700gでどうだ!

やっと振れました!
23Ω
手を軽く乗せた時と反応が異なってるような・・・

抵抗レンジ x1 です。

一番下の石、ざっくり 110 x 75 の楕円として面積は、
3.14 x 110 x 75 ≒ 25900 mm² に1700gとして
50mm²に換算すると、3g・・・何か間違ってるような(-_-;)
石の底が丸いのは加味してないしな~

このプラケースだと、50 x 35 = 1750mm²

その上に石を乗せて
1302g

振れてくれません

この消しゴムだと、40 x 18 = 720mm²

指で押さえて、2590gで

60Ω
結構な重みじゃないと反応してくれないのかあ(~_~)
手のひらの時は、そんなに荷重掛けてなかったんだけどな~

で、消しゴムを写真左のから右の位置にズラしたら

指で押さえて452g
40 x 18 = 720mm² を50mm² 換算すると、31g

30Ω
これだと、かかとの重み程度で反応しそうです。
かかとの重さは測ったことないですが・・・(-_-;)
やはり「25Kg over 50mm² actuation pressure」は、
作動圧じゃなくて耐圧じゃないのかな~?

上と同じ位置に石を1個で810g

9Ω
あまり意味のない実験になりグラフにはできませんね~(-_-;)

ちなみに、何も乗せてない時

最高の x10Kレンジでも

∞ を指しています。

ちなみに、布団の上に敷いて、頭を乗せて寝るとONします。
プラパイプ枕より重めの蕎麦殻枕を載せても反応せず、
その上にマーティーの頭を乗せても∞のままでした。
横になって片足のかかとを乗せると反応してくれます。
微妙に足を浮かせると、2~100Ω 辺りで変動します。
先の実験では、場所によって反応が異なってましたが
かかとだと、どこに乗せても確実に反応してくれます。
が、アルミシートより縦が半分程度になるのが心配です。

NANOに接続します。
突貫工事なので、この箱のままベッド下に置きます^^;

拡大!

配線図
基本は、アルミシートの時と同じです。
感圧マットのもう一方を5.6KΩで5V PullUpを追加してます。
上の写真では、先を急いで、送信ボタンの電源も5Vにしてますが
3.3Vにしとかないとまずいです。

と言うのは、執筆がほぼ終わって気づいたのですが(-_-;)
送信ボタン基板写真のIC「CMT2157B」と読めたので
CMOSTEK社のPDFのDatasheetを見つけたところ
VDD Max:3.6Vでした!(-_-;)
このIC、ボタンが7個付けれるので、面白いことできるのかも?

スケッチを圧力パッド用に少々変更します。
CapacitiveSensor関連を削除して、
単純にPB2のHIGH/LOWを監視するだけ
離床・就寝の判定は、そのままです。
執筆中に動画撮影の為、Serial print部だけ変更しましたが、
製作から1年半経過して、中身がするっと読めません(-_-;)
変数 LastCountDown_WAKEは、何のためだったかな~
基本動作は、
◆ 12秒間パッドに乗ってると就寝と判定し就寝Flagが立つ
◆ 就寝後は、10秒間パッドから離れると起床と判定しボタン押下
◆ それより前にパッドに乗ったり離れたりした場合は、無視
***BedSensing_Pres-PAD_NANO_2023-0423***
#define Pad_In 2 // PB2 for Pressure PAD 
#define nCHIME 3 // PB3 for チャイム制御出力、LOW Active

int LED_State = LOW;

short CountDown_WAKE = 0; // WAKEした時のカウントダウン
short LastCountDown_WAKE = 0; // 直前のCountDown_WAKE値
short WateTime = 10;          // このカウント(約1sec/count)WAKEしたらチャイムを鳴らす

short CountUp_SLEEP = 0; // 就寝したかのカウントアップ
short SleepTime = 12;  // このカウント(約1sec/count)SLEEPしたら寝たと判断する

short SleepFlag = 0; // 1:SLEEP、0:none

void setup() {
    Serial.begin(9600);
    pinMode(Pad_In, INPUT); // from 感圧パッド
    pinMode(nCHIME, OUTPUT);  //  チャイム制御出力
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
    digitalWrite(LED_BUILTIN, HIGH);  // 内蔵LED
    digitalWrite(nCHIME, HIGH);  // チャイム制御出力
    CSread();
}

void CSread() {

    Serial.print("Pad: ");
    Serial.print( digitalRead(Pad_In) );
    Serial.print("   ");
    Serial.print("起床CountDown: ");
    Serial.print(CountDown_WAKE);
    Serial.print("\t");
    Serial.print("就寝CountUp: ");
    Serial.print(CountUp_SLEEP);
    Serial.print("\t");
    Serial.print("     就寝Flag: ");
    Serial.println(SleepFlag);
    
// if (csSum >= StateThresh){
   if (digitalRead(Pad_In) == LOW) { 
      //Pad_InがLOWだとSLEEPと判定する
          StateCountUpSLEEP(); // 就寝時間をカウント
          delay(300); //  LOW時の1秒間隔の微調
          CountDown_WAKE = WateTime;  // カウントダウン値をRESET
      
          digitalWrite(LED_BUILTIN, HIGH);
          digitalWrite(nCHIME, HIGH);  // チャイム出力OFF
         
       }
    else {
      //Pad_InがHIGHだとWAKEと判定する
          StateCountDownWAKE();  // WAKE検出した時のカウントダウン
          for (short j=0; j<=3; j++){
              // 離床時 内蔵LEDを点滅
              digitalWrite(LED_BUILTIN, LOW);
              delay(50);
              digitalWrite(LED_BUILTIN, HIGH);
              delay(50);
          }
          
              if ( CountDown_WAKE == 0 && LastCountDown_WAKE == 1 && SleepFlag == 1 ) {
              // WateTime時間のカウントダウンが終わったらWAKEした判定
                  SleepFlag = 0;  // SLEEPフラグRESET
                  LastCountDown_WAKE = 0;  // いるのか?
              // チャイムボタンを2回押す
                  digitalWrite(nCHIME, HIGH);
                  delay(100);
                  digitalWrite(nCHIME, LOW);
                  delay(300);
                  digitalWrite(nCHIME, HIGH);
                  delay(1000);
                  digitalWrite(nCHIME, LOW);
                  delay(300);
                  digitalWrite(nCHIME, HIGH);
              } 

           CountUp_SLEEP = 0; // ちょっとでも起きたらSLEEPカウントをRESET

    }

  delay(800); // 1秒間隔でPad_Inを見に行くため

}


void StateCountUpSLEEP() { // SLEEP状態 
  // 就寝を検出したらSleepTimeまでカウントUP
  if ( (0 <= CountUp_SLEEP && CountUp_SLEEP < SleepTime) ){
    CountUp_SLEEP++ ;
    if (CountUp_SLEEP == SleepTime){
    // CountUp_SLEEP == SleepTime で就寝フラグを立てる
      SleepFlag = 1;
    }
    else {
    }
  }
}


void StateCountDownWAKE() { // WAKE状態
   // 1 以上 ~ WateTime以下:減算
  if ( (1 <= CountDown_WAKE && CountDown_WAKE <= WateTime)){
    LastCountDown_WAKE = CountDown_WAKE;
    CountDown_WAKE-- ;
  }
}
******

当初、上のスケッチは、幸いミスなくすんなり動きました(^^)
感圧パッドをかかとが乗る辺りに敷きますが、
幅が狭くなったので、位置決めが大事です。
母上の場合、ほとんど、足を曲げたり動かしたりしないので
これでいけると思うのですが、場合によっては、パッド2枚いるかも?

シーツを被せます。
NANOは、箱に入れてベッドの下に置いたまま。

当時、動画を撮ってなかったので
執筆中に実験風景を再現しました!
足のかかとの代わりに鉄アレイ(5kg)です^^;
この鉄アレイだと、パッドの場所によって反応しないことがありました。

解説が長いですが、動作状況を動画で!
・鉄アレイ置く・・・Pad:0、鉄アレイどかす・・・Pad:1
・起床中・・・就寝Flag:0、就寝中・・・就寝Flag:1
PC画面は、Arduino IDEのSerial Monitorです。
[00:32]鉄アレイ置きPad:0、就寝CountUpが始まり
     12カウントしたら、就寝Flag:1になります。
[00:36]鉄アレイどけてPad:1、起床CountDownが始まり
[00:48]10カウントしたら、送信ボタンがLOWになり
     ワイヤレス親機のチャイムが鳴ります。
[00:56]再び、鉄アレイ置いて
[01:02]起床CountDown 5カウント、就寝Flag:0の時にどける
    (起床後、12カウント未満、圧力パッドを押さえた場合
     ・・・就寝と判定しない)
[01:14]起床CountDownが始まり、10カウントしますが
     チャイムはなりません。
[01:19]再び、鉄アレイ置いて
[01:34]就寝CountUp:12で、就寝Flag:1となり
[01:38]一旦、鉄アレイをどかして
[01:45]起床CountDown:4 で鉄アレイ置いても
    (就寝後、10カウント未満だけ圧力パッドから離れた場合
     ・・・起床と判定しない)
[01:47]就寝Flag:1のまま、起床CountDown:10に再セットされます。
[01:54]就寝Flag:1の状態で鉄アレイどけると、起床CountDownが始まり
[02:05]起床CountDown:10が終わると
     起床を知らせるチャイムがなります。

本番では、夜中に足を動かしたのか?
チャイムが鳴って行ったら寝てたってことが数回ありましたが
概ねうまいこと動作していました。
段々と自力で起き上がれなくなったので
適宜、起こしてあげないといけなくなったのですが
突然起きる日もあり、この装置は、なかなか役に立ちました。

一方、父上の方は、
寝返りをよくするし、足を曲げたり、枕から頭がズレてたりと
この方法が全く使えないのですが、認知症にはならなかったので
ベッド柵の両側に送信ボタンをぶら下げて、
用事の時に押してもらえました。

介護系のものは、一人一人状況が異なるし、経過で変わってくるし
随時カスタマイズが必要なのでなかなか難しいですね~
この例が役に立つ方がおられると幸いです。
が、完璧な装置には仕上がっておりませんので
ご使用にあたっては、自己責任でお願いしますm(_ _)m
ある意味、介護系の装置が高価なわけですね~

0 件のコメント: