obnizでぬいぐるみとの握手をトリガーに🦉


やったこと

obnizのアドベントカレンダーに何書こうかと考えていたところ、このフクロウくんが視界に入ったので、ぬいぐるみとの握手で何かアクションを起こしたら面白いんじゃないかなぁ〜ってことで色々やってみました。

材料

  • obniz
  • バッテリ
  • 圧力センサ

obnizにそのまま圧力センサをさして握手を検知しています。めちゃ簡単。

こんな感じにして、フクロウくんのお腹と手に埋め込みました。
(写真汚くてごめんなさい...)

配線したものたち お腹の中身

🦉と握手するたびツイートする

IFTTTを使って握手をしたらWebhookを叩き、ツイートをするようにしてみました。

握手すると... ツイート!!

🦉との握手で来客をLINE通知

来客にインターホンの代わりに握手してもらうことで、LINEに通知を送るようにしました。LINE NotifyのAPIを叩いています。

訪ねて来た人が握手すると... LINEで通知🔔

家のWiFiがギリギリ届く範囲内だったのでできたのですが、常設するには厳しいかもしれません😢

🦉と握手でライトのON/OFFを切り替える

握手をすることでUSBライトのON/OFFを切り替えるようにしました。スイッチの部分が常に押し込まれるようテープで留めて、USBアクセサリへの電流の供給のあり/なしだけで切り替えられるようにしています。
個人的にobnizのパーツライブラリにUSBアクセサリが入っているのはとても便利だと思うのですが、意外とみなさん使われていないので取り入れてみました。

だいたい共通のコード

基本的にNode.jsで以下のようなコードをかいて、「ここでアクションを起こす関数を発動!!」のところでそれぞれのアクションに適応させています。頭悪いコードですみません。

中身をざっと説明すると、

  1. 100msごとに圧力センサの値を読むループを回している
  2. 前回ループとの値の変化量を保存(値が小さいので勝手に *10 してます)
  3. 前回ループまでの過去20ループの変化量の平均値を出す
  4. 過去の変化量の平均値と今回の変化量を比較して、閾値を超えたらアクション発動
  5. (アクション発動中8ループは検知しない)

という感じになっています。急に値が変化した時 = 握手 というイメージです。


const fs = require('fs'),
            request = require('request'),
            Obniz = require('obniz');
const PRESSED_THOREHOLD = 1.0;

let obniz = new Obniz('OBNIZ_ID_HERE');
let pressVals = [];
let passCount = 8;
let passFlag = false;

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

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

        if(passFlag){
            await passCount--;
            if(passCount <= 0){
                passCount = 8;
                passFlag = false;
            }
            return;
        }
        if(changeDiffAbs < PRESSED_THOREHOLD || Number.isNaN(changeDiffAbs)){
            return;
        }

        //await ここでアクションを起こす関数を発動!!!!!!
        passFlag = true;    
    }, 100);
}

async function arrangeArray(arr, val){
    const ARR_LIMIT_NUM = 20;
    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;
}

おわりに

今更ながら作ってて改めて感じたのですが、obnizはボード本体にコードを書き込まないので、今回みたいにハード側をぬいぐるみに埋め込んでしまっても、コードを更新するだけでソフト側で簡単にアクションを変更できて楽ですね。