kopanitsa / biofeedback

MIT License
1 stars 0 forks source link

サンプルコードを理解する #3

Closed kopanitsa closed 10 years ago

kopanitsa commented 10 years ago

heartrate_feedback.ino

setup(), loop()は特に難しいことはやっていない。

interrupt.ino

ISR(TIMER2_COMPA_vect)メソッド

 // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
 OCR2A = 0X7C;      

センサの値を読み取る。

  // 割り込みできないようにする
  cli();                                      
  // read the Pulse Sensor 
  Signal = analogRead(pulsePin);              

  // keep track of the time in mS with this variable
  sampleCounter += 2;                         
  // monitor the time since the last beat to avoid noise
  int N = sampleCounter - lastBeatTime;       

Thresholdと比較し、troughとpeakに値を入れる

  //  find the peak and trough of the pulse wave
  // avoid dichrotic noise by waiting 3/5 of last IBI
  if(Signal < thresh && N > (IBI/5)*3){       
    // Tは谷。谷のthresholdよりも小さい場合は、Tに値を入れる。
    if (Signal < T){                      
      T = Signal;
    }
  }

  // Pはpeak。peakのthresholdよりも大きいい場合は、Pに値を入れる。
  if(Signal > thresh && Signal > P){
    P = Signal;                          
  }    

Thresholdを超えていたら(beatが発生したら)、 値を保持し、time intervalとbeat rateを計算する。

  if (N > 250){ // 250msec後にこのブロックに入る。
    // thresholdを超えていたら
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
        // ....
    }                       
  }
      Pulse = true;                               // set the Pulse flag when we think there is a pulse
      digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
      IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
      lastBeatTime = sampleCounter;               // keep track of time for next pulse

1回目と2回目のbeatのみ、特別扱いする。 1回目は割り込み可能フラグを立てる。 2回目はrateを初期化する。

      if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
        secondBeat = false;                  // clear secondBeat flag
        for(int i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
          rate[i] = IBI;                      
        }
      }

      if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
        firstBeat = false;                   // clear firstBeat flag
        secondBeat = true;                   // set the second beat flag
        sei();                               // enable interrupts again
        return;                              // IBI value is unreliable so discard it
      }   

要素10の配列を持っており、それを1つずつずらして、最後の値rate[9]に 最新のIBI (time interval)を入れる。 10個のIBIからBPM (beat per minute)を更新する。

      // keep a running total of the last 10 IBI values
      word runningTotal = 0;                  // clear the runningTotal variable    

      for(int i=0; i<=8; i++){                // shift data in the rate array
        rate[i] = rate[i+1];                  // and drop the oldest IBI value 
        runningTotal += rate[i];              // add up the 9 oldest IBI values
      }

      rate[9] = IBI;                          // add the latest IBI to the rate array
      runningTotal += rate[9];                // add the latest IBI to runningTotal
      runningTotal /= 10;                     // average the last 10 IBI values 
      BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
      QS = true;                              // set Quantified Self flag 
      // QS FLAG IS NOT CLEARED INSIDE THIS ISR
  // spikeが終わったあとでthresholdの調整を行う。
  if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
    digitalWrite(blinkPin,LOW);            // turn off pin 13 LED
    Pulse = false;                         // reset the Pulse flag so we can do it again
    // peak引くtrough
    amp = P - T;                           // get amplitude of the pulse wave
    thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
    P = thresh;                            // reset these for next time
    T = thresh;
  }

  // 2500msec間beatが発生しなかったらデフォルト値に戻す。
  if (N > 2500){                           // if 2.5 seconds go by without a beat
    thresh = 512;                          // set thresh default
    P = 512;                               // set P default
    T = 512;                               // set T default
    lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
    firstBeat = true;                      // set these to avoid noise
    secondBeat = false;                    // when we get the heartbeat back
  }

参考

Arduinoで遊ぶページ http://garretlab.web.fc2.com/arduino/inside/index.html

kopanitsa commented 10 years ago

まとめ