Components and supplies
28BYJ-48 Stepper Motor with ULN2003 Driver Board
Jumper wires (generic)
Standard LCD - 16x2 White on Blue
9 Volt Battery
Rocker Switch, VISI-ROCKER
Rotary potentiometer (generic)
Male/Female Jumper Wires
Arduino UNO
Pulsesensor
best promotion 95DB alarm for Arduino High-decibel DC 3- 24V 12V electronic buzzer
Apps and platforms
Arduino IDE
Project description
Code
untitled
c_cpp
1Laith Adnan, [24.07.19 17:41] 2[ Photo ] 3 4Laith Adnan, [24.07.19 20:07] 5#include <LiquidCrystal.h> 6#define IN1 8 7#define IN2 9 8#define IN3 10 9#define IN4 7 10int Steps = 4096; //4096 or 768 11int cstep = 0; 12const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; 13const int buzzer = 9; 14LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 15 16int pulsePin = A0; // Pulse Sensor purple wire connected to analog pin A0 17int blinkPin = 13; // pin to blink led at each beat 18// Volatile Variables, used in the interrupt service routine! 19volatile int BPM; // int that holds raw Analog in 0. updated every 2mS 20volatile int Signal; // holds the incoming raw data 21volatile int IBI = 600; // int that holds the time interval between beats! Must be seeded! 22volatile boolean Pulse = false; // "True" when User's live heartbeat is detected. "False" when not a "live beat". 23volatile boolean QS = false; // becomes true when Arduoino finds a beat. 24 25static boolean serialVisual = true; // Set to 'false' by Default. Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse 26 27volatile int rate[10]; // array to hold last ten IBI values 28volatile unsigned long sampleCounter = 0; // used to determine pulse timing 29volatile unsigned long lastBeatTime = 0; // used to find IBI 30volatile int P = 512; // used to find peak in pulse wave, seeded 31volatile int T = 512; // used to find trough in pulse wave, seeded 32volatile int thresh = 525; // used to find instant moment of heart beat, seeded 33volatile int amp = 100; // used to hold amplitude of pulse waveform, seeded 34volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM 35volatile boolean secondBeat = false; // used to seed rate array so we startup with reasonable BPM 36 37void setup() 38{ 39 pinMode(IN1, OUTPUT); 40 pinMode(IN2, OUTPUT); 41 pinMode(IN3, OUTPUT); 42 pinMode(IN4, OUTPUT); 43 pinMode(buzzer,OUTPUT); 44 pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat! 45 Serial.begin(115200); // we agree to talk fast! 46 interruptSetup(); // sets up to read Pulse Sensor signal every 2mS 47 // IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE, 48 // UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN 49 // analogReference(EXTERNAL); 50 lcd.begin(16, 2); 51 lcd.clear(); 52} 53 54 55// Where the Magic Happens 56void loop() 57{ 58 serialOutput(); 59 lcd.print("DEVICE-STATE"); 60 lcd.setCursor(1,1); 61 lcd.print("UPDATING... "); 62 lcd.setCursor(5,1); 63 delay(3000); 64 lcd.clear(); 65 if (QS == true) // A Heartbeat Was Found 66 { 67 // BPM and IBI have been Determined 68 // Quantified Self "QS" true when arduino finds a heartbeat 69 serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial. 70 QS = false; // reset the Quantified Self flag for next time 71 state(); 72 buzer(); 73 inject(); 74 } 75 76 delay(20); // take a break 77} 78 79 80void interruptSetup() 81{ 82 // Initializes Timer2 to throw an interrupt every 2mS. 83 TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE 84 TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER 85 OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE 86 TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A 87 sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED 88} 89 90void serialOutput() 91{ // Decide How To Output Serial. 92 if (serialVisual == true) 93 { 94 arduinoSerialMonitorVisual('-', Signal); // goes to function that makes Serial Monitor Visualizer 95 } 96 else 97 { 98 sendDataToSerial('S', Signal); // goes to sendDataToSerial function 99 } 100} 101 102Laith Adnan, [24.07.19 20:07] 103void serialOutputWhenBeatHappens() 104{ 105 if (serialVisual == true) // Code to Make the Serial Monitor Visualizer Work 106 { 107 Serial.print(" Heart-Beat Found "); //ASCII Art Madness 108 Serial.print("BPM: "); 109 Serial.println(BPM); 110 lcd.print("Heart-Beat Found "); 111 lcd.setCursor(1,1); 112 lcd.print("BPM: "); 113 lcd.setCursor(5,1); 114 lcd.print(BPM); 115 delay(3000); 116 lcd.clear(); 117 } 118 else 119 { 120 sendDataToSerial('B',BPM); // send heart rate with a 'B' prefix 121 sendDataToSerial('Q',IBI); // send time between beats with a 'Q' prefix 122 } 123} 124 125void arduinoSerialMonitorVisual(char symbol, int data ) 126{ 127 const int sensorMin = 0; // sensor minimum, discovered through experiment 128 const int sensorMax = 1024; // sensor maximum, discovered through experiment 129 int sensorReading = data; // map the sensor range to a range of 12 options: 130 int range = map(sensorReading, sensorMin, sensorMax, 0, 11); 131 // do something different depending on the 132 // range value: 133} 134 135 136void sendDataToSerial(char symbol, int data ) 137{ 138 Serial.print(symbol); 139 Serial.println(data); 140} 141 142ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts to 124 143{ 144 cli(); // disable interrupts while we do this 145 Signal = analogRead(pulsePin); // read the Pulse Sensor 146 sampleCounter += 2; // keep track of the time in mS with this variable 147 int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise 148 // find the peak and trough of the pulse wave 149 if(Signal < thresh && N > (IBI/5)*3) // avoid dichrotic noise by waiting 3/5 of last IBI 150 { 151 if (Signal < T) // T is the trough 152 { 153 T = Signal; // keep track of lowest point in pulse wave 154 } 155 } 156 157 if(Signal > thresh && Signal > P) 158 { // thresh condition helps avoid noise 159 P = Signal; // P is the peak 160 } // keep track of highest point in pulse wave 161 162 // NOW IT'S TIME TO LOOK FOR THE HEART BEAT 163 // signal surges up in value every time there is a pulse 164 if (N > 250) 165 { // avoid high frequency noise 166 if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) 167 { 168 Pulse = true; // set the Pulse flag when we think there is a pulse 169 digitalWrite(blinkPin,HIGH); // turn on pin 13 LED 170 IBI = sampleCounter - lastBeatTime; // measure time between beats in mS 171 lastBeatTime = sampleCounter; // keep track of time for next pulse 172 173 if(secondBeat) 174 { // if this is the second beat, if secondBeat == TRUE 175 secondBeat = false; // clear secondBeat flag 176 for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup 177 { 178 rate[i] = IBI; 179 } 180 } 181 182 if(firstBeat) // if it's the first time we found a beat, if firstBeat == TRUE 183 { 184 firstBeat = false; // clear firstBeat flag 185 secondBeat = true; // set the second beat flag 186 sei(); // enable interrupts again 187 return; // IBI value is unreliable so discard it 188 } 189 // keep a running total of the last 10 IBI values 190 word runningTotal = 0; // clear the runningTotal variable 191 192 for(int i=0; i<=8; i++) 193 { // shift data in the rate array 194 rate[i] = rate[i+1]; // and drop the oldest IBI value 195 runningTotal += rate[i]; // add up the 9 oldest IBI values 196 } 197 198Laith Adnan, [24.07.19 20:07] 199rate[9] = IBI; // add the latest IBI to the rate array 200 runningTotal += rate[9]; // add the latest IBI to runningTotal 201 runningTotal /= 10; // average the last 10 IBI values 202 BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! 203 QS = true; // set Quantified Self flag 204 // QS FLAG IS NOT CLEARED INSIDE THIS ISR 205 } 206 } 207 208 if (Signal < thresh && Pulse == true) 209 { // when the values are going down, the beat is over 210 digitalWrite(blinkPin,LOW); // turn off pin 13 LED 211 Pulse = false; // reset the Pulse flag so we can do it again 212 amp = P - T; // get amplitude of the pulse wave 213 thresh = amp/2 + T; // set thresh at 50% of the amplitude 214 P = thresh; // reset these for next time 215 T = thresh; 216 } 217 218 if (N > 2500) 219 { // if 2.5 seconds go by without a beat 220 thresh = 512; // set thresh default 221 P = 512; // set P default 222 T = 512; // set T default 223 lastBeatTime = sampleCounter; // bring the lastBeatTime up to date 224 firstBeat = true; // set these to avoid noise 225 secondBeat = false; // when we get the heartbeat back 226 } 227 228 sei(); // enable interrupts when youre done! 229}// end isr 230void buzer(){ 231 // dangerous situation or pressed button 232 if (BPM < 60 ) 233 { 234 lcd.print("hypotension"); 235 lcd.setCursor(1,1); 236 lcd.print("BPM: "); 237 lcd.setCursor(5,1); 238 lcd.print(BPM); 239 delay(3000); 240 lcd.clear(); 241 digitalWrite(buzzer,HIGH); 242 delay(500); 243 digitalWrite(buzzer,LOW); 244 delay(500); 245 246} 247 248} 249void inject() 250{ 251 if (BPM>160) 252 { 253 lcd.print("Hypertention"); 254 lcd.setCursor(1,1); 255 lcd.print("BPM: "); 256 lcd.setCursor(5,1); 257 lcd.print(BPM); 258 delay(5000); 259 lcd.clear(); 260 for(int x=0;x<Steps;x++) 261 { 262 switch(cstep) 263 { 264 case 0: 265 digitalWrite(IN1, LOW); 266 digitalWrite(IN2, LOW); 267 digitalWrite(IN3, LOW); 268 digitalWrite(IN4, HIGH); 269 break; 270 case 1: 271 digitalWrite(IN1, LOW); 272 digitalWrite(IN2, LOW); 273 digitalWrite(IN3, HIGH); 274 digitalWrite(IN4, HIGH); 275 break; 276 case 2: 277 digitalWrite(IN1, LOW); 278 digitalWrite(IN2, LOW); 279 digitalWrite(IN3, HIGH); 280 digitalWrite(IN4, LOW); 281 break; 282 case 3: 283 digitalWrite(IN1, LOW); 284 digitalWrite(IN2, HIGH); 285 digitalWrite(IN3, HIGH); 286 digitalWrite(IN4, LOW); 287 break; 288 case 4: 289 digitalWrite(IN1, LOW); 290 digitalWrite(IN2, HIGH); 291 digitalWrite(IN3, LOW); 292 digitalWrite(IN4, LOW); 293 break; 294 case 5: 295 digitalWrite(IN1, HIGH); 296 digitalWrite(IN2, HIGH); 297 digitalWrite(IN3, LOW); 298 digitalWrite(IN4, LOW); 299 break; 300 case 6: 301 digitalWrite(IN1, HIGH); 302 digitalWrite(IN2, LOW); 303 digitalWrite(IN3, LOW); 304 digitalWrite(IN4, LOW); 305 break; 306 case 7: 307 digitalWrite(IN1, HIGH); 308 digitalWrite(IN2, LOW); 309 digitalWrite(IN3, LOW); 310 digitalWrite(IN4, HIGH); 311 break; 312 default: 313 digitalWrite(IN1, LOW); 314 digitalWrite(IN2, LOW); 315 digitalWrite(IN3, LOW); 316 digitalWrite(IN4, LOW); 317 break; 318 } 319 320 cstep=cstep+1; 321 if(cstep==8) 322 {cstep=0;} 323 324 delayMicroseconds(2500); 325 326 } 327} 328} 329void state() 330{ 331 if (BPM > 60 & BPM < 74){ 332 lcd.print("VERY-GOOD"); 333 lcd.setCursor(1,1); 334 lcd.print("BPM: "); 335 lcd.setCursor(5,1); 336 lcd.print(BPM); 337 delay(3000); 338 lcd.clear(); 339 } 340}
untitled
c_cpp
1Laith Adnan, [24.07.19 17:41] 2[ Photo ] 3 4Laith Adnan, [24.07.19 20:07] 5#include <LiquidCrystal.h> 6#define IN1 8 7#define IN2 9 8#define IN3 10 9#define IN4 7 10int Steps = 4096; //4096 or 768 11int cstep = 0; 12const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; 13const int buzzer = 9; 14LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 15 16int pulsePin = A0; // Pulse Sensor purple wire connected to analog pin A0 17int blinkPin = 13; // pin to blink led at each beat 18// Volatile Variables, used in the interrupt service routine! 19volatile int BPM; // int that holds raw Analog in 0. updated every 2mS 20volatile int Signal; // holds the incoming raw data 21volatile int IBI = 600; // int that holds the time interval between beats! Must be seeded! 22volatile boolean Pulse = false; // "True" when User's live heartbeat is detected. "False" when not a "live beat". 23volatile boolean QS = false; // becomes true when Arduoino finds a beat. 24 25static boolean serialVisual = true; // Set to 'false' by Default. Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse 26 27volatile int rate[10]; // array to hold last ten IBI values 28volatile unsigned long sampleCounter = 0; // used to determine pulse timing 29volatile unsigned long lastBeatTime = 0; // used to find IBI 30volatile int P = 512; // used to find peak in pulse wave, seeded 31volatile int T = 512; // used to find trough in pulse wave, seeded 32volatile int thresh = 525; // used to find instant moment of heart beat, seeded 33volatile int amp = 100; // used to hold amplitude of pulse waveform, seeded 34volatile boolean firstBeat = true; // used to seed rate array so we startup with reasonable BPM 35volatile boolean secondBeat = false; // used to seed rate array so we startup with reasonable BPM 36 37void setup() 38{ 39 pinMode(IN1, OUTPUT); 40 pinMode(IN2, OUTPUT); 41 pinMode(IN3, OUTPUT); 42 pinMode(IN4, OUTPUT); 43 pinMode(buzzer,OUTPUT); 44 pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat! 45 Serial.begin(115200); // we agree to talk fast! 46 interruptSetup(); // sets up to read Pulse Sensor signal every 2mS 47 // IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE, 48 // UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE TO THE A-REF PIN 49 // analogReference(EXTERNAL); 50 lcd.begin(16, 2); 51 lcd.clear(); 52} 53 54 55// Where the Magic Happens 56void loop() 57{ 58 serialOutput(); 59 lcd.print("DEVICE-STATE"); 60 lcd.setCursor(1,1); 61 lcd.print("UPDATING... "); 62 lcd.setCursor(5,1); 63 delay(3000); 64 lcd.clear(); 65 if (QS == true) // A Heartbeat Was Found 66 { 67 // BPM and IBI have been Determined 68 // Quantified Self "QS" true when arduino finds a heartbeat 69 serialOutputWhenBeatHappens(); // A Beat Happened, Output that to serial. 70 QS = false; // reset the Quantified Self flag for next time 71 state(); 72 buzer(); 73 inject(); 74 } 75 76 delay(20); // take a break 77} 78 79 80void interruptSetup() 81{ 82 // Initializes Timer2 to throw an interrupt every 2mS. 83 TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE 84 TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER 85 OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE 86 TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A 87 sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED 88} 89 90void serialOutput() 91{ // Decide How To Output Serial. 92 if (serialVisual == true) 93 { 94 arduinoSerialMonitorVisual('-', Signal); // goes to function that makes Serial Monitor Visualizer 95 } 96 else 97 { 98 sendDataToSerial('S', Signal); // goes to sendDataToSerial function 99 } 100} 101 102Laith Adnan, [24.07.19 20:07] 103void serialOutputWhenBeatHappens() 104{ 105 if (serialVisual == true) // Code to Make the Serial Monitor Visualizer Work 106 { 107 Serial.print(" Heart-Beat Found "); //ASCII Art Madness 108 Serial.print("BPM: "); 109 Serial.println(BPM); 110 lcd.print("Heart-Beat Found "); 111 lcd.setCursor(1,1); 112 lcd.print("BPM: "); 113 lcd.setCursor(5,1); 114 lcd.print(BPM); 115 delay(3000); 116 lcd.clear(); 117 } 118 else 119 { 120 sendDataToSerial('B',BPM); // send heart rate with a 'B' prefix 121 sendDataToSerial('Q',IBI); // send time between beats with a 'Q' prefix 122 } 123} 124 125void arduinoSerialMonitorVisual(char symbol, int data ) 126{ 127 const int sensorMin = 0; // sensor minimum, discovered through experiment 128 const int sensorMax = 1024; // sensor maximum, discovered through experiment 129 int sensorReading = data; // map the sensor range to a range of 12 options: 130 int range = map(sensorReading, sensorMin, sensorMax, 0, 11); 131 // do something different depending on the 132 // range value: 133} 134 135 136void sendDataToSerial(char symbol, int data ) 137{ 138 Serial.print(symbol); 139 Serial.println(data); 140} 141 142ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts to 124 143{ 144 cli(); // disable interrupts while we do this 145 Signal = analogRead(pulsePin); // read the Pulse Sensor 146 sampleCounter += 2; // keep track of the time in mS with this variable 147 int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise 148 // find the peak and trough of the pulse wave 149 if(Signal < thresh && N > (IBI/5)*3) // avoid dichrotic noise by waiting 3/5 of last IBI 150 { 151 if (Signal < T) // T is the trough 152 { 153 T = Signal; // keep track of lowest point in pulse wave 154 } 155 } 156 157 if(Signal > thresh && Signal > P) 158 { // thresh condition helps avoid noise 159 P = Signal; // P is the peak 160 } // keep track of highest point in pulse wave 161 162 // NOW IT'S TIME TO LOOK FOR THE HEART BEAT 163 // signal surges up in value every time there is a pulse 164 if (N > 250) 165 { // avoid high frequency noise 166 if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) 167 { 168 Pulse = true; // set the Pulse flag when we think there is a pulse 169 digitalWrite(blinkPin,HIGH); // turn on pin 13 LED 170 IBI = sampleCounter - lastBeatTime; // measure time between beats in mS 171 lastBeatTime = sampleCounter; // keep track of time for next pulse 172 173 if(secondBeat) 174 { // if this is the second beat, if secondBeat == TRUE 175 secondBeat = false; // clear secondBeat flag 176 for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup 177 { 178 rate[i] = IBI; 179 } 180 } 181 182 if(firstBeat) // if it's the first time we found a beat, if firstBeat == TRUE 183 { 184 firstBeat = false; // clear firstBeat flag 185 secondBeat = true; // set the second beat flag 186 sei(); // enable interrupts again 187 return; // IBI value is unreliable so discard it 188 } 189 // keep a running total of the last 10 IBI values 190 word runningTotal = 0; // clear the runningTotal variable 191 192 for(int i=0; i<=8; i++) 193 { // shift data in the rate array 194 rate[i] = rate[i+1]; // and drop the oldest IBI value 195 runningTotal += rate[i]; // add up the 9 oldest IBI values 196 } 197 198Laith Adnan, [24.07.19 20:07] 199rate[9] = IBI; // add the latest IBI to the rate array 200 runningTotal += rate[9]; // add the latest IBI to runningTotal 201 runningTotal /= 10; // average the last 10 IBI values 202 BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! 203 QS = true; // set Quantified Self flag 204 // QS FLAG IS NOT CLEARED INSIDE THIS ISR 205 } 206 } 207 208 if (Signal < thresh && Pulse == true) 209 { // when the values are going down, the beat is over 210 digitalWrite(blinkPin,LOW); // turn off pin 13 LED 211 Pulse = false; // reset the Pulse flag so we can do it again 212 amp = P - T; // get amplitude of the pulse wave 213 thresh = amp/2 + T; // set thresh at 50% of the amplitude 214 P = thresh; // reset these for next time 215 T = thresh; 216 } 217 218 if (N > 2500) 219 { // if 2.5 seconds go by without a beat 220 thresh = 512; // set thresh default 221 P = 512; // set P default 222 T = 512; // set T default 223 lastBeatTime = sampleCounter; // bring the lastBeatTime up to date 224 firstBeat = true; // set these to avoid noise 225 secondBeat = false; // when we get the heartbeat back 226 } 227 228 sei(); // enable interrupts when youre done! 229}// end isr 230void buzer(){ 231 // dangerous situation or pressed button 232 if (BPM < 60 ) 233 { 234 lcd.print("hypotension"); 235 lcd.setCursor(1,1); 236 lcd.print("BPM: "); 237 lcd.setCursor(5,1); 238 lcd.print(BPM); 239 delay(3000); 240 lcd.clear(); 241 digitalWrite(buzzer,HIGH); 242 delay(500); 243 digitalWrite(buzzer,LOW); 244 delay(500); 245 246} 247 248} 249void inject() 250{ 251 if (BPM>160) 252 { 253 lcd.print("Hypertention"); 254 lcd.setCursor(1,1); 255 lcd.print("BPM: "); 256 lcd.setCursor(5,1); 257 lcd.print(BPM); 258 delay(5000); 259 lcd.clear(); 260 for(int x=0;x<Steps;x++) 261 { 262 switch(cstep) 263 { 264 case 0: 265 digitalWrite(IN1, LOW); 266 digitalWrite(IN2, LOW); 267 digitalWrite(IN3, LOW); 268 digitalWrite(IN4, HIGH); 269 break; 270 case 1: 271 digitalWrite(IN1, LOW); 272 digitalWrite(IN2, LOW); 273 digitalWrite(IN3, HIGH); 274 digitalWrite(IN4, HIGH); 275 break; 276 case 2: 277 digitalWrite(IN1, LOW); 278 digitalWrite(IN2, LOW); 279 digitalWrite(IN3, HIGH); 280 digitalWrite(IN4, LOW); 281 break; 282 case 3: 283 digitalWrite(IN1, LOW); 284 digitalWrite(IN2, HIGH); 285 digitalWrite(IN3, HIGH); 286 digitalWrite(IN4, LOW); 287 break; 288 case 4: 289 digitalWrite(IN1, LOW); 290 digitalWrite(IN2, HIGH); 291 digitalWrite(IN3, LOW); 292 digitalWrite(IN4, LOW); 293 break; 294 case 5: 295 digitalWrite(IN1, HIGH); 296 digitalWrite(IN2, HIGH); 297 digitalWrite(IN3, LOW); 298 digitalWrite(IN4, LOW); 299 break; 300 case 6: 301 digitalWrite(IN1, HIGH); 302 digitalWrite(IN2, LOW); 303 digitalWrite(IN3, LOW); 304 digitalWrite(IN4, LOW); 305 break; 306 case 7: 307 digitalWrite(IN1, HIGH); 308 digitalWrite(IN2, LOW); 309 digitalWrite(IN3, LOW); 310 digitalWrite(IN4, HIGH); 311 break; 312 default: 313 digitalWrite(IN1, LOW); 314 digitalWrite(IN2, LOW); 315 digitalWrite(IN3, LOW); 316 digitalWrite(IN4, LOW); 317 break; 318 } 319 320 cstep=cstep+1; 321 if(cstep==8) 322 {cstep=0;} 323 324 delayMicroseconds(2500); 325 326 } 327} 328} 329void state() 330{ 331 if (BPM > 60 & BPM < 74){ 332 lcd.print("VERY-GOOD"); 333 lcd.setCursor(1,1); 334 lcd.print("BPM: "); 335 lcd.setCursor(5,1); 336 lcd.print(BPM); 337 delay(3000); 338 lcd.clear(); 339 } 340}
untitled
c_cpp
1Laith Adnan, [24.07.19 17:41] 2[ Photo ] 3 4Laith Adnan, [24.07.19 5 20:07] 6#include <LiquidCrystal.h> 7#define IN1 8 8#define IN2 9 9#define 10 IN3 10 11#define IN4 7 12int Steps = 13 4096; //4096 or 768 14int cstep = 0; 15const int rs = 12, en = 11, d4 = 5, d5 16 = 4, d6 = 3, d7 = 2; 17const int buzzer = 9; 18LiquidCrystal lcd(12, 11, 5, 4, 19 3, 2); 20 21int pulsePin = A0; // Pulse Sensor purple wire connected 22 to analog pin A0 23int blinkPin = 13; // pin to blink led at each 24 beat 25// Volatile Variables, used in the interrupt service routine! 26volatile 27 int BPM; // int that holds raw Analog in 0. updated every 2mS 28volatile 29 int Signal; // holds the incoming raw data 30volatile int IBI = 31 600; // int that holds the time interval between beats! Must be seeded! 32 33volatile boolean Pulse = false; // "True" when User's live heartbeat is 34 detected. "False" when not a "live beat". 35volatile boolean QS = false; // 36 becomes true when Arduoino finds a beat. 37 38static boolean serialVisual = true; 39 // Set to 'false' by Default. Re-set to 'true' to see Arduino Serial Monitor 40 ASCII Visual Pulse 41 42volatile int rate[10]; // array 43 to hold last ten IBI values 44volatile unsigned long sampleCounter = 0; // 45 used to determine pulse timing 46volatile unsigned long lastBeatTime = 0; // 47 used to find IBI 48volatile int P = 512; // used to find peak 49 in pulse wave, seeded 50volatile int T = 512; // used to find 51 trough in pulse wave, seeded 52volatile int thresh = 525; // used 53 to find instant moment of heart beat, seeded 54volatile int amp = 100; // 55 used to hold amplitude of pulse waveform, seeded 56volatile boolean firstBeat = 57 true; // used to seed rate array so we startup with reasonable BPM 58volatile 59 boolean secondBeat = false; // used to seed rate array so we startup with reasonable 60 BPM 61 62void setup() 63{ 64 pinMode(IN1, OUTPUT); 65 pinMode(IN2, OUTPUT); 66 67 pinMode(IN3, OUTPUT); 68 pinMode(IN4, OUTPUT); 69 pinMode(buzzer,OUTPUT); 70 71 pinMode(blinkPin,OUTPUT); // pin that will blink to your heartbeat! 72 73 Serial.begin(115200); // we agree to talk fast! 74 interruptSetup(); 75 // sets up to read Pulse Sensor signal every 2mS 76 // 77 IF YOU ARE POWERING The Pulse Sensor AT VOLTAGE LESS THAN THE BOARD VOLTAGE, 78 79 // UN-COMMENT THE NEXT LINE AND APPLY THAT VOLTAGE 80 TO THE A-REF PIN 81 // analogReference(EXTERNAL); 82 83 lcd.begin(16, 2); 84 lcd.clear(); 85} 86 87 88// Where the Magic Happens 89void 90 loop() 91{ 92 serialOutput(); 93 lcd.print("DEVICE-STATE"); 94 lcd.setCursor(1,1); 95 96 lcd.print("UPDATING... "); 97 lcd.setCursor(5,1); 98 delay(3000); 99 100 lcd.clear(); 101 if (QS == true) // A Heartbeat Was Found 102 { 103 104 // BPM and IBI have been Determined 105 // Quantified Self "QS" true 106 when arduino finds a heartbeat 107 serialOutputWhenBeatHappens(); // A Beat 108 Happened, Output that to serial. 109 QS = false; // reset the Quantified 110 Self flag for next time 111 state(); 112 buzer(); 113 inject(); 114 115 } 116 117 delay(20); // take a break 118} 119 120 121void interruptSetup() 122{ 123 124 // Initializes Timer2 to throw an interrupt every 2mS. 125 TCCR2A = 126 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE 127 TCCR2B 128 = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER 129 OCR2A = 0X7C; // SET 130 THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE 131 TIMSK2 = 0x02; // ENABLE 132 INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A 133 sei(); // MAKE SURE 134 GLOBAL INTERRUPTS ARE ENABLED 135} 136 137void serialOutput() 138{ // Decide 139 How To Output Serial. 140 if (serialVisual == true) 141 { 142 arduinoSerialMonitorVisual('-', 143 Signal); // goes to function that makes Serial Monitor Visualizer 144 } 145 146 else 147 { 148 sendDataToSerial('S', Signal); // goes to sendDataToSerial 149 function 150 } 151} 152 153Laith Adnan, [24.07.19 20:07] 154void serialOutputWhenBeatHappens() 155{ 156 157 if (serialVisual == true) // Code to Make the Serial Monitor Visualizer 158 Work 159 { 160 Serial.print(" Heart-Beat Found "); //ASCII 161 Art Madness 162 Serial.print("BPM: "); 163 Serial.println(BPM); 164 lcd.print("Heart-Beat 165 Found "); 166 lcd.setCursor(1,1); 167 lcd.print("BPM: "); 168 lcd.setCursor(5,1); 169 170 lcd.print(BPM); 171 delay(3000); 172 lcd.clear(); 173 } 174 else 175 176 { 177 sendDataToSerial('B',BPM); // send heart rate with a 'B' prefix 178 179 sendDataToSerial('Q',IBI); // send time between beats with a 'Q' prefix 180 181 } 182} 183 184void arduinoSerialMonitorVisual(char symbol, int data ) 185{ 186 187 const int sensorMin = 0; // sensor minimum, discovered through experiment 188 189 const int sensorMax = 1024; // sensor maximum, discovered through experiment 190 191 int sensorReading = data; // map the sensor range to a range of 12 options: 192 193 int range = map(sensorReading, sensorMin, sensorMax, 0, 11); 194 // do something 195 different depending on the 196 // range value: 197} 198 199 200void sendDataToSerial(char 201 symbol, int data ) 202{ 203 Serial.print(symbol); 204 Serial.println(data); 205 206} 207 208ISR(TIMER2_COMPA_vect) //triggered when Timer2 counts 209 to 124 210{ 211 cli(); // disable interrupts 212 while we do this 213 Signal = analogRead(pulsePin); // read the Pulse 214 Sensor 215 sampleCounter += 2; // keep track of the time 216 in mS with this variable 217 int N = sampleCounter - lastBeatTime; // monitor 218 the time since the last beat to avoid noise 219 // 220 find the peak and trough of the pulse wave 221 if(Signal < thresh && N > (IBI/5)*3) 222 // avoid dichrotic noise by waiting 3/5 of last IBI 223 { 224 if (Signal 225 < T) // T is the trough 226 { 227 T = Signal; 228 // keep track of lowest point in pulse wave 229 } 230 } 231 232 if(Signal 233 > thresh && Signal > P) 234 { // thresh condition helps avoid noise 235 236 P = Signal; // P is the peak 237 } // 238 keep track of highest point in pulse wave 239 240 // NOW IT'S TIME TO LOOK FOR 241 THE HEART BEAT 242 // signal surges up in value every time there is a pulse 243 244 if (N > 250) 245 { // avoid high frequency 246 noise 247 if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) 248 249 { 250 Pulse = true; // set the 251 Pulse flag when we think there is a pulse 252 digitalWrite(blinkPin,HIGH); 253 // turn on pin 13 LED 254 IBI = sampleCounter - lastBeatTime; 255 // measure time between beats in mS 256 lastBeatTime = sampleCounter; 257 // keep track of time for next pulse 258 259 if(secondBeat) 260 261 { // if this is the second beat, if secondBeat == 262 TRUE 263 secondBeat = false; // clear secondBeat flag 264 265 for(int i=0; i<=9; i++) // seed the running total to get a realisitic 266 BPM at startup 267 { 268 rate[i] = IBI; 269 270 } 271 } 272 273 if(firstBeat) // if it's the first time 274 we found a beat, if firstBeat == TRUE 275 { 276 277 firstBeat = false; // clear firstBeat flag 278 secondBeat 279 = true; // set the second beat flag 280 sei(); // 281 enable interrupts again 282 return; // IBI 283 value is unreliable so discard it 284 } 285 // keep a running total 286 of the last 10 IBI values 287 word runningTotal = 0; // clear 288 the runningTotal variable 289 290 for(int i=0; i<=8; i++) 291 { 292 // shift data in the rate array 293 rate[i] = rate[i+1]; 294 // and drop the oldest IBI value 295 runningTotal += 296 rate[i]; // add up the 9 oldest IBI values 297 } 298 299Laith 300 Adnan, [24.07.19 20:07] 301rate[9] = IBI; // add the latest 302 IBI to the rate array 303 runningTotal += rate[9]; // add the 304 latest IBI to runningTotal 305 runningTotal /= 10; // average 306 the last 10 IBI values 307 BPM = 60000/runningTotal; // how 308 many beats can fit into a minute? that's BPM! 309 QS = true; // 310 set Quantified Self flag 311 // QS FLAG IS NOT CLEARED INSIDE THIS ISR 312 313 } 314 } 315 316 if (Signal < thresh && Pulse == true) 317 318 { // when the values are going down, the beat is over 319 digitalWrite(blinkPin,LOW); 320 // turn off pin 13 LED 321 Pulse = false; // 322 reset the Pulse flag so we can do it again 323 amp = P - T; // 324 get amplitude of the pulse wave 325 thresh = amp/2 + T; // 326 set thresh at 50% of the amplitude 327 P = thresh; // 328 reset these for next time 329 T = thresh; 330 } 331 332 if (N > 2500) 333 334 { // if 2.5 seconds go by without a beat 335 thresh 336 = 512; // set thresh default 337 P = 512; // 338 set P default 339 T = 512; // set T default 340 341 lastBeatTime = sampleCounter; // bring the lastBeatTime up to date 342 343 firstBeat = true; // set these to avoid noise 344 345 secondBeat = false; // when we get the heartbeat back 346 347 } 348 349 sei(); // enable interrupts when 350 youre done! 351}// end isr 352void buzer(){ 353 // dangerous situation or pressed 354 button 355 if (BPM < 60 ) 356 { 357 lcd.print("hypotension"); 358 lcd.setCursor(1,1); 359 360 lcd.print("BPM: "); 361 lcd.setCursor(5,1); 362 lcd.print(BPM); 363 364 delay(3000); 365 lcd.clear(); 366 digitalWrite(buzzer,HIGH); 367 delay(500); 368 369 digitalWrite(buzzer,LOW); 370 delay(500); 371 372} 373 374 375} 376void inject() 377{ 378 if (BPM>160) 379 { 380 lcd.print("Hypertention"); 381 382 lcd.setCursor(1,1); 383 lcd.print("BPM: "); 384 lcd.setCursor(5,1); 385 386 lcd.print(BPM); 387 delay(5000); 388 lcd.clear(); 389 for(int x=0;x<Steps;x++) 390 391 { 392 switch(cstep) 393 { 394 case 0: 395 digitalWrite(IN1, LOW); 396 397 digitalWrite(IN2, LOW); 398 digitalWrite(IN3, LOW); 399 digitalWrite(IN4, 400 HIGH); 401 break; 402 case 1: 403 digitalWrite(IN1, LOW); 404 digitalWrite(IN2, 405 LOW); 406 digitalWrite(IN3, HIGH); 407 digitalWrite(IN4, HIGH); 408 break; 409 410 case 2: 411 digitalWrite(IN1, LOW); 412 digitalWrite(IN2, LOW); 413 414 digitalWrite(IN3, HIGH); 415 digitalWrite(IN4, LOW); 416 break; 417 418 case 3: 419 digitalWrite(IN1, LOW); 420 digitalWrite(IN2, HIGH); 421 422 digitalWrite(IN3, HIGH); 423 digitalWrite(IN4, LOW); 424 break; 425 426 case 4: 427 digitalWrite(IN1, LOW); 428 digitalWrite(IN2, HIGH); 429 430 digitalWrite(IN3, LOW); 431 digitalWrite(IN4, LOW); 432 break; 433 case 434 5: 435 digitalWrite(IN1, HIGH); 436 digitalWrite(IN2, HIGH); 437 digitalWrite(IN3, 438 LOW); 439 digitalWrite(IN4, LOW); 440 break; 441 case 6: 442 digitalWrite(IN1, 443 HIGH); 444 digitalWrite(IN2, LOW); 445 digitalWrite(IN3, LOW); 446 digitalWrite(IN4, 447 LOW); 448 break; 449 case 7: 450 digitalWrite(IN1, HIGH); 451 digitalWrite(IN2, 452 LOW); 453 digitalWrite(IN3, LOW); 454 digitalWrite(IN4, HIGH); 455 break; 456 457 default: 458 digitalWrite(IN1, LOW); 459 digitalWrite(IN2, LOW); 460 461 digitalWrite(IN3, LOW); 462 digitalWrite(IN4, LOW); 463 break; 464 } 465 466 467 cstep=cstep+1; 468 if(cstep==8) 469 {cstep=0;} 470 471 delayMicroseconds(2500); 472 473 474 } 475} 476} 477void state() 478{ 479 if (BPM > 60 & BPM < 74){ 480 lcd.print("VERY-GOOD"); 481 482 lcd.setCursor(1,1); 483 lcd.print("BPM: "); 484 lcd.setCursor(5,1); 485 486 lcd.print(BPM); 487 delay(3000); 488 lcd.clear(); 489 } 490}
Downloadable files
picture1_7ADZYkRd0M.png
picture1_7ADZYkRd0M.png
Comments
Only logged in users can leave comments