MAXREFDES117# Code Documentation  V01.00
Heart Rate / SpO2 Monitor
 All Data Structures Files Functions Variables Typedefs Macros Pages
RD117_ARDUINO.ino
Go to the documentation of this file.
1 
30 /*******************************************************************************
31 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
32 *
33 * Permission is hereby granted, free of charge, to any person obtaining a
34 * copy of this software and associated documentation files (the "Software"),
35 * to deal in the Software without restriction, including without limitation
36 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
37 * and/or sell copies of the Software, and to permit persons to whom the
38 * Software is furnished to do so, subject to the following conditions:
39 *
40 * The above copyright notice and this permission notice shall be included
41 * in all copies or substantial portions of the Software.
42 *
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
44 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
47 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
48 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
49 * OTHER DEALINGS IN THE SOFTWARE.
50 *
51 * Except as contained in this notice, the name of Maxim Integrated
52 * Products, Inc. shall not be used except as stated in the Maxim Integrated
53 * Products, Inc. Branding Policy.
54 *
55 * The mere transfer of this software does not imply any licenses
56 * of trade secrets, proprietary technology, copyrights, patents,
57 * trademarks, maskwork rights, or any other form of intellectual
58 * property whatsoever. Maxim Integrated Products, Inc. retains all
59 * ownership rights.
60 *******************************************************************************
61 */
77 #include <Arduino.h>
78 #include "algorithm.h"
79 #include "max30102.h"
80 
81 //if Adafruit Flora development board is chosen, include NeoPixel library and define an NeoPixel object
82 #if defined(ARDUINO_AVR_FLORA8)
83 #include "adafruit_neopixel.h"
84 #define BRIGHTNESS_DIVISOR 8 //to lower the max brightness of the neopixel LED
86 #endif
87 
88 #define MAX_BRIGHTNESS 255
89 
90 #if defined(ARDUINO_AVR_UNO)
91 //Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
92 //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
93 uint16_t aun_ir_buffer[100]; //infrared LED sensor data
94 uint16_t aun_red_buffer[100]; //red LED sensor data
95 #else
96 uint32_t aun_ir_buffer[100]; //infrared LED sensor data
97 uint32_t aun_red_buffer[100]; //red LED sensor data
98 #endif
99 int32_t n_ir_buffer_length; //data length
100 int32_t n_spo2; //SPO2 value
101 int8_t ch_spo2_valid; //indicator to show if the SPO2 calculation is valid
102 int32_t n_heart_rate; //heart rate value
103 int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
104 uint8_t uch_dummy;
105 
106 
107 // the setup routine runs once when you press reset:
108 void setup() {
109 
110 #if defined(ARDUINO_AVR_LILYPAD_USB)
111  pinMode(13, OUTPUT); //LED output pin on Lilypad
112 #endif
113 
114 #if defined(ARDUINO_AVR_FLORA8)
115  //Initialize the LED
116  LED.begin();
117  LED.show();
118 #endif
119 
120  maxim_max30102_reset(); //resets the MAX30102
121  // initialize serial communication at 115200 bits per second:
122  Serial.begin(115200);
123  pinMode(10, INPUT); //pin D10 connects to the interrupt output pin of the MAX30102
124  delay(1000);
125  maxim_max30102_read_reg(REG_INTR_STATUS_1,&uch_dummy); //Reads/clears the interrupt status register
126  while(Serial.available()==0) //wait until user presses a key
127  {
128  Serial.write(27); // ESC command
129  Serial.print(F("[2J")); // clear screen command
130 #if defined(ARDUINO_AVR_LILYPAD_USB)
131  Serial.println(F("Lilypad"));
132 #endif
133 #if defined(ARDUINO_AVR_FLORA8)
134  Serial.println(F("Adafruit Flora"));
135 #endif
136  Serial.println(F("Press any key to start conversion"));
137  delay(1000);
138  }
139  uch_dummy=Serial.read();
140  maxim_max30102_init(); //initialize the MAX30102
141 }
142 
143 // the loop routine runs over and over again forever:
144 void loop() {
145  uint32_t un_min, un_max, un_prev_data, un_brightness; //variables to calculate the on-board LED brightness that reflects the heartbeats
146  int32_t i;
147  float f_temp;
148 
149  un_brightness=0;
150  un_min=0x3FFFF;
151  un_max=0;
152 
153  n_ir_buffer_length=100; //buffer length of 100 stores 4 seconds of samples running at 25sps
154 
155  //read the first 100 samples, and determine the signal range
156  for(i=0;i<n_ir_buffer_length;i++)
157  {
158  while(digitalRead(10)==1); //wait until the interrupt pin asserts
159  maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
160 
161  if(un_min>aun_red_buffer[i])
162  un_min=aun_red_buffer[i]; //update signal min
163  if(un_max<aun_red_buffer[i])
164  un_max=aun_red_buffer[i]; //update signal max
165  Serial.print(F("red="));
166  Serial.print(aun_red_buffer[i], DEC);
167  Serial.print(F(", ir="));
168  Serial.println(aun_ir_buffer[i], DEC);
169  }
170  un_prev_data=aun_red_buffer[i];
171  //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
173 
174  //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second
175  while(1)
176  {
177  i=0;
178  un_min=0x3FFFF;
179  un_max=0;
180 
181  //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
182  for(i=25;i<100;i++)
183  {
185  aun_ir_buffer[i-25]=aun_ir_buffer[i];
186 
187  //update the signal min and max
188  if(un_min>aun_red_buffer[i])
189  un_min=aun_red_buffer[i];
190  if(un_max<aun_red_buffer[i])
191  un_max=aun_red_buffer[i];
192  }
193 
194  //take 25 sets of samples before calculating the heart rate.
195  for(i=75;i<100;i++)
196  {
197  un_prev_data=aun_red_buffer[i-1];
198  while(digitalRead(10)==1);
199  digitalWrite(9, !digitalRead(9));
201 
202  //calculate the brightness of the LED
203  if(aun_red_buffer[i]>un_prev_data)
204  {
205  f_temp=aun_red_buffer[i]-un_prev_data;
206  f_temp/=(un_max-un_min);
207  f_temp*=MAX_BRIGHTNESS;
208  f_temp=un_brightness-f_temp;
209  if(f_temp<0)
210  un_brightness=0;
211  else
212  un_brightness=(int)f_temp;
213  }
214  else
215  {
216  f_temp=un_prev_data-aun_red_buffer[i];
217  f_temp/=(un_max-un_min);
218  f_temp*=MAX_BRIGHTNESS;
219  un_brightness+=(int)f_temp;
220  if(un_brightness>MAX_BRIGHTNESS)
221  un_brightness=MAX_BRIGHTNESS;
222  }
223 #if defined(ARDUINO_AVR_LILYPAD_USB)
224  analogWrite(13, un_brightness);
225 #endif
226 
227 #if defined(ARDUINO_AVR_FLORA8)
228  LED.setPixelColor(0, un_brightness/BRIGHTNESS_DIVISOR, 0, 0);
229  LED.show();
230 #endif
231 
232  //send samples and calculation result to terminal program through UART
233  Serial.print(F("red="));
234  Serial.print(aun_red_buffer[i], DEC);
235  Serial.print(F(", ir="));
236  Serial.print(aun_ir_buffer[i], DEC);
237 
238  Serial.print(F(", HR="));
239  Serial.print(n_heart_rate, DEC);
240 
241  Serial.print(F(", HRvalid="));
242  Serial.print(ch_hr_valid, DEC);
243 
244  Serial.print(F(", SPO2="));
245  Serial.print(n_spo2, DEC);
246 
247  Serial.print(F(", SPO2Valid="));
248  Serial.println(ch_spo2_valid, DEC);
249  }
251  }
252 }
253