質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.13%

M5StackとPulseSensorを使って、力の入れ具合を可視化したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 396

実現したいこと

PulseSensorのライブラリを用いて、M5Stackで力の入れ具合をグラフで可視化する。
開発環境は、ArduinoIDEです。

発生している問題

loop文が実行されずに、以下のメッセージがM5Stackに表示されます。
PulseSensor.begin: failed

該当のソースコード

#ifdef ARDUINO_M5Stack_Core_ESP32
#include <M5Stack.h>
#endif

#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>


const int OUTPUT_TYPE = SERIAL_PLOTTER;

const int BEEP = 22; //ブザーにつながるピン

const int PIN_INPUT = 36; //センサ値検出(アナログ入力)
const int THRESHOLD = 550;   // Adjust this number to avoid noise when idle

PulseSensorPlayground pulseSensor;

void setup() {
#ifdef ARDUINO_M5Stack_Core_ESP32
    M5.begin();
    dacWrite(25, 0); // Speaker OFF
    pinMode(BEEP, OUTPUT); //ブザー設定
#endif

    pulseSensor.analogInput(PIN_INPUT);
    pulseSensor.setSerial(Serial);
    pulseSensor.setOutputType(OUTPUT_TYPE);
    pulseSensor.setThreshold(THRESHOLD);

    if (!pulseSensor.begin()) {
        M5.Lcd.println("PulseSensor.begin: failed");
        for(;;) {
            delay(0);
        }
    }
}

const int LCD_WIDTH = 320;
const int LCD_HEIGHT = 240;
const int DOTS_DIV = 30;
#define GREY 0x7BEF

void DrawGrid() {
    for (int x = 0; x <= LCD_WIDTH; x += 2) { // Horizontal Line
        for (int y = 0; y <= LCD_HEIGHT; y += DOTS_DIV) {
            M5.Lcd.drawPixel(x, y, GREY);
        }
        if (LCD_HEIGHT == 240) {
            M5.Lcd.drawPixel(x, LCD_HEIGHT - 1, GREY);
        }
    }
    for (int x = 0; x <= LCD_WIDTH; x += DOTS_DIV) { // Vertical Line
        for (int y = 0; y <= LCD_HEIGHT; y += 2) {
            M5.Lcd.drawPixel(x, y, GREY);
        }
    }
}

#define REDRAW 20 // msec

short lastMin = 0, lastMax = 4096;
short minS = 4096, maxS = 0;
int lastY = 220;
int x = 0;

int lastlow = 120;//- 20; //BlueLine
int low = 120; //- 20; //Next BlueLine

int lasthigh = 60;//-20; //RedLine
int high = 60;//- 20; //Next RedLine

int flagl = 1;//0; //BlueLineの有無判定
int flagh = 1;//0; //RedLineの有無判定

int mag = 3.5; //倍数
int soundFlag = 60;//-20; //これ以下なら音を出す
int soundFlag2 = 120;//-20; //これ以上なら音を出す 

int changesum = 0; //変化量の合計値
int changecount = 0; //多数決
int downcount = 0; //変化量減少
int upcount = 0; //変化量増加
int updownflag = 0; //減少中か増加中か
int topflag = 0; //頂点
int beforeflag = 0; //前のフラッグ
int testcounter = 0; //test
int max_x = 0;
int Bmax_x = 0;
int min_y = 220;
int Bmin_y = 220;

int Premin_y = 220;
int Premax_x = 0;

int soundcountflag = 0;
int soundcountflag2 = 0;
int soundcount = 0;
int soundcount2 = 0;

int Hzflag = 0;
double far = 0.0;
double hz = 0.0;

int linefirstflag = 0;

void loop() {
// 値の検出
    delay(REDRAW);
    int y = pulseSensor.getLatestSample() * mag; //220(Neutral) ~ 40(MaxPower)

    if(linefirstflag == 0){
       M5.Lcd.fillRect(50, low, 270, 2, BLUE);
       M5.Lcd.fillRect(50, high, 270, 2, RED);
       linefirstflag = 1;
    }

    if (x > 0) {
        y = (int)((LCD_HEIGHT - (float)(y - lastMin) / (lastMax - lastMin) * LCD_HEIGHT) - 20);

        if(x < 140){
           M5.Lcd.fillRect(x, 30, 50, 220, BLACK);
        }else if(140 <= x){
           M5.Lcd.fillRect(x, 0, 50, 240, BLACK);
           if(x > 270){
              M5.Lcd.fillRect(0, 30, x - 270, 220, BLACK);
           }
        }
        if(flagl == 1){
            M5.Lcd.fillRect(x, low, 1, 2, BLUE);
        }
        if(flagh == 1){
            M5.Lcd.fillRect(x, high, 1, 2, RED);
        }

        M5.Lcd.drawLine(x - 1, lastY, x, y, WHITE);

      // ピーク値検出
        if(changecount < 5){                          //5回計測(増加が多いか、減少が多いか)

            if((y - lastY) <= 0){                     //減少している時
                changesum += (y - lastY)*(y - lastY); //変化量の計算
                downcount++;                          //減少+1

                if(y < min_y){                        //最小値記録
                  min_y = y;
                  max_x = x;
                }

            }else if((y - lastY) > 0){                //増加している時
                changesum += (y - lastY)*(y - lastY); //変化量の計算
                upcount++;                            //増加+1

                if(y < min_y){                        //最小値記録
                  min_y = y;
                  max_x = x;
                }

            } 

        }else if(changecount == 5){                   //5回の計測が終わった時
            if(downcount > upcount){                  //減少回数が多ければ
                updownflag = 0;                       //[減少]
           }else if(downcount < upcount){             //増加回数が多ければ
                updownflag = 1;                       //[増加]
            }
            changecount = 0;                          //計測した数を0回に戻す
            downcount = 0;
            upcount = 0;                              


            if((updownflag - beforeflag) == 1 && changesum > 30){ //[減少]->[増加]に移行した時  (changesumの値で、カウントする波形のサイズを変更)
            //ピークの時の処理
              if(Bmin_y < min_y){
                min_y = Bmin_y;
                max_x = Bmax_x;
              }


             // 周期計算
                if(max_x - Premax_x < 0){
                  far = (double)max_x + 320.0 - (double)Premax_x;
                }else if(max_x - Premax_x >= 0){
                  far = (double)max_x - (double)Premax_x;
                }

                if(Hzflag == 1 && (far < 35.0)){
                  hz  = 2400 / far;   //60.0 / (far / 49.5);

                  M5.Lcd.setCursor(0, 0);
                  M5.Lcd.setTextSize(4);
                  M5.Lcd.printf("Hz %3.0lf", hz);

                  Premax_x = max_x;

                }else if(Hzflag == 1 && (far >= 35.0)){

                   Hzflag = 0;
                   Premax_x = 0;
                   hz = 0.0;
                   far = 0.0;

                  M5.Lcd.setCursor(0, 0);
                  M5.Lcd.setTextSize(4);
                  M5.Lcd.printf("Hz ---");
                }

                if(Hzflag == 0){
                  Premax_x = max_x;
                  Hzflag = 1;                 
                }

                testcounter++;//(回数を表示する時)

                if(min_y < soundFlag){
                   digitalWrite(BEEP,HIGH);
                   soundcountflag = 1;
                }

                if(min_y < soundFlag2){
                   digitalWrite(BEEP,HIGH);
                   soundcountflag2 = 1;
                } 

            }//ピーク時の処理の終わり

            changesum = 0;                             //変化量の合計リセット
            beforeflag = updownflag;                   //前の判定が[増加]か[減少]か
            Bmin_y = min_y;
            Bmax_x = max_x;
            min_y = 220;
            max_x = 0;

        }    

    changecount++;
    lastY = y;
    }

// 各ボタンの処理
    if(M5.BtnA.wasPressed()){//左ボタンを押した時
      flagl = 1;
      M5.Lcd.fillRect(0, lastlow,320,2,BLACK);//表示されているブルーのラインを黒で上書きして消す
      low = y;
      M5.Lcd.fillRect(0, low, 320, 2, BLUE);//新たにブルーのライン(最低圧力)を描画する
      lastlow = low;
      soundFlag2 = low;
    }

    if(M5.BtnA.pressedFor(1000)){//左ボタン1秒以上長押し
      flagl = 0;
      M5.Lcd.fillRect(0, lastlow,320,2,BLACK);//表示されているブルーのラインを黒で上書きして消す
      low = -20;
      lastlow = -20;
    }

    if(M5.BtnC.wasPressed()){//右ボタンを押した時
      flagh = 1;
      M5.Lcd.fillRect(0, lasthigh,320,2,BLACK);
      high = y;
      M5.Lcd.fillRect(0, high, 320, 2, RED);
      lasthigh = high;
      soundFlag = high;
    }

    if(M5.BtnC.pressedFor(1000)){//右ボタン1秒以上長押し
      flagh = 0;
      M5.Lcd.fillRect(0, lasthigh,320,2,BLACK);
      high = -20;
      lasthigh= -20;
    }

    if(M5.BtnB.pressedFor(1000)){//真ん中のボタン1秒以上長押し
      flagl = 0;
      flagh = 0;
      M5.Lcd.fillRect(0, lasthigh,320,2,BLACK);
      M5.Lcd.fillRect(0, lastlow, 320, 2,BLACK);
      int lastlow = - 20;
      int low = - 20;
      int lasthigh = - 20;
      int high = - 20;
    }

    if(M5.BtnB.wasPressed()){//中ボタンを押した時
      if(mag <= 7.5){
      mag = mag + 1;
      }else{
        mag = 3.5;
      }

    }

// ブザー処理
///RedLineOver
    if(soundcountflag == 1 && soundcount < 2){
       soundcount++;
    }else if(soundcountflag == 1 && soundcount > 1 && soundcount < 4 ) {
        digitalWrite(BEEP,LOW);
        soundcount++;
    }else if(soundcountflag == 1 && soundcount > 3 && soundcount < 6){
        digitalWrite(BEEP,HIGH);
        soundcount++;
    }else if(soundcountflag == 1 && soundcount == 6){
        digitalWrite(BEEP,LOW);     
        soundcount = 0;
        soundcountflag = 0;
    }

//BlueLineOver
    if(soundcountflag2 == 1 && soundcount2 < 2){
        soundcount2++;
    }else if(soundcountflag2 == 1 && soundcount2 == 2 ) {  
        digitalWrite(BEEP,LOW);  
        soundcount2 = 0;
        soundcountflag2 = 0;
    }

    if (++x > LCD_WIDTH) {
        x = 1;
        M5.Lcd.fillRect(0, 30, 1, 220, BLACK);
        //M5.Lcd.fillRect(x + 1, 0, 20, 240, BLACK);
       // DrawGrid();

        minS = 4096;
        maxS = 0;

        if(flagl == 1){
        M5.Lcd.fillRect(50, low, 320, 2, BLUE);
        }
        if(flagh == 1){
        M5.Lcd.fillRect(50, high, 320, 2, RED);
        }
    }

    M5.update();
}

試したこと

#define USE_ARDUINO_INTERRUPTS true
trueをfalseにしたら、loop文が実行されましたが、int y = pulseSensor.getLatestSample() * mag;で変数yに値が入っていません。
(おそらく、pulseSensor.getLatestSample()で値を取得できていない)

補足情報(FW/ツールのバージョンなど)

Arduino1.8.7

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

解決しました。。。。。。。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/30 20:11

    折角だから、どうやって解決したのか教えてほしいな。

    キャンセル

  • 2019/05/02 10:36

    #define USE_ARDUINO_INTERRUPTS trueのtrueをfalseにして、
    pulseSensor.getLatestSample()をanalogRead()に変えたら出来ました。
    pulseSensor.getLatestSample()で値を取得できていなかったみたいです。

    キャンセル

  • 2019/05/02 10:38

    #define USE_ARDUINO_INTERRUPTS trueのtrueの状態でloop文が実行できたら、pulseSensor.getLatestSample()でも値取得できそうなのですが、、、、

    キャンセル

  • 2019/05/02 13:04

    ESP32での割り込みには対応していなくて PulseSensorPlayground::getLatestSample() では値が取れない、ということのようですね。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる