SSブログ

ESP-WROOM-02で心拍センサーを動かしてみた [Arduino]

ESP-WROOM-02で心拍センサーを動かしてみました。


DSC04081.JPG


ESP-WROOM-02のADCは0Vから1Vの範囲しか測定できないので、3.3Vの心拍センサーの出力をだいたい1/3に分圧して入力しています。


ESP-WROOM-0220with20PulseSensor.png


スケッチを設計するポイントは、

・ シグナル値の読み込みに analobRead() 関数ではなく sysytem_adc_read() 関数を使用
・ 割り込みの設定に、timer0_isr_init()、timer0_attachInterrupt()、timer0_write() 関数を使用
・ 時間取得に、ESP.getCycleCount() 関数を使用

の3点です。


extern "C" {
  #include "user_interface.h"
}

#define N 10

volatile int BPM;
volatile int Signal;
volatile int IBI = 600;
volatile boolean Pulse = false;
volatile boolean QS = false;

volatile int Rate[N];
volatile unsigned long CurrBeatTime = 0;
volatile unsigned long LastBeatTime = 0;
volatile int P = 500;
volatile int T = 500;
volatile int Threshold = 512;
volatile int Amplifier = 100;

int PulseSensorPin = 17;
int FadePin = 4;
int FadeRate = 0;

void timer0_ISR (void) {
  noInterrupts();
  Signal = system_adc_read();
  CurrBeatTime = getCurrentTime(); // msec
  unsigned long interval = CurrBeatTime - LastBeatTime;
  
  // hold bottom
  if ((Signal < Threshold) && (interval > (IBI*3) / 5)) {
    if (Signal < T) {
      T = Signal;
    }
  }
   
  // hold peak
  if (Signal > Threshold && Signal > P) {
    P = Signal;
  }
  
  if (interval > 250 /* ms */) {
    
    // check if Signal is over Threshold
    if ((Signal > Threshold) && !Pulse && (interval > (IBI*3) / 5)) {
      Pulse = true;
      IBI = interval;
      
      if (Rate[0] < 0) { // first time
        Rate[0] = 0;
        LastBeatTime = getCurrentTime();
        setupTimer(10);
        noInterrupts();
        return;
      } else if (Rate[0] == 0) {  // second time
        for (int i = 0; i < N; ++i) {
          Rate[i] = IBI;
        }
      }
      
      word running_total = 0;     
      for (int i = 0; i < N-1; ++i) {
        Rate[i] = Rate[i+1];
        running_total += Rate[i];
      }
      
      Rate[N-1] = IBI;
      running_total += IBI;
      running_total /= N;
      BPM = 60000 / running_total;
      QS = true;
      LastBeatTime = getCurrentTime();
    }
  }
  
  // check if Signal is under Threshold
  if ((Signal < Threshold) && Pulse) {
    Pulse = false;
    Amplifier = P - T;
    Threshold = Amplifier / 2 + T; // revise Threshold
    P = Threshold;
    T = Threshold;
  }
  
  // check if no Signal is over 2.5 sec
  if (interval > 2500 /* ms */) {
    Threshold = 512;
    P = 500;
    T = 500;
    LastBeatTime = getCurrentTime();
    for (int i = 0; i < N; ++i) {
      Rate[i] = -1;
    }
  }
  setupTimer(10);
  interrupts();
}

void setupTimer(int m /* msec */) {
  timer0_isr_init();
  timer0_attachInterrupt(timer0_ISR);
  timer0_write(ESP.getCycleCount() + 80000L * m); // 80MHz/1000 == 1msec
}

unsigned long getCurrentTime() {
  return ESP.getCycleCount() / 80000L;
}

void setup() {
  pinMode(FadePin, OUTPUT);
  analogWriteRange(255);
  Serial.begin(115200); 
  noInterrupts();
  setupTimer(10);
  interrupts();
  LastBeatTime = getCurrentTime(); // msec
}

void loop() {
  if (QS) {
    FadeRate = 255; 
    Serial.print("BPM: ");
    Serial.println(BPM);
    QS = false;
  }
  
  FadeRate -= 15;
  FadeRate = constrain(FadeRate, 0, 255);
  analogWrite(FadePin, FadeRate);
  delay(20);
}


さて、きちんと動くかなー?



システムから時間をとっているせいか、Arduno Pro Mini で使ったアルゴリズムよりも精度よく測定しているような気がします。次はいよいよバッテリー駆動にチャレンジかなぁ。
σ(^_^)





ESP-WROOM-02ピッチ変換済みモジュール《フル版》

ESP-WROOM-02ピッチ変換済みモジュール《フル版》

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



心拍センサ

心拍センサ

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス







nice!(34)  コメント(0)  トラックバック(0) 
共通テーマ:趣味・カルチャー

nice! 34

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。