M5Stackでおみくじを作ってみた

はじめに

年のはじめの運試しとして毎年神社でおみくじを引いています。

そんなおみくじをM5Stackで実現したので本記事にて紹介します。

完成品

動画の通り、1回目は吉、2回目は中吉という結果が得られました。好きなだけおみくじが引けて良いですね。

開発環境

準備物

  • M5Stack Gray

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

原理

表示する画面分の画像を用意して、ボタン操作に応じて画像を切り替えております。
M5Stackの画面サイズは320×240ですので、ペイントにて画面サイズを指定後、必要となる画像を作成しました。
f:id:kuracux:20190219104611p:plain:w200

今回は、以下の7枚の画像を使用しております。
(フォルダ構成およびファイル名は下記のスケッチ例をもとに命名してください)


f:id:kuracux:20190219105357j:plain
f:id:kuracux:20190219105401j:plain
f:id:kuracux:20190219105409j:plain


f:id:kuracux:20190219105413j:plain
f:id:kuracux:20190219105420j:plain
f:id:kuracux:20190219112448j:plain
f:id:kuracux:20190219112653j:plain

スケッチ例

初期値をランダムで設定し、振ることでその値が変わり、表示される画像も変わります。
振った際の処理についてはこちらの記事をご覧ください。
kuracux.hatenablog.jp

#include <M5Stack.h>
#include "utility/MPU9250.h"
MPU9250 IMU;

bool leftFlag = false; //左に動いたことを保持するフラグ
bool rightFlag = false; //右に動いたことを保持するフラグ

bool omikujiFlag = false;

int th = 80;
int count;

void setup(){
  Serial.begin(115200);
  M5.begin();
  Wire.begin();
  M5.Lcd.setBrightness(50);
  M5.Lcd.drawJpgFile(SD, "/pictures/home.jpg");
  byte c = IMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
  IMU.calibrateMPU9250(IMU.gyroBias, IMU.accelBias);
  randomSeed(analogRead(0));
}

void loop(){
  if(M5.BtnA.wasPressed()){
    omikujiFlag = true;
    count = random(0,5);
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.drawJpgFile(SD, "/pictures/omikuji.jpg");
  }else if(M5.BtnB.wasPressed()){
    if(omikujiFlag){
      resultOmikuji();
      omikujiFlag = false;
    }
  }else if(M5.BtnC.wasPressed()){
    omikujiFlag = false;
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.drawJpgFile(SD, "/pictures/home.jpg");
  }

  if(omikujiFlag){
    shake();  
  }
  M5.update();
}

void resultOmikuji(){
  M5.Lcd.fillScreen(BLACK);
  String s = "/pictures/"+String(count)+".jpg";
  M5.Lcd.drawJpgFile(SD, s.c_str());
}

void shake(){
  if (IMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01){  
    IMU.readGyroData(IMU.gyroCount);  // Read the x/y/z adc values
    IMU.getGres();
    IMU.gz = (float)IMU.gyroCount[2]*IMU.gRes;
  } 
  IMU.delt_t = millis() - IMU.count;
  if (IMU.delt_t > 100){
    int accel = (int)(IMU.gz);
    if(accel < -th){
      if(leftFlag){
        //左に振る→右に振るの後の処理
         count = (count + 1) % 5;
      }else{
        rightFlag = true;
      }
    }else if(accel > th){
      if(rightFlag){
        //右に振る→左に振るの後の処理
        count = (count + 1) % 5;
      }else{
        leftFlag = true;
      }
    }else{
      leftFlag = false;
      rightFlag = false;
    }
    IMU.count = millis();
  } 
}

所感

  • おみくじを振ってる感があまりない

理由の1つとしては振った時のジャラジャラ音がないことが考えられます。よりリアリティを求めるのであれば、実際の体験に近づける工夫をしようと思いました。

  • 振った際に値が変わる処理はなくても良い

おみくじ開始時にランダムで値が決まり、なおかつユーザがその値を知らないのであれば、振る動作によって値が変わる処理を入れてもあまり意味はありません。
確かに振った際の動作で結果が変わるという処理は「おみくじらしさ」があるかもしれませんが、あくまでそれは開発者側の視点であって、ユーザの視点で考えると不要だと感じました。

おわりに

今回はM5Stackでおみくじを作りました。

個人的には、このおみくじではまだまだM5Stackを活かしきれていないなと感じておりますので、その辺りも考えた上で作り上げていければいいなと思います。