Created
June 13, 2019 20:30
-
-
Save kasperkamperman/5a52eb345416ed605d39e2746fe2f557 to your computer and use it in GitHub Desktop.
Code in which I read serial data and write it to a CSV file. Used for a research project.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ReadPulseCooking.pde | |
import processing.serial.*; | |
/* | |
http://pulsesensor.myshopify.com/ | |
Uses a modified pulse sensor script in Arduino to update each 10ms | |
A different string is formulated with all the data | |
We use to pulse flag to add data to running average etc. | |
*/ | |
public class ReadPulseCooking //extends PApplet | |
{ | |
PApplet p; | |
Serial port; | |
int heartbeatVisual; | |
long rowId = 0; | |
long timeInMillis = 0; | |
PrintWriter outputCSV; | |
private boolean isLookingAuto = false; | |
private boolean isLookingManual = false; | |
private boolean isLooking = false; | |
private boolean isReadingManual = false; | |
//long timeStamp; | |
// calculations RunningStat | |
private RunningStat bpmStat; | |
private RunningStat bpmLookingStat; | |
private RunningStat bpmNotLookingStat; | |
private int pulseBPM; | |
private float [] [] bpmStatArray; | |
boolean turnPortOff = false; | |
public ReadPulseCooking (PApplet p) { | |
this.p = p; | |
//printArray(Serial.list()); | |
if(!turnPortOff) | |
{ println("open pulse cooking port: "+Serial.list()[2]); | |
port = new Serial(p, Serial.list()[2], 115200); | |
port.clear(); // flush buffer | |
port.bufferUntil(10); // set buffer full flag on receipt of carriage return | |
} | |
// able to record about 40 minutes | |
// 120BPM*40 = 4800 | |
//sampleArraySize = 4800; | |
//sampleArray = new PulseSample[sampleArraySize]; | |
//sampleArrayIndex = 0; | |
// runningstat | |
bpmStat = new RunningStat(); | |
bpmLookingStat = new RunningStat(); | |
bpmNotLookingStat = new RunningStat(); | |
// array: cols - rows (rows: normal/looking/not-looking, cols:mean, std) | |
bpmStatArray = new float[2][3]; | |
} | |
void dispose() | |
{ if(!turnPortOff) | |
{ | |
println("stop ReadPulseCooking serialport"); | |
port.clear(); | |
port.stop(); | |
} | |
} | |
void reinitSerialPort() | |
{ if(!turnPortOff) | |
{ | |
// restarts Arduino, that's the reason | |
port.clear(); | |
port.stop(); | |
port = new Serial(p, Serial.list()[2], 115200); | |
port.clear(); // flush buffer | |
port.bufferUntil(10); // set buffer full flag on receipt of carriage return | |
println("re-opened pulse-amped port: "+Serial.list()[1]); | |
} | |
} | |
public void updateIsLookingAuto(boolean val) | |
{ isLookingAuto = val; | |
if(isLookingAuto || isLookingManual) isLooking = true; | |
else isLooking = false; | |
} | |
public void updateIsLookingManual(boolean val) | |
{ isLookingManual = val; | |
if(isLookingAuto || isLookingManual) isLooking = true; | |
else isLooking = false; | |
} | |
public void updateIsReading(boolean val) | |
{ isReadingManual = val; | |
} | |
//public void serialEvent(Serial s) | |
public void serialEvent() | |
{ | |
String incomingData = port.readStringUntil(10); | |
incomingData = trim(incomingData); | |
String[] values = split(incomingData, ','); | |
//println("incomingData: "+incomingData); | |
//println(values[0]); | |
//println(values[1]); | |
//timeStamp = Long.parseLong(values[0]); | |
pulseBPM = int(values[1]); | |
//println("pulseBPMCook: "+pulseBPM); | |
if(isTimeRunning) | |
{ | |
timeInMillis = getRunTime(); // get the runtime, so that's written // millis(); | |
// update RunningStat | |
if(pulseBPM>0) | |
{ | |
bpmStat.addSample(pulseBPM); | |
if(isLooking) bpmLookingStat.addSample(pulseBPM); | |
else bpmNotLookingStat.addSample(pulseBPM); | |
} | |
bpmStatArray[0][0] = (float) bpmStat.getMean(); | |
bpmStatArray[0][1] = (float) bpmLookingStat.getMean(); | |
bpmStatArray[0][2] = (float) bpmNotLookingStat.getMean(); | |
bpmStatArray[1][0] = (float) bpmStat.getStdDev(); | |
bpmStatArray[1][1] = (float) bpmLookingStat.getStdDev(); | |
bpmStatArray[1][2] = (float) bpmNotLookingStat.getStdDev(); | |
// store sample in csv file | |
// rowId, millis Processing, millis Arduino, BPM, IBI, isLooking, isLookingAuto, isLookingManual | |
String csv = rowId + "," + timeInMillis + "," + int(values[0]) + "," + pulseBPM + "," + | |
int(isPersonWaiting) + "," + int(isSession) + ","+ int(isLooking) + "," + int(isLookingAuto) + "," + int(isLookingManual) + "," + | |
// mean bpm total std bpm total | |
bpmStatArray[0][0] + "," + bpmStatArray[1][0] + "," + | |
// mean looking std bpm looking | |
bpmStatArray[0][1] + "," + bpmStatArray[1][1] + "," + | |
// mean bpm not looking std bpm not looking | |
bpmStatArray[0][2] + "," + bpmStatArray[1][2]; | |
outputCSV.println(csv); | |
//println(csv); | |
rowId++; | |
} | |
} | |
void startReading(String fileName) | |
{ | |
outputCSV = p.createWriter(fileName); | |
rowId = 0; | |
// reset Runningstat | |
bpmStat.clear(); | |
bpmLookingStat.clear(); | |
bpmNotLookingStat.clear(); | |
} | |
void stopReading() | |
{ outputCSV.flush(); | |
outputCSV.close(); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// RunningStat.PDE ----------- | |
// http://whileonefork.blogspot.nl/2011/09/tracking-running-standard-deviation.html | |
// points to: http://www.johndcook.com/standard_deviation.html | |
// This better way of computing variance goes back to a 1962 paper by B. P. Welford and is presented in | |
// Donald Knuth's Art of Computer Programming, Vol 2, page 232, 3rd edition. | |
// std dev is sqrt of variance | |
//class | |
public class RunningStat { | |
private int m_n; | |
private double m_oldM; | |
private double m_newM; | |
private double m_oldS; | |
private double m_newS; | |
public RunningStat() { | |
m_n = 0; | |
} | |
public void clear() { m_n = 0; } | |
public void addSample(double sample) { | |
m_n++; | |
// See Knuth TAOCP vol 2, 3rd edition, page 232 | |
if (m_n == 1) | |
{ | |
m_oldM = m_newM = sample; | |
m_oldS = 0.0; | |
} | |
else | |
{ | |
m_newM = m_oldM + (sample - m_oldM)/m_n; | |
m_newS = m_oldS + (sample - m_oldM)*(sample - m_newM); | |
// set up for next iteration | |
m_oldM = m_newM; | |
m_oldS = m_newS; | |
} | |
} | |
public int getNumSamples() { return m_n; } | |
public double getMean() { return (m_n > 0) ? m_newM : 0.0; } | |
public double getVariance() { return ( (m_n > 1) ? m_newS/(m_n - 1) : 0.0 ); } | |
public double getStdDev() { return Math.sqrt(getVariance()); } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment