感圧センサーを押すと、LINE Notifyに通知を出す方法のまとめ

# 感圧センサーを使いこなす

今回、感圧センサーを押すと、LINE Notifyに通知を出すことに挑戦しました。
動作は以下の通りです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LINE Notifyとも連携。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E3%83%98%E3%83%AB%E3%82%B9%E5%AD%A6%E4%BC%9A?src=hash&amp;ref_src=twsrc%5Etfw">#デジタルヘルス学会</a> <a href="https://twitter.com/hashtag/deployorlose?src=hash&amp;ref_src=twsrc%5Etfw">#deployorlose</a> <a href="https://t.co/VgQDacZG9x">pic.twitter.com/VgQDacZG9x</a></p>&mdash; 北城雅照|プログラミングにはまったサーフィン好きの整形外科医 (@teru3_kitashiro) <a href="https://twitter.com/teru3_kitashiro/status/1345545604768829441?ref_src=twsrc%5Etfw">January 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

今後作っていきたい[プロサーファーの世界を体験できるVRデバイス](https://note.com/teru_3/n/n16e88d4327d2)の肝となる部分の1つに感圧センサーがあり、今回その部分について学ぶべく、作成してみました。

感圧センサーに関しては下記の記事を参考にしました。
[obnizでぬいぐるみとの握手をトリガーに](https://qiita.com/SAKUA/items/4c7a7c4166fcb71df196)

LINE Notifyとの連携は、僕の下記の記事を参考にしてください。
[近すぎると小池都知事が『密です。』と連呼するデバイスを作ったら腹筋が崩壊したので、皆さんにも試して欲しい。](https://qiita.com/Teru_3/items/4570bd76d8feeaa37db4)

# デバイス作り
## 今回用意したもの
1) ブレッドボード
2) Obniz
3) [圧力センサーＦＳＲ４０６](https://akizukidenshi.com/catalog/g/gP-04158/)
4) ジャンパワイヤ x2

# 作成したコード
コードのポイントは以下の通りです。
①　２００ms（つまり0.2秒）ごとに感圧センサーの値を調べるループを回す
②　前回ループとの値の差＝変化量を保存(値が小さいので勝手に *10 してます)
③　前回ループまでの過去5ループ(つまり1秒分)の変化量の平均値＝平均変化量を出す
④　過去１秒の平均変化量と今回の変化量を比較して、閾値（今回は５N）を超えたらアクション発動
(アクション発動中8ループは検知しない)

```javascript:pressure_LINE_Notify.js
'use strcit';

const axios = require('axios'); // axiosの呼び出しを追加
const qs = require('querystring'); // 送信するデータの整形
const Obniz = require('obniz');
const obniz = new Obniz('Obniz_ID'); // Obniz_IDに自分のIDを入れます
const LINE_TOKEN = 'LINE notifyのアクセストークンを入力'; // 先程取得したアクセストークンを入れます
const PRESSED_THOREHOLD = 5.0;

let pressVals = [];
let passCount = 5;
let passFlag = false;

obniz.onconnect = async () => {
    obniz.display.clear();
    obniz.display.print('Hello obniz!');

    let pressure = obniz.wired("FSR40X", {pin0:9, pin1:10});
    let rawPress = 0;
    let changeDiffAbs = 0;

    const config = {
        url: 'https://notify-api.line.me/api/notify',
        method: 'post',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Authorization': `Bearer ${LINE_TOKEN}`
        },
        data: qs.stringify({
          message: `Take off!!!`,
        })
    };

    obniz.repeat(async () => {
        rawPress = await pressure.getWait();
        changeDiffAbs  = await calChangeDiffAbs(pressVals, rawPress);

        if(passFlag){
            await passCount--;
            if(passCount <= 0){
                passCount = 5;
                passFlag = false;
            }
            obniz.display.clear();
            obniz.display.print("Let's paddling.");
            return;
        }
        if(changeDiffAbs < PRESSED_THOREHOLD || Number.isNaN(changeDiffAbs)){
            obniz.display.clear();
            obniz.display.print("Let's paddling.");
            return;
        }
        //await ここでアクションを起こす関数を発動！！！！！！
        obniz.display.clear();
        obniz.display.print('Take off!!');
        try {
            // configの設定を元に送信
            const response = await axios.request(config);
            // データ送信が成功するとレスポンスが来る
            console.log('レスポンスを受信しました：' + response.data);
            console.log('POSTに成功しました！');
            //await obniz.wait(10000);
          } catch (error) {
            // ネットワークに接続できてない、サーバーが落ちてる、URLが違うなど様々なエラー
            console.log('POSTに失敗しました……');
            console.error(error);
          }

        passFlag = true;    
    }, 200);
}

async function arrangeArray(arr, val){
    const ARR_LIMIT_NUM = 5;
    await arr.push(val);
    if(arr.length > ARR_LIMIT_NUM){
        await arr.shift();
    }
}

async function calPrevChangeAve(arr){
    let prevChanges = [];

    for(let i=0; i<arr.length-1; i++){
        await prevChanges.push((arr[i+1]-arr[i])/100 * 10);
    }
    let denoNum = prevChanges.length;
    let total = await prevChanges.reduce((sum, data) => {return sum + data}, 0);

    return total / denoNum;
}

async function calChangeDiffAbs(arr, val){
    let prevVal = arr[arr.length-1];
    let currentChange = (prevVal - val)/100 * 10;
    let prevChangeAve = await calPrevChangeAve(arr);
    let diff = await Math.abs(prevChangeAve - currentChange);
    await arrangeArray(arr, val);

    return diff;
}

```