Arduino heart beat sensor
Jag valde att läsa på https://create.arduino.cc/projecthub/Ingeimaks/diy-heart-rate-sensor-a96e89, där dom visar hur själva sensorn används men även kodningen. Arduino heart beat sensor är en sensor där du lägger ditt finger på den hjärtliknande föremålet, det som händer då är att den mäter ditt hjärtslag. På hemsidan https://store.arduino.cc/arduino-uno-rev3 kan du köpa själva arduinot men på hemsidan https://protocentral.com/product/pulse-pulse-ox-heart-rate-sensor-based-on-max30102/ så kan man köpa där man ska lägga sitt finger för att mäta hjärtslagen.
Exempel på kodning nedan, markera hela kodningen och sedan stryck Ctrl+C för att kopiera.
import processing.serial.*; // serial library lets us talk to Arduino PFont font; PFont portsFont; Scrollbar scaleBar; Serial port; 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[] RawY; // HOLDS HEARTBEAT WAVEFORM DATA BEFORE SCALING int[] ScaledY; // USED TO POSITION SCALED HEARTBEAT WAVEFORM int[] rate; // USED TO POSITION BPM DATA WAVEFORM float zoom; // USED WHEN SCALING PULSE WAVEFORM TO PULSE WINDOW float offset; // USED WHEN SCALING PULSE WAVEFORM TO PULSE WINDOW color eggshell = color(255, 253, 248); int heart = 0; // This variable times the heart image 'pulse' on screen // THESE VARIABLES DETERMINE THE SIZE OF THE DATA WINDOWS int PulseWindowWidth = 490; int PulseWindowHeight = 512; int BPMWindowWidth = 180; int BPMWindowHeight = 340; boolean beat = false; // 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(700, 600); // Stage size frameRate(100); font = loadFont("Arial-BoldMT-24.vlw"); textFont(font); textAlign(CENTER); rectMode(CENTER); ellipseMode(CENTER); // Scrollbar constructor inputs: x,y,width,height,minVal,maxVal scaleBar = new Scrollbar (400, 575, 180, 12, 0.5, 1.0); // set parameters for the scale bar RawY = new int[PulseWindowWidth]; // initialize raw pulse waveform array ScaledY = new int[PulseWindowWidth]; // initialize scaled pulse waveform array rate = new int [BPMWindowWidth]; // initialize BPM waveform array zoom = 0.75; // initialize scale of heartbeat window // set the visualizer lines to 0 resetDataTraces(); background(0); // DRAW OUT THE PULSE WINDOW AND BPM WINDOW RECTANGLES drawDataWindows(); drawHeart(); // GO FIND THE ARDUINO fill(eggshell); text("Select Your Serial Port",245,30); listAvailablePorts(); } void draw() { if(serialPortFound){ // ONLY RUN THE VISUALIZER AFTER THE PORT IS CONNECTED background(0); noStroke(); drawDataWindows(); drawPulseWaveform(); drawBPMwaveform(); drawHeart(); // PRINT THE DATA AND VARIABLE VALUES fill(eggshell); // get ready to print text text("Ingeimaks BPM PULSE",245,30); // tell them what you are text("IBI " + IBI + "mS",600,585); // print the time between heartbeats in mS text(BPM + " BPM",600,200); // print the Beats Per Minute text("Pulse Window Scale " + nf(zoom,1,2), 150, 585); // show the current scale of Pulse Window // DO THE SCROLLBAR THINGS scaleBar.update (mouseX, mouseY); scaleBar.display(); } else { // SCAN BUTTONS TO FIND THE SERIAL PORT autoScanPorts(); if(refreshPorts){ refreshPorts = false; drawDataWindows(); drawHeart(); listAvailablePorts(); } for(int i=0; i<numPorts+1; i++){ button[i].overRadio(mouseX,mouseY); button[i].displayRadio(); } } } //end of draw loop void drawDataWindows(){ // DRAW OUT THE PULSE WINDOW AND BPM WINDOW RECTANGLES noStroke(); fill(eggshell); // color for the window background rect(255,height/2,PulseWindowWidth,PulseWindowHeight); rect(600,385,BPMWindowWidth,BPMWindowHeight); } void drawPulseWaveform(){ // DRAW THE PULSE WAVEFORM // prepare pulse data points RawY[RawY.length-1] = (1023 - Sensor) - 212; // place the new raw datapoint at the end of the array zoom = scaleBar.getPos(); // get current waveform scale value offset = map(zoom,0.5,1,150,0); // calculate the offset needed at this scale for (int i = 0; i < RawY.length-1; i++) { // move the pulse waveform by RawY[i] = RawY[i+1]; // shifting all raw datapoints one pixel left float dummy = RawY[i] * zoom + offset; // adjust the raw data to the selected scale ScaledY[i] = constrain(int(dummy),44,556); // transfer the raw data array to the scaled array } stroke(250,0,0); // red is a good color for the pulse waveform noFill(); beginShape(); // using beginShape() renders fast for (int x = 1; x < ScaledY.length-1; x++) { vertex(x+10, ScaledY[x]); //draw a line connecting the data points } endShape(); } void drawBPMwaveform(){ // DRAW THE BPM WAVE FORM // first, shift the BPM waveform over to fit then next data point only when a beat is found if (beat == true){ // move the heart rate line over one pixel every time the heart beats beat = false; // clear beat flag (beat flag waset in serialEvent tab) for (int i=0; i<rate.length-1; i++){ rate[i] = rate[i+1]; // shift the bpm Y coordinates over one pixel to the left } // then limit and scale the BPM value BPM = min(BPM,200); // limit the highest BPM value to 200 float dummy = map(BPM,0,200,555,215); // map it to the heart rate window Y rate[rate.length-1] = int(dummy); // set the rightmost pixel to the new data point value } // GRAPH THE HEART RATE WAVEFORM stroke(250,0,0); // color of heart rate graph strokeWeight(2); // thicker line is easier to read noFill(); beginShape(); for (int i=0; i < rate.length-1; i++){ // variable 'i' will take the place of pixel x position vertex(i+510, rate[i]); // display history of heart rate datapoints } endShape(); } void drawHeart(){ // DRAW THE HEART AND MAYBE MAKE IT BEAT fill(250,0,0); stroke(250,0,0); // the 'heart' variable is set in serialEvent when arduino sees a beat happen heart--; // heart is used to time how long the heart graphic swells when your heart beats heart = max(heart,0); // don't let the heart variable go into negative numbers if (heart > 0){ // if a beat happened recently, strokeWeight(8); // make the heart big } smooth(); // draw the heart with two bezier curves bezier(width-100,50, width-20,-20, width,140, width-100,150); bezier(width-100,50, width-190,-20, width-200,140, width-100,150); strokeWeight(1); // reset the strokeWeight for next time } void listAvailablePorts(){ println(Serial.list()); // print a list of available serial ports to the console serialPorts = Serial.list(); fill(0); textFont(font,16); textAlign(LEFT); // set a counter to list the ports backwards int yPos = 0; int xPos = 35; for(int i=serialPorts.length-1; i>=0; i--){ button[i] = new Radio(xPos, 95+(yPos*20),12,color(180),color(80),color(255),i,button); text(serialPorts[i],xPos+15, 100+(yPos*20)); yPos++; if(yPos > height-30){ yPos = 0; xPos+=200; } } 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; // was serialPorts.length 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<rate.length; i++){ rate[i] = 555; // Place BPM graph line at bottom of BPM Window } for (int i=0; i<RawY.length; i++){ RawY[i] = height/2; // initialize the pulse window data line to V/2 } }