// Biofeedback by Marek Cermak. Use it as you want:). Plan was to release version with computing Heart Rate from Heart beats, thats the reason why are there so many unused variables Serial myPort; import processing.serial.*; Serial mySerial; PrintWriter output; int time = 0; int setTimeZero = 0; int timeBeats=0; int screenWidth = 1200, screenHeight=1000; boolean bSafe = false; boolean bRec = false; boolean bTime = true; boolean bStartBeat = false; float randNum = 0; int period = 0; //pokus vykreslovani String xLabel = "time(s)"; String yLabel = "Voltage (mV)"; String heading = "Biofeedback @MaraC"; int numOfVertDivisions=5; // dark gray int numOfVertSubDivisions=10; // light gray int numOfHorDivisions = 15; int leftMargin=70; int rightMargin=50; int graphYposition=50; int xPos=leftMargin; int lastxPos=xPos; int lastheight, lastheight2, lastheight3, lastheight4=graphYposition; int step = 20; int tooth = 0; float fs=1/(0.02); int TextGap=50; float avgSignal=0; float avgSignalSum=0; float avgScale=0; int window = 250; int value; int DivisounsWidth = 50; PFont font; PImage bg; float koefPeak = 1.4; int i=1; int n=0; int HR=0; float maxBeat = 0; float avgBeat = 0; int posBeat = 0; float yRatio = 0.85; int startBeat =0; float kanel1 = 0;//HR not filtered float kanel2 =0;// GSR float kanel3 = 0;//TEMP float kanel4=0;//HR filtered, gain 5,7 int endBeat = 0; int previousBeat = 0; int beatCount=0; int maxHeight = (screenHeight-graphYposition)-int(yRatio*(screenHeight)*(1/numOfVertDivisions)); int minHeight = graphYposition; float[] signal = {0}; float[] derivace={0}; float[] beatArray={0}; //for temp. see datasheet lmt70, page13. m and b are const value for temp equation for temperature between 30 and 40 celsius float m = 0.192; float b = 211.22; float temp=0; //int maxValue=5000; //8************************************** void setup() { size(screenWidth, screenHeight); font = createFont("Arial Narrow", 32); //mySerial = new Serial(this, Serial.list()[0], 115200); output = createWriter( "data.txt" ); background(0); setTimeZero = millis(); myPort = new Serial(this, Serial.list()[0], 115200); myPort.bufferUntil('\n'); background(0); // set inital background: Axis(); Labels(); Buttons(); Heart(); } void draw() { } void serialEvent (Serial myPort) { time = millis() - setTimeZero; Buttons(); String inString = myPort.readStringUntil('\n'); if(inString != null) { inString = trim(inString); // trim off whitespaces. int mysensors[] = int(split(inString, '\t')); int count = mysensors.length; kanel1 = float(mysensors[0]); kanel2 = float(mysensors[1]); kanel3 = float(mysensors[2]); kanel4 = float(mysensors[3]); } //computing signal average for computing HR - not completed signal = splice(signal, kanel1, signal.length); // pridam na posledni prvek pole signal cislo randNum if(signal.length=window){ avgSignalSum=avgSignalSum-signal[(signal.length-window)]; avgSignalSum=avgSignalSum+signal[(signal.length-1)];//tohle je posledni prvek avgSignal = avgSignalSum/window; } temp = b - (kanel3*m); println(temp); fill(0,0,0); rect(3, 60, 65, 30);//rectangle to erase old temp, stupid way but works fill(255,0,0); textFont(font,16); text("T=",5,80); text(temp,17,80); kanel1 = map(kanel1, 0, 5000, 0, maxHeight); kanel2 = map(kanel2, 0, 5000, 0, maxHeight); kanel3 = map(kanel3, 0, 5000, 0, maxHeight); kanel4 = map(kanel4, 0, 5000, 0, maxHeight); avgScale = map(avgSignal, 0, 5000, 0, maxHeight); stroke(255,255,255); line(lastxPos, lastheight, xPos, maxHeight - kanel1); lastheight= int(maxHeight-kanel1); stroke(0,255,0); line(lastxPos, lastheight2, xPos, maxHeight - kanel2); lastheight2= int(maxHeight-kanel2); stroke(255,255,0); line(lastxPos, lastheight3, xPos, maxHeight - kanel3); lastheight3= int(maxHeight-kanel3); stroke(255,0,0); line(lastxPos, lastheight4, xPos, maxHeight - kanel4); lastheight4= int(maxHeight-kanel4); lastxPos= xPos; /* if(bSafe){ output.print(derivace[derivace.length-1]); output.print( " "); output.println(kanel1); } */ // at the edge of the window, go back to the beginning: if (xPos >= (width - rightMargin)) { xPos = leftMargin; lastxPos = leftMargin; background(0); //Clear the screen. Heart(); Axis(); Labels(); //beatCount = 0; } else { // increment the horizontal position: xPos++; } n++; } void keyPressed() { if(key == 'e' || key == 'E'){ output.flush(); // Writes the remaining data to the file output.close(); // Finishes the file exit(); // Stops the program bSafe = false; bRec = false; } if(key == 'r' || key == 'R'){ bSafe = true; bRec = true; } } void Axis(){ strokeWeight(1); stroke(220); /*for(float x=0;x<=numOfVertSubDivisions;x++){ int bars=(screenHeight-graphYposition)-int(yRatio*(screenHeight)*(x/numOfVertSubDivisions)); line(leftMargin-15,bars,screenWidth-rightMargin-DivisounsWidth,bars); } */ strokeWeight(1); stroke(180); for(float x=0;x<=numOfVertDivisions;x++){ int bars=(screenWidth-leftMargin-rightMargin)-int((screenWidth)*(x/numOfVertDivisions)); //println(bars); line(leftMargin,bars,screenWidth-rightMargin,bars); } strokeWeight(2); stroke(90); //println(DivisounsWidth); //println(screenWidth-rightMargin-DivisounsWidth+50);println(screenHeight-graphYposition+2); line(leftMargin, screenHeight-graphYposition+2, screenWidth-rightMargin, screenHeight-graphYposition+2); line(leftMargin,screenHeight-graphYposition+2,leftMargin,graphYposition); strokeWeight(1); } void Labels(){ textFont(font,18); fill(50); for(float x=0;x<=(round((screenWidth-leftMargin-rightMargin)/fs));x++){ float timeStamps=x*fs; text(round(x),timeStamps,height-graphYposition+30); } textFont(font,18); fill(50); rotate(radians(-90)); text(yLabel,-screenHeight/2,leftMargin-45); textFont(font,16); for(float x=0;x<=numOfVertDivisions;x++){ int bars=(screenHeight-graphYposition)-int(yRatio*(screenHeight)*(x/numOfVertDivisions)); text(round(x)*1000,-bars,leftMargin-10); } textFont(font,18); rotate(radians(90)); text(xLabel,leftMargin+(screenWidth-leftMargin-rightMargin-30)/2,screenHeight-graphYposition+45); textFont(font,24); fill(50); text(heading,leftMargin+(screenWidth-leftMargin-rightMargin-30)/2,30); textFont(font); } void Buttons(){ if (bRec){ textFont(font,16); fill(255,0,0); ellipse(30, 25, 10, 10); text("rec",20,45); } } void Heart(){ smooth(); noStroke(); fill(255,0,0); beginShape(); vertex(50, 15); bezierVertex(50, -5, 90, 5, 50, 40); vertex(50, 15); bezierVertex(50, -5, 10, 5, 50, 40); endShape(); }