|
#include "struct_all.h"
#include "delay.h"
#include "sys.h"
#include "usart1_dma.h"
#include "algorithm.h"
#include "max30102.h"
#include "myiic.h"
#include "key.h"
#define MAX_BRIGHTNESS 255
uint32_t aun_ir_buffer[500]; //infrared LED sensor data
uint32_t aun_red_buffer[500]; //red LED sensor data
int32_t n_ir_buffer_length; //data length
float n_spo2; //SPO2 value
int8_t ch_spo2_valid; //indicator to show if the SPO2 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;
int32_t hr_buf[16];
int32_t hrSum;
int32_t hrAvg;
float spo2_buf[16];
float spo2Sum;
float spo2Avg;
int32_t spo2BuffFilled;
int32_t hrBuffFilled;
int32_t hrValidCnt = 0;
int32_t spo2ValidCnt = 0;
int32_t hrThrowOutSamp = 0;
int32_t spo2ThrowOutSamp = 0;
int32_t spo2Timeout = 0;
int32_t hrTimeout = 0;
void Send_To_PC( int rate, float spo2 );
void Send_To_PC2( unsigned int red, unsigned int ir);
void Send_To_Robot( unsigned int rate, float spo2 );
void loop(void);
void gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設置成上拉輸入
GPIO_Init(GPIOB, &GPIO_InitStructure);//
}
int main(void)
{
delay_init(); //延時函數初始化
NVIC_Configuration();
USART1_DMA_Init(115200); //PA9:TX PA10:RX 接WIFI模塊 與手機相連發送狀態數據
gpio_init(); //實際是 max30102的中斷線
bsp_InitI2C();
maxim_max30102_reset(); //resets the MAX30102
maxim_max30102_read_reg(REG_INTR_STATUS_1, &uch_dummy); //Reads/clears the interrupt status register
maxim_max30102_init(); //initialize the MAX30102
while(1)
{
loop();
}
}
// the loop routine runs over and over again forever:
void loop(void)
{
uint32_t un_min, un_max, un_prev_data, un_brightness; //variables to calculate the on-board LED brightness that reflects the heartbeats
int32_t i;
float f_temp;
un_brightness = 0;
un_min = 0x3FFFF;
un_max = 0;
n_ir_buffer_length = 150; //buffer length of 150 stores 3 seconds of samples running at 50sps 150的緩沖區長度存儲了以50sps運行的3秒的樣本
//read the first 150 samples, and determine the signal range
for(i = 0; i < n_ir_buffer_length; i++)
{
while(KEY0 == 1); //wait until the interrupt pin asserts
maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i)); //read from MAX30102 FIFO
if(un_min > aun_red_buffer[ i])
un_min = aun_red_buffer[ i]; //update signal min
if(un_max < aun_red_buffer[ i])
un_max = aun_red_buffer[ i]; //update signal max
}
un_prev_data = aun_red_buffer[ i];
//calculate heart rate and SpO2 after first 150 samples (first 3 seconds of samples)
maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
//Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second 連續從MAX30102取樣。心率和SpO2每1秒計算一次
while(1)
{
i = 0;
un_min = 0x3FFFF;
un_max = 0;
//將前100組樣本轉儲到內存中,并將最后400組樣本移到頂部
for(i = 100; i < 500; i++)
{
aun_red_buffer[i - 100] = aun_red_buffer[ i];
aun_ir_buffer[i - 100] = aun_ir_buffer[ i];
//update the signal min and max 更新信號的最小值和最大值
if(un_min > aun_red_buffer[ i])
un_min = aun_red_buffer[ i];
if(un_max < aun_red_buffer[ i])
un_max = aun_red_buffer[ i];
}
//計算心率之前取100組樣本
for(i = 400; i < 500; i++)
{
un_prev_data = aun_red_buffer[i - 1];
while(KEY0 == 1);
maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i));
//calculate the brightness of the LED 計算LED的亮度
if(aun_red_buffer[ i] > un_prev_data)
{
f_temp = aun_red_buffer[ i] - un_prev_data;
f_temp /= (un_max - un_min);
f_temp *= MAX_BRIGHTNESS;
f_temp = un_brightness - f_temp;
if(f_temp < 0)
un_brightness = 0;
else
un_brightness = (int)f_temp;
}
else
{
f_temp = un_prev_data - aun_red_buffer[ i];
f_temp /= (un_max - un_min);
f_temp *= MAX_BRIGHTNESS;
un_brightness += (int)f_temp;
if(un_brightness > MAX_BRIGHTNESS)
un_brightness = MAX_BRIGHTNESS;
}
}
maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
if ((ch_hr_valid == 1) && (n_heart_rate < 190) && (n_heart_rate > 40))
{
hrTimeout = 0;
// Throw out up to 1 out of every 5 valid samples if wacky 每5個有效樣本中就有1個是古怪的
if (hrValidCnt == 4)
{
hrThrowOutSamp = 1;
hrValidCnt = 0;
for (i = 12; i < 16; i++)
{
if (n_heart_rate < hr_buf[ i] + 10)
{
hrThrowOutSamp = 0;
hrValidCnt = 4;
}
}
}
else
{
hrValidCnt = hrValidCnt + 1;
}
if (hrThrowOutSamp == 0)
{
// Shift New Sample into buffer
for(i = 0; i < 15; i++)
{
hr_buf[ i] = hr_buf[i + 1];
}
hr_buf[15] = n_heart_rate;
// Update buffer fill value
if (hrBuffFilled < 16)
{
hrBuffFilled = hrBuffFilled + 1;
}
// Take moving average
hrSum = 0;
if (hrBuffFilled < 2)
{
hrAvg = 0;
}
else if (hrBuffFilled < 4)
{
for(i = 14; i < 16; i++)
{
hrSum = hrSum + hr_buf[ i];
}
hrAvg = hrSum >> 1;
}
else if (hrBuffFilled < 8)
{
for(i = 12; i < 16; i++)
{
hrSum = hrSum + hr_buf[ i];
}
hrAvg = hrSum >> 2;
}
else if (hrBuffFilled < 16)
{
for(i = 8; i < 16; i++)
{
hrSum = hrSum + hr_buf[ i];
}
hrAvg = hrSum >> 3;
}
else
{
for(i = 0; i < 16; i++)
{
hrSum = hrSum + hr_buf[ i];
}
hrAvg = hrSum >> 4;
}
}
hrThrowOutSamp = 0;
}
else
{
hrValidCnt = 0;
if (hrTimeout == 4)
{
hrAvg = 0;
hrBuffFilled = 0;
}
else
{
hrTimeout++;
}
}
if ((ch_spo2_valid == 1) && (n_spo2 > 59))
{
spo2Timeout = 0;
// Throw out up to 1 out of every 5 valid samples if wacky
if (spo2ValidCnt == 4)
{
spo2ThrowOutSamp = 1;
spo2ValidCnt = 0;
for (i = 12; i < 16; i++)
{
if (n_spo2 > spo2_buf[ i] - 10)
{
spo2ThrowOutSamp = 0;
spo2ValidCnt = 4;
}
}
}
else
{
spo2ValidCnt = spo2ValidCnt + 1;
}
if (spo2ThrowOutSamp == 0)
{
// Shift New Sample into buffer
for(i = 0; i < 15; i++)
{
spo2_buf[ i] = spo2_buf[i + 1];
}
spo2_buf[15] = n_spo2;
// Update buffer fill value
if (spo2BuffFilled < 16)
{
spo2BuffFilled = spo2BuffFilled + 1;
}
// Take moving average
spo2Sum = 0;
if (spo2BuffFilled < 2)
{
spo2Avg = 0;
}
else if (spo2BuffFilled < 4)
{
for(i = 14; i < 16; i++)
{
spo2Sum = spo2Sum + spo2_buf[ i];
}
spo2Avg = spo2Sum/2.f;
}
else if (spo2BuffFilled < 8)
{
for(i = 12; i < 16; i++)
{
spo2Sum = spo2Sum + spo2_buf[ i];
}
spo2Avg = spo2Sum/4.f;
}
else if (spo2BuffFilled < 16)
{
for(i = 8; i < 16; i++)
{
spo2Sum = spo2Sum + spo2_buf[ i];
}
spo2Avg = spo2Sum /8.f;
}
else
{
for(i = 0; i < 16; i++)
{
spo2Sum = spo2Sum + spo2_buf[ i];
}
spo2Avg = spo2Sum/16.f;
}
}
spo2ThrowOutSamp = 0;
}
else
{
spo2ValidCnt = 0;
if (spo2Timeout == 4)
{
spo2Avg = 0;
spo2BuffFilled = 0;
}
else
{
spo2Timeout++;
}
}
printf("hr:%d\r\n",hrAvg);
printf("spo2Avg:%f\r\n",spo2Avg);
}
}
|
-
-
stm32 max30102.7z
2021-3-31 16:25 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
453.96 KB, 下載次數: 60, 下載積分: 黑幣 -5
評分
-
查看全部評分
|