这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 第二期-智能手环DIY活动-成果贴(基础任务)

共2条 1/1 1 跳转至

第二期-智能手环DIY活动-成果贴(基础任务)

工程师
2025-08-30 18:12:18     打赏

项目概况:

项目用的主控是ADI公司的MAX78000单片机,具有arm cortex-m4内核与risc-v AI协处理器。板卡还带有音频line-in/out接口,SD卡接口。本次智能手环项目的重点放在

  1. 板载屏幕RGB彩灯,使用GPIO驱动。

  2. oled屏幕驱动,使用硬件IIC接口驱动。

  3. 驱动max30102传感器实现心率与血氧数据的测量,使用硬件IIC接口驱动。


系统框图:

项目硬件框图如下:P2.0, P2.1, P2.2用于驱动R,G,B小灯。0.16与P0.17用于IIC总线SCL,SDA。

image.png

软件流程图:

项目软件流程图如下所示,基于bare-metal模式,比较简单。

image.png

开发关键:

任务1:点亮RGB灯

实现细节参考:第二期-智能手环DIY活动-GPIO点亮LED过程贴  https://forum.eepw.com.cn/thread/394430/1

重点是相关结构体:

    mxc_gpio_cfg_t red_led_pin = {MXC_GPIO2, MXC_GPIO_PIN_0,
    MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH};
    MXC_GPIO_Config(&red_led_pin);

    MXC_GPIO_OutSet(red_led_pin.port, red_led_pin.mask);

任务2:驱动OLED屏幕

实现细节参考:第二期-智能手环DIY活动-屏幕驱动过程贴 https://forum.eepw.com.cn/thread/394423/1

重点是如何调用MAX78000 SDK的IIC接口进行数据发送。


任务3:驱动MAX30102,实现血氧、心率检测并显示

实现重点如下:

复位与配置MAX30102模式:

	Max30102_reset();     //reset max30102
	MAX30102_Config();    //config max30102

实现如下:

uint8_t Max30102_reset(void)
{
	if(max30102_write_reg(REG_MODE_CONFIG, 0x40))
        return 1;
    else
        return 0;    
}


void MAX30102_Config(void)
{
	max30102_write_reg(REG_INTR_ENABLE_1,0xc0); //INTR setting
	max30102_write_reg(REG_INTR_ENABLE_2,0x00);//
	max30102_write_reg(REG_FIFO_WR_PTR,0x00);//FIFO_WR_PTR[4:0]
	max30102_write_reg(REG_OVF_COUNTER,0x00);//OVF_COUNTER[4:0]
	max30102_write_reg(REG_FIFO_RD_PTR,0x00);//FIFO_RD_PTR[4:0]
	
	max30102_write_reg(REG_FIFO_CONFIG,0x0f);//sample avg = 1, fifo rollover=false, fifo almost full = 17
	max30102_write_reg(REG_MODE_CONFIG,0x03);//0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
	max30102_write_reg(REG_SPO2_CONFIG,0x27);	// SPO2_ADC range = 4096nA, SPO2 sample rate (50 Hz), LED pulseWidth (400uS)  
	max30102_write_reg(REG_LED1_PA,0x32);//Choose value for ~ 10mA for LED1
	max30102_write_reg(REG_LED2_PA,0x32);// Choose value for ~ 10mA for LED2
	max30102_write_reg(REG_PILOT_PA,0x7f);// Choose value for ~ 25mA for Pilot LED
}

max30102传感器数据的获取:

void blood_data_update(void)
{
	g_fft_index=0;
	while(g_fft_index < FFT_N)
	{
		while(max30102_read_reg(REG_INTR_STATUS_1)&0x40 )
		{
			max30102_read_fifo();  //read from MAX30102 FIFO2
			if(g_fft_index < FFT_N)
			{
				s1[g_fft_index].real = fifo_red;
				s1[g_fft_index].imag= 0;
				s2[g_fft_index].real = fifo_ir;
				s2[g_fft_index].imag= 0;
				g_fft_index++;
			}
		}
	}
}

提取心率与血氧数据:

void blood_data_translate(void)
{	
	float n_denom;
	uint16_t i;

	float dc_red =0; 
	float dc_ir =0;
	float ac_red =0; 
	float ac_ir =0;
	
	for (i=0 ; i<FFT_N ; i++ ) 
	{
		dc_red += s1[i].real ;
		dc_ir +=  s2[i].real ;
	}
		dc_red =dc_red/FFT_N ;
		dc_ir =dc_ir/FFT_N ;
	for (i=0 ; i<FFT_N ; i++ )  
	{
		s1[i].real =  s1[i].real - dc_red ; 
		s2[i].real =  s2[i].real - dc_ir ; 
	}

	for(i = 1;i < FFT_N-1;i++) 
	{
		n_denom= ( s1[i-1].real + 2*s1[i].real + s1[i+1].real);
		s1[i].real=  n_denom/4.00; 
		
		n_denom= ( s2[i-1].real + 2*s2[i].real + s2[i+1].real);
		s2[i].real=  n_denom/4.00; 			
	}

	for(i = 0;i < FFT_N-8;i++) 
	{
		n_denom= ( s1[i].real+s1[i+1].real+ s1[i+2].real+ s1[i+3].real+ s1[i+4].real+ s1[i+5].real+ s1[i+6].real+ s1[i+7].real);
		s1[i].real=  n_denom/8.00; 
		
		n_denom= ( s2[i].real+s2[i+1].real+ s2[i+2].real+ s2[i+3].real+ s2[i+4].real+ s2[i+5].real+ s2[i+6].real+ s2[i+7].real);
		s2[i].real=  n_denom/8.00; 
		
	}

	g_fft_index = 0;	
	FFT(s1);
	FFT(s2);
	
	for(i = 0;i < FFT_N;i++) 
	{
		s1[i].real=sqrtf(s1[i].real*s1[i].real+s1[i].imag*s1[i].imag);
		s1[i].real=sqrtf(s2[i].real*s2[i].real+s2[i].imag*s2[i].imag);
	}
	for (i=1 ; i<FFT_N ; i++ ) 
	{
		ac_red += s1[i].real ;
		ac_ir +=  s2[i].real ;
	}
	
	for(i = 0;i < 50;i++) 
	{
		if(s1[i].real<=10)
			break;
	}
	
	int s1_max_index = find_max_num_index(s1, 60);
	int s2_max_index = find_max_num_index(s2, 60);

	if(i>=45)
	{
		uint16_t Heart_Rate = 60.00 * SAMPLES_PER_SECOND * s1_max_index / FFT_N;
		heart = Heart_Rate;
		
		float R = (ac_ir*dc_red)/(ac_red*dc_ir);
		float sp02_num = -45.060*R*R+ 30.354 *R + 94.845;
		SpO2 = sp02_num;
		
	}
	else 
	{
		heart = 0;
		SpO2 = 0;
	}
}


演示视频:

项目演示视频发布在B站:https://www.bilibili.com/video/BV1A6hqzzEkG/?vd_source=06b417808f9325071f39e5fd55985221


总结:

项目实现的过程中熟悉了MAX78000的SDK,首次实现了硬件IIC驱动SSD1315屏幕和MAX30102传感器。

在OLED显示遇到困难的时候,参考了论坛网友之前的分享,特此感谢。

整体上完成了基础任务的3个任务,感谢EEPW与得捷提供的机会。


完整代码:

Proj_EEPW_OLED_1.zip


专家
2025-08-31 06:49:26     打赏
2楼

谢谢楼主分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]