Test program for a Max30102 heartrate sensor on a STM32L476RG specific board ENSMM

Dependencies:   mbed

These two pictures show how to connect the Mheuve Sensor to the ST-Link debugger (don't forget to disable ST-link jumpers and JP5 on the board! ):

https://os.mbed.com/media/uploads/jimbaud/1611739514454.jpghttps://os.mbed.com/media/uploads/jimbaud/1611739514453.jpg

These two pictures show how to connect the Mheuve Sensor TX RX to the ST-Link debugger (don't forget to cross TX and RX, it means Mheuve sensor TX on ST-Link RX and ST-Link TX on Mheuve sensor RX ):

https://os.mbed.com/media/uploads/jimbaud/1611739514450.jpg https://os.mbed.com/media/uploads/jimbaud/1611739514452.jpg

The Mheuve sensor board needs to be powered by an external battery.

The result appears on the terminal, speed config is 115200 bds.

https://os.mbed.com/media/uploads/jimbaud/terminal.jpg

Revision:
0:346a7fa07998
Child:
3:7c0fb55eb3ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 20 21:46:06 2016 +0000
@@ -0,0 +1,224 @@
+/** \file main.cpp ******************************************************
+*
+* Project: MAXREFDES117#
+* Filename: main.cpp
+* Description: This module contains the Main application for the MAXREFDES117 example program.
+*
+* Revision History:
+*\n 1-18-2016 Rev 01.00 GL Initial release.
+*\n
+*
+* --------------------------------------------------------------------
+*
+* This code follows the following naming conventions:
+*
+*\n char              ch_pmod_value
+*\n char (array)      s_pmod_s_string[16]
+*\n float             f_pmod_value
+*\n int32_t           n_pmod_value
+*\n int32_t (array)   an_pmod_value[16]
+*\n int16_t           w_pmod_value
+*\n int16_t (array)   aw_pmod_value[16]
+*\n uint16_t          uw_pmod_value
+*\n uint16_t (array)  auw_pmod_value[16]
+*\n uint8_t           uch_pmod_value
+*\n uint8_t (array)   auch_pmod_buffer[16]
+*\n uint32_t          un_pmod_value
+*\n int32_t *         pn_pmod_value
+*
+* ------------------------------------------------------------------------- */
+/*******************************************************************************
+* Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+/*!\mainpage Main Page
+*
+* \section intro_sec Introduction
+*
+* This is the code documentation for the MAXREFDES117# subsystem reference design.
+* \n
+* \n The Files page contains the File List page and the Globals page.
+* \n
+* \n The Globals page contains the Functions, Variables, and Macros sub-pages.
+*
+* \image html MAXREFDES117_Block_Diagram.png "MAXREFDES117# System Block Diagram"
+* \n
+* \image html MAXREFDES117_firmware_Flowchart.png "MAXREFDES117# Firmware Flowchart"
+*
+*/
+#include "mbed.h"
+#include "main.h"
+#include "algorithm.h"
+#include "MAX30102.h"
+
+#define MAX_BRIGHTNESS 255
+
+uint32_t un_ir_buffer[500]; //IR LED sensor data
+int32_t n_ir_buffer_length;    //data length
+uint32_t un_red_buffer[500];    //Red LED sensor data
+int32_t n_sp02; //SPO2 value
+int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
+int32_t n_heart_rate;   //heart rate value
+int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
+uint8_t uch_dummy;
+
+Serial pc(USBTX, USBRX);    //initializes the serial port
+#ifdef TARGET_KL25Z 
+PwmOut led(PTB18);  //initializes the pwm output that connects to the on board LED
+DigitalIn INT(PTD1);  //pin PTD1 connects to the interrupt output pin of the MAX30102
+#endif
+#ifdef TARGET_K64F
+DigitalIn INT(PTD1);  //pin PTD1 connects to the interrupt output pin of the MAX30102
+#endif
+#ifdef TARGET_MAX32600MBED
+PwmOut led(LED_RED);    //initializes the pwm output that connects to the on board LED
+DigitalIn INT(P2_0);  //pin P20 connects to the interrupt output pin of the MAX30102
+#endif
+
+// the setup routine runs once when you press reset:
+int main() { 
+    uint32_t un_min, un_max, un_prev_data;  //variables to calculate the on-board LED brightness that reflects the heartbeats
+    int i;
+    int32_t n_brightness;
+    float f_temp;
+    
+    maxim_max30102_reset(); //resets the MAX30102
+    // initialize serial communication at 115200 bits per second:
+    pc.baud(115200);
+    pc.format(8,SerialBase::None,1);
+    wait(1);
+    
+    //read and clear status register
+    maxim_max30102_read_reg(0,&uch_dummy);
+    
+    //wait until the user presses a key
+    while(pc.readable()==0)
+    {
+        pc.printf("%c[2J",27);  //clear terminal program screen
+        pc.printf("Press any key to start conversion\n\r");
+        wait(1);
+    }
+    uch_dummy=getchar();
+    
+    maxim_max30102_init();  //initializes the MAX30102
+        
+        
+    n_brightness=0;
+    un_min=0x3FFFF;
+    un_max=0;
+  
+    n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
+    
+    //read the first 500 samples, and determine the signal range
+    for(i=0;i<n_ir_buffer_length;i++)
+    {
+        while(INT.read()==1);   //wait until the interrupt pin asserts
+        
+        maxim_max30102_read_fifo((un_red_buffer+i), (un_ir_buffer+i));  //read from MAX30102 FIFO
+            
+        if(un_min>un_red_buffer[i])
+            un_min=un_red_buffer[i];    //update signal min
+        if(un_max<un_red_buffer[i])
+            un_max=un_red_buffer[i];    //update signal max
+        pc.printf("red=");
+        pc.printf("%i", un_red_buffer[i]);
+        pc.printf(", ir=");
+        pc.printf("%i\n\r", un_ir_buffer[i]);
+    }
+    un_prev_data=un_red_buffer[i];
+    
+    
+    //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
+    maxim_heart_rate_and_oxygen_saturation(un_ir_buffer, n_ir_buffer_length, un_red_buffer ,  &n_sp02, &ch_spo2_valid , &n_heart_rate , &ch_hr_valid); 
+    
+    //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
+    while(1)
+    {
+        i=0;
+        un_min=0x3FFFF;
+        un_max=0;
+        
+        //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
+        for(i=100;i<500;i++)
+        {
+            un_red_buffer[i-100]=un_red_buffer[i];
+            un_ir_buffer[i-100]=un_ir_buffer[i];
+            
+            //update the signal min and max
+            if(un_min>un_red_buffer[i])
+            un_min=un_red_buffer[i];
+            if(un_max<un_red_buffer[i])
+            un_max=un_red_buffer[i];
+        }
+        
+        //take 100 sets of samples before calculating the heart rate.
+        for(i=400;i<500;i++)
+        {
+            un_prev_data=un_red_buffer[i-1];
+            while(INT.read()==1);
+            maxim_max30102_read_fifo((un_red_buffer+i), (un_ir_buffer+i));
+        
+            if(un_red_buffer[i]>un_prev_data)
+            {
+                f_temp=un_red_buffer[i]-un_prev_data;
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness-=(int)f_temp;
+                if(n_brightness<0)
+                    n_brightness=0;
+            }
+            else
+            {
+                f_temp=un_prev_data-un_red_buffer[i];
+                f_temp/=(un_max-un_min);
+                f_temp*=MAX_BRIGHTNESS;
+                n_brightness+=(int)f_temp;
+                if(n_brightness>MAX_BRIGHTNESS)
+                    n_brightness=MAX_BRIGHTNESS;
+            }
+#if defined(TARGET_KL25Z) || defined(TARGET_MAX32600MBED)
+            led.write(1-(float)n_brightness/256);
+#endif
+            //send samples and calculation result to terminal program through UART
+            pc.printf("red=");
+            pc.printf("%i",un_red_buffer[i]);
+            pc.printf(", ir=");
+            pc.printf("%i", un_ir_buffer[i]);
+            pc.printf(", HR=%i, ",n_heart_rate); 
+            pc.printf("HRvalid=%i, ",ch_hr_valid);
+            pc.printf("SpO2=%i, ",n_sp02);
+            pc.printf("SPO2Valid=%i\n\r",ch_spo2_valid);
+        }
+        maxim_heart_rate_and_oxygen_saturation(un_ir_buffer, n_ir_buffer_length, un_red_buffer ,  &n_sp02, &ch_spo2_valid , &n_heart_rate , &ch_hr_valid); 
+
+    }
+}
+ 
\ No newline at end of file