みかづきブログ・カスタム

基本的にはちょちょいのほいです。

M5StickCを振り始めた時、振り終わった時にコールバックイベントを設定する 🔨

最近加速度センサの値に応じた音を再生する仕組みを作り続けてます。


加速度が「しきい値を超えた際のイベントをキャッチ」するのであれば、MESHをつかって、さささっと作ってしまうのですが、


このように「しきい値を超え続けている際に、しきい値を下回るまで音を流す」という処理を書きたい場合は、M5StickC(obniz)をつかっています。
おそらく、MESHでもできないことはないと思うんですが、工夫するよりも愚直にプログラムを書いた方が早いという判断です。



以前、M5StickCに内蔵された加速度センサへのアクセス方法は記事にまとめましたが、今回は、「振り始めた時」と「振り終わった時」にコールバックを実行するプログラムを作ってみます。

blog.kimizuka.org


JavaScript

const Obniz = require('obniz');
const m5 = new Obniz.M5StickC('XXXXXXXX'); // ObnizIDに差し替える

const CACHE_LENGTH = 8; // 平均値に採用する加速度の数(8なら過去8回分の計測値の平均値を取る)
const START_ACCELERATION = 2; // しきい値
const INTERVAL = 200; // 加速度をチェックする間隔

// 加速度収納用の配列
const qax = [];
const qay = [];
const qaz = [];

let moveFlag = false;
let i = 0;

m5.onconnect = async () => {
  await m5.setupIMUWait();

  setInterval(async () => {
    const acc = await m5.accelerationWait();

    handleDeviceMotion(
      acc,
      () => { // 振り始めのコールバック
        console.log('start!');
      },
      () => { // 振り終わりのコールバック
        console.log('end!');
      });
  }, INTERVAL);
};

function handleDeviceMotion(acc, moveCallback = () => {}, stopCallback = () => {}) {
  qax[i] = acc.x;
  qay[i] = acc.y;
  qaz[i] = acc.z;

  if (qax.length > CACHE_LENGTH - 1) {
    if (ave(qax) + ave(qay) + ave(qaz) > START_ACCELERATION) {
      if (!moveFlag) {
        moveFlag = true;
        moveCallback();
      }
    } else {
      if (moveFlag) {
        moveFlag = false;
        stopCallback();
      }
    }
  }

  i = ++i % CACHE_LENGTH;
  
  function ave(arr) {
    let length = arr.length;
    let i = length;
    let sum = 0;

    while (i--) {
      sum += Math.abs(arr[i]);
    }

    return sum / length;
  }
}

ぱぱぱっと書いたコードなので雑ですが、撮影には耐えうるコードになったかなと思います。