Averaging data

Hello.

Currently, I am trying to average the values of a variable over time. I am exporting the data from the Arduino to Processing. The specific variable I am trying to average over time is PTT. Is this possible? Here's my code so far in Arduino:

//Arduino
#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>
#include <math.h>

const int OUTPUT_TYPE = PROCESSING_VISUALIZER;

const int PULSE_SENSOR_COUNT = 2;


const int PULSE_INPUT0 = A0;
const int PULSE_BLINK0 = 13;
const int PULSE_FADE0 = 5;

const int PULSE_INPUT1 = A1;
const int PULSE_BLINK1 = 12;
const int PULSE_FADE1 = 11;

const int THRESHOLD = 550;


PulseSensorPlayground pulseSensor(PULSE_SENSOR_COUNT);


unsigned long lastBeatSampleNumber[PULSE_SENSOR_COUNT];
int PTT;


void setup() {

  Serial.begin(250000);

  pulseSensor.analogInput(PULSE_INPUT0, 0);
  pulseSensor.blinkOnPulse(PULSE_BLINK0, 0);
  pulseSensor.fadeOnPulse(PULSE_FADE0, 0);

  pulseSensor.analogInput(PULSE_INPUT1, 1);
  pulseSensor.blinkOnPulse(PULSE_BLINK1, 1);
  pulseSensor.fadeOnPulse(PULSE_FADE1, 1);

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



  if (!pulseSensor.begin()) {
 
    for (;;) {
      digitalWrite(PULSE_BLINK0, LOW);
      delay(50);
      digitalWrite(PULSE_BLINK0, HIGH);
      delay(50);
    }
  }
}

void loop() {
  delay(20);

  pulseSensor.outputSample();

  for (int i = 0; i < PULSE_SENSOR_COUNT; ++i) {
    if (pulseSensor.sawStartOfBeat(i)) {
      pulseSensor.outputBeat(i);

      lastBeatSampleNumber[i] = pulseSensor.getLastBeatTime(i);
      if(i == 1){
        PTT = lastBeatSampleNumber[1] - lastBeatSampleNumber[0]; 
        pulseSensor.outputToSerial('|',PTT);
      }
    }
  }

}

Thanks in advance.

Processing code:

//Processing
import processing.serial.*;
PFont font;

Serial port;
int numSensors = 2;

int[] Sensor;      // HOLDS PULSE SENSOR DATA FROM ARDUINO
int[] IBI;         // HOLDS TIME BETWEN HEARTBEATS FROM ARDUINO
int[] BPM;         // HOLDS HEART RATE VALUE FROM ARDUINO
int[][] RawPPG;      // HOLDS HEARTBEAT WAVEFORM DATA BEFORE SCALING
int[][] ScaledPPG;   // USED TO POSITION SCALED HEARTBEAT WAVEFORM
int[][] ScaledBPM;      // USED TO POSITION BPM DATA WAVEFORM
float offset;    // USED WHEN SCALING PULSE WAVEFORM TO PULSE WINDOW
color eggshell = color(255, 253, 248);
int heart[];   // USED TO TIME THE HEART 'PULSE'

float PTT;

int PulseWindowWidth; // = 490;
int PulseWindowHeight; // = 512;
int PulseWindowX;
int PulseWindowY[];
int BPMWindowWidth; // = 180;
int BPMWindowHeight; // = 340;
int BPMWindowX;
int BPMWindowY[];
int spacer = 10;
boolean beat[];    // set when a heart beat is detected, then cleared when the BPM graph is advanced

// SERIAL PORT STUFF TO HELP YOU FIND THE CORRECT SERIAL PORT
String serialPort;
String[] serialPorts = new String[Serial.list().length];
boolean serialPortFound = false;
Radio[] button = new Radio[Serial.list().length*2];
int numPorts = serialPorts.length;
boolean refreshPorts = false;

void setup() {
  size(900, 725);  // Stage size
  frameRate(100);
  font = loadFont("Arial-BoldMT-24.vlw");
  textFont(font);
  textAlign(CENTER);
  rectMode(CORNER);
  ellipseMode(CENTER);
  // Display Window Setup
  PulseWindowWidth = 490;
  PulseWindowHeight = 640/numSensors;
  PulseWindowX = 10;
  PulseWindowY = new int [numSensors];
  for(int i=0; i<numSensors; i++){
    PulseWindowY[i] = 43 + (PulseWindowHeight * i);
    if(i > 0) PulseWindowY[i]+=spacer*i;
  }
  BPMWindowWidth = 180;
  BPMWindowHeight = PulseWindowHeight;
  BPMWindowX = PulseWindowX + PulseWindowWidth + 10;
  BPMWindowY = new int [numSensors];
  for(int i=0; i<numSensors; i++){
    BPMWindowY[i] = 43 + (BPMWindowHeight * i);
    if(i > 0) BPMWindowY[i]+=spacer*i;
  }
  heart = new int[numSensors];
  beat = new boolean[numSensors];
  // Data Variables Setup
  Sensor = new int[numSensors];      // HOLDS PULSE SENSOR DATA FROM ARDUINO
  IBI = new int[numSensors];         // HOLDS TIME BETWEN HEARTBEATS FROM ARDUINO
  BPM = new int[numSensors];         // HOLDS HEART RATE VALUE FROM ARDUINO
  RawPPG = new int[numSensors][PulseWindowWidth];
  ScaledPPG = new int[numSensors][PulseWindowWidth];
  ScaledBPM = new int [numSensors][BPMWindowWidth];

  // set the visualizer lines to 0
  resetDataTraces();

 background(0);
 noStroke();
 drawDataWindows();
 drawHeart();

  fill(eggshell);
  text("Select Your Serial Port",245,30);
  listAvailablePorts();
}

void draw() {
if(serialPortFound){
  background(0);
  drawDataWindows();
  drawPulseWaveform();
  drawBPMwaveform();
  drawHeart();
  printDataToScreen();

} else {
  autoScanPorts();

  if(refreshPorts){
    refreshPorts = false;
    drawDataWindows();
    drawHeart();
    listAvailablePorts();
  }

  for(int i=0; i<numPorts+1; i++){
    button[i].overRadio(mouseX,mouseY);
    button[i].displayRadio();
  }

}

}


void drawDataWindows(){
  noStroke();
  fill(eggshell);
  for(int i=0; i<numSensors; i++){
    rect(PulseWindowX, PulseWindowY[i], PulseWindowWidth, PulseWindowHeight);
    rect(BPMWindowX, BPMWindowY[i], BPMWindowWidth, BPMWindowHeight);
  }
}

void drawPulseWaveform(){
  for (int i=0; i<numSensors; i++) {
    RawPPG[i][PulseWindowWidth-1] = (1023 - Sensor[i]);

    for (int j = 0; j < PulseWindowWidth-1; j++) {
      RawPPG[i][j] = RawPPG[i][j+1];
      float dummy = RawPPG[i][j] * 0.625/numSensors;
      offset = float(PulseWindowY[i]);
      ScaledPPG[i][j] = int(dummy) + int(offset);
    }
    stroke(250, 0, 0);
    noFill();
    beginShape();
    for (int x = 1; x < PulseWindowWidth-1; x++) {
      vertex(x+10, ScaledPPG[i][x]);
    }
    endShape();
  }

}

void drawBPMwaveform(){
for (int i=0; i<numSensors; i++) {
if (beat[i] == true) {
  beat[i] = false;

    for (int j=0; j<BPMWindowWidth-1; j++) {
      ScaledBPM[i][j] = ScaledBPM[i][j+1];
    }
    // then limit and scale the BPM value
    BPM[i] = constrain(BPM[i], 0, 200);
    float dummy = map(BPM[i], 0, 200, BPMWindowY[i]+BPMWindowHeight, BPMWindowY[i]);
    ScaledBPM[i][BPMWindowWidth-1] = int(dummy);
  }
}
// GRAPH THE HEART RATE WAVEFORM
stroke(250, 0, 0);
strokeWeight(2);
noFill();

for (int i=0; i<numSensors; i++) {
  beginShape();
  for (int j=0; j < BPMWindowWidth; j++) {
    vertex(j+BPMWindowX, ScaledBPM[i][j]);
  }
  endShape();
}
}
void drawHeart(){
  // DRAW THE HEART AND MAYBE MAKE IT BEAT
    fill(250,0,0);
    stroke(250,0,0);
  int bezierZero = 0;
  for(int i=0; i<numSensors; i++){
    heart[i]--;                    
    heart[i] = max(heart[i], 0);       
    if (heart[i] > 0) {             
      strokeWeight(8);          
    }
    smooth();
    bezier(width-100, bezierZero+70, width-20, bezierZero, width, bezierZero+160, width-100, bezierZero+170);
    bezier(width-100, bezierZero+70, width-190, bezierZero, width-200, bezierZero+160, width-100, bezierZero+170);
    strokeWeight(1);
    bezierZero += BPMWindowHeight+spacer;
  }
}



void listAvailablePorts(){
  println(Serial.list());
  serialPorts = Serial.list();
  fill(0);
  textFont(font,16);
  textAlign(LEFT);
  // set a counter to list the ports backwards
  int yPos = 0;

  for(int i=numPorts-1; i>=0; i--){
    button[i] = new Radio(35, 95+(yPos*20),12,color(180),color(80),color(255),i,button);
    text(serialPorts[i],50, 100+(yPos*20));
    yPos++;
  }
  int p = numPorts;
   fill(233,0,0);
  button[p] = new Radio(35, 95+(yPos*20),12,color(180),color(80),color(255),p,button);
    text("Refresh Serial Ports List",50, 100+(yPos*20));

  textFont(font);
  textAlign(CENTER);
}

void autoScanPorts(){
  if(Serial.list().length != numPorts){
    if(Serial.list().length > numPorts){
      println("New Ports Opened!");
      int diff = Serial.list().length - numPorts;
      serialPorts = expand(serialPorts,diff);
      numPorts = Serial.list().length;
    }else if(Serial.list().length < numPorts){
      println("Some Ports Closed!");
      numPorts = Serial.list().length;
    }
    refreshPorts = true;
    return;
}
}

void resetDataTraces(){
  for (int i=0; i<numSensors; i++) {
    BPM[i] = 0;
    for(int j=0; j<BPMWindowWidth; j++){
      ScaledBPM[i][j] = BPMWindowY[i] + BPMWindowHeight;
    }
  }
  for (int i=0; i<numSensors; i++) {
    Sensor[i] = 512;
    for (int j=0; j<PulseWindowWidth; j++) {
      RawPPG[i][j] = 1024 - Sensor[i];
    }
  }
}

void printDataToScreen(){
    fill(eggshell);                                       
    text("Blood Pressure Monitor", 300, 30);     
    for (int i=0; i<numSensors; i++) {
      text("Sensor # " + (i+1), 800, BPMWindowY[i] + 220);
      text(BPM[i] + " BPM", 800, BPMWindowY[i] +185);// 215          
      text("IBI " + IBI[i] + "ms", 800, BPMWindowY[i] + 160);// 245   
    }
    text("PTT: " + PTT + "ms", 800, BPMWindowY[1] - 50);
}

What is PTT?

Any series of single measurement can be averaged. You could, for example, add up 10 values, divide by 10 and output the result.

Another option is a moving or running average, where you keep the last N values and average them. Each time a new measurement comes in, replace the oldest measurement, calculate and output the new average.