stm32项目(7)——基于stm32的智能床的控制与设计

目录

1 .功能设计

2.硬件方案

        1.单片机

2.显示器

3.称重模块

4.心率测量模块

5.蓝牙模块

6.蜂鸣器模块

7.电机及其驱动模块

 8.开关

3.程序设计

1 .功能设计

        本次设计实现的功能:使用称重模块对体重进行测量,将体重数值实时显示在显示屏上;使用心率采集模块,测量用户的实时心率,并将数据显示在显示屏上。可以设定心率阈值,如果数据超出正常范围,进行报警。报警方式:采用蓝牙模块,发送报警信息到用户手机上!心率的采集受开关控制,按键按下时,开启心率采集,按键没有按下,则不采集。另外,系统还有一个受开关控制的电机,按键按下时,电机转动。

      功能完成后的效果如下:

 

       

 演示视频如下;

智能床演示视频1

 

 

智能床演示视频2

2.硬件方案

        1.单片机

        单片机选择正点原子的stm32mini板,板载芯片型号是stm32f103rct6,实物图如下:

 

正点原子Mini板(DFRobot Romeo V2.2) 是一款开源的嵌入式开发板,具有Arduino兼容性,由DFRobot(创客工具领域的知名公司)推出。该开发板基于Atmega328P微控制器,集成了丰富的硬件资源和接口,方便开发者进行快速的原型设计和开发。

主要特点和功能包括:

1. 丰富的接口资源:板载了丰富的接口和硬件资源,包括数字输入/输出口、模拟输入口、PWM输出口、串口、I2C、SPI等,方便连接和控制外部设备。

2. USB接口:通过USB接口可以方便地与计算机进行通信和编程。

3. 电源管理:板载了稳压电路和电源管理模块,可以接受多种电源输入(5V)、并提供电源供应给其他外部设备。

4. 尺寸小巧:正点原子Mini板尺寸小巧,便于嵌入到各种项目中,适合携带和移动应用。

2.显示器

显示器选择TFT液晶屏,实物图如下:

 

        TFT液晶屏(Thin-Film Transistor Liquid Crystal Display)是一种广泛应用于消费电子产品的平面显示技术。它采用薄膜晶体管(TFT)作为驱动元件,可实现高分辨率、高亮度和快速刷新率的图像显示。

        TFT液晶屏的主要特点和优势包括:

        1. 高画质和色彩表现:TFT液晶屏可以实现高分辨率的图像显示,能够呈现细腻、清晰的画面。此外,它还具有广色域和优秀的色彩表现能力,可以呈现生动逼真的图像。

        2. 快速刷新率:TFT液晶屏的刷新率较高,能够实现流畅的视频播放和动画效果。

        3. 视角宽广:TFT液晶屏具有广视角特性,观看角度变化时图像的亮度和对比度变化较小,使得多人同时观看时能够保持较好的显示效果。

        4. 节能省电:TFT液晶屏采用薄膜晶体管作为驱动元件,其工作电流较低,能够省电和减少能源消耗。

        5. 薄型轻便:TFT液晶屏结构简单,整体厚度较薄,使得产品具有较小的尺寸和轻便的特点,有利于便携性和设计创新。

        TFT液晶屏广泛应用于各种电子设备中,包括智能手机、平板电脑、电视、电子显示器、汽车导航系统等。它不仅适用于个人消费电子产品,还被广泛应用于工业控制、医疗设备、广告显示和户外显示等领域。随着技术的不断进步,TFT液晶屏不断提升性能,未来可能会更加薄型、高分辨率和能效更高。

3.称重模块

称重模块选择HX711,实物图:

        HX711是一款集成了24位ADC(模数转换器)的增益放大器芯片。它常用于称重传感器与微控制器之间的连接,通过将称重传感器的模拟信号放大并转换为数字信号,实现精确的重量测量。

        HX711芯片的主要特点和功能包括:

        1. 高精度ADC:HX711芯片内部集成了24位的Σ-Δ(sigma-delta)ADC,能够实现高精度的模拟信号转换。

        2. 可调增益:HX711芯片内部具有可调的增益放大器,支持不同量程下称重传感器的连接,以适应不同应用需求。

        3. 低噪声:HX711芯片具有低噪声设计,能够减少环境和电源的干扰,提高测量的稳定性和准确性。

        4. 内部校准:HX711芯片内部具有自动零点校准和内部参考电压的选项,可以提供更准确的测量结果。

        5. 串行接口:HX711芯片通过串行接口(如SPI)与微控制器进行通信,简化了与外部系统的连接和控制。

        6. 低功耗:HX711芯片在静态状态下具有低功耗特性,适用于功耗敏感的应用场景。

        HX711芯片常用于称重应用,如厨房电子秤、工业称重装置、嵌入式测量系统等。它的高精度和稳定性使得重量测量更加精确可靠。同时,HX711芯片的简单接口设计和丰富的开发资源,方便了开发者的使用和二次开发。

4.心率测量模块

心率测量采用的传感器是MAX30102,实物图:

 

 

        MAX30102是一款集成了心率和血氧饱和度(SpO2)测量功能的模块芯片。它使用光学传感器来非侵入性地监测心率和血氧水平,适用于健康监测、运动追踪、医疗设备等应用领域。

        MAX30102芯片的主要特点和功能包括:

        1. 心率监测:MAX30102芯片通过光学传感器测量皮肤上的血液脉搏信号,可以实时监测心率。

        2. 血氧饱和度(SpO2)监测:MAX30102芯片利用红外LED和红色LED对血液中的血氧水平进行监测,测量结果以SpO2百分比的形式提供。

        3. 光学传感器集成:MAX30102芯片集成了高度集成的光学传感器,包括LED、光电二极管(photodetector)和模拟前端,用于采集光学信号并将其转换为数字信号。

        4. 低功耗:MAX30102芯片具有低功耗特性,适合于便携式设备和可穿戴设备应用。

        5. 灵活的接口和配置选项:MAX30102芯片支持I2C接口进行通信,并提供了丰富的配置选项,如采样速率、增益控制等,以适应不同应用场景的需求。

        6. 简化的算法和数据处理:MAX30102芯片可以提供经过滤波和算法处理后的心率和血氧测量结果,减少了外部处理器的工作量。

        MAX30102芯片广泛应用于各种健康监测和医疗设备中,包括智能手环、智能手表、健康追踪器、医疗传感器等。通过非侵入性的方式,它可以提供关键的生理参数监测,帮助用户实时了解和管理自己的健康状况。

5.蓝牙模块

        蓝牙模块选用HC08,实物图:

        蓝牙模块是一种用于无线通信的设备,能够实现设备之间的短距离数据传输和通信。蓝牙模块通常包含了蓝牙无线通信所需的硬件和软件功能,可以轻松地与其他蓝牙设备进行配对和通信。

        蓝牙模块的主要特点和功能包括:

        1. 无线通信:蓝牙模块通过蓝牙无线技术实现设备之间的数据传输和通信,通常工作在2.4 GHz频段。

        2. 低功耗:蓝牙模块通常具有低功耗特性,适用于电池供电的设备,并能够有效延长电池寿命。

        3. 小型化和集成:蓝牙模块通常具有小尺寸和高度集成的设计,方便嵌入到各种设备中,并与其他硬件模块集成使用。

        4. 通信范围:蓝牙模块通常适用于短距离通信,通信范围一般在几米到几十米之间,最大通信距离取决于模块的功率和环境条件。

6.蜂鸣器模块

        蜂鸣器选择高电平触发的,有源蜂鸣器。

7.电机及其驱动模块

        电机选择最简单的直流电机,二端口。实物图如下:

 

        由于单片机的IO输出电流能力有限,无法直接驱动该直流电机工作,所以还需要使用电机的驱动模块。驱动模块选择L298N,实物图如下:

 8.开关

        开关是使用mini板子上自带的开关。

3.程序设计

接线方式为:

//HX711_SCK---> PA6
//HX711_DOUT---> PA7

//MAX30102  IIC_SCL---> PC11
//MAX30102  IIC_SDA---> PC12
//MAX30102  INT---> PC13

//BEEP--->  PC0

//蓝牙 RX---> PA2
//蓝牙 TX---> PA3
//L298N_IN1--->PA4   L298N_IN2--->PA5
//(L298N需要额外供电)

本次程序的难点是,MAX30102的驱动编写。这里我不详细展开,我们直接给出主函数代码:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "HX711.h"
#include "max30102.h" 
#include "myiic.h"
#include "algorithm.h"
#include "key.h"

//HX711_SCK---> PA6
//HX711_DOUT---> PA7

//MAX30102  IIC_SCL---> PC11
//MAX30102  IIC_SDA---> PC12
//MAX30102  INT---> PC13

//BEEP--->  PC0

//蓝牙 RX---> PA2
//蓝牙 TX---> PA3
//L298N_IN1--->PA4   L298N_IN2--->PA5
//(L298N需要额外供电)

//心率数据
uint32_t aun_ir_buffer[500]; //IR LED sensor data
int32_t n_ir_buffer_length;    //data length
uint32_t aun_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;
//variables to calculate the on-board LED brightness that reflects the heartbeats
uint32_t un_min, un_max, un_prev_data;  
int i;
int32_t n_brightness;
float f_temp;
u8 temp_num=0;
u8 temp[6];
u8 str[100];
u8 dis_hr=0,dis_spo2=0;
u8 SendData[7]="alarm\r\t";       //要发送到串口的报警信息
u16 hr_yuzhi=70;           //心率阈值  超出此范围  则蜂鸣器报警

#define MAX_BRIGHTNESS 255

/**********************************************************************
  * @ 函数名  :获取心率数据
  ********************************************************************/
static void Heart_num(void){
		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++)
		{
				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];
		}
		//take 100 sets of samples before calculating the heart rate.
		for(i=400;i<500;i++)
		{
				un_prev_data=aun_red_buffer[i-1];
				while(MAX30102_INT==1);
				max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
	aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
	aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
		
				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;
						n_brightness-=(int)f_temp;
						if(n_brightness<0)
								n_brightness=0;
				}
				else
				{
						f_temp=un_prev_data-aun_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;
				}
			//send samples and calculation result to terminal program through UART
		if(ch_hr_valid == 1 && n_heart_rate<120)//**/ ch_hr_valid == 1 && ch_spo2_valid ==1 && n_heart_rate<120 && n_sp02<101
		{
			dis_hr = n_heart_rate;
			dis_spo2 = n_sp02;
		}
		else
		{
			dis_hr = 0;
			dis_spo2 = 0;
		}

		}
      maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
}

 int main(void)
 { 
	 
	
	delay_init();	    	 //延时函数初始化	  
	uart_init(9600);	 	//串口初始化为9600
   USART2_init(9600);			//串口2初始化函数
	LED_Init();		  		//初始化与LED连接的硬件接口
 	LCD_Init();
   KEY_Init();          	//初始化与按键连接的硬件接口
   BEEP_Init();            //蜂鸣器初始化
   Init_HX711pin();     //HX711管脚初始化
	 
   Get_Maopi();				//称毛皮重量
	delay_ms(1000);
	delay_ms(1000);
	Get_Maopi();				//重新获取毛皮重量
       
	max30102_init();  //初始化max30102
   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(MAX30102_INT==1);   //wait until the interrupt pin asserts
        
		max30102_FIFO_ReadBytes(REG_FIFO_DATA,temp);
		aun_red_buffer[i] =  (long)((long)((long)temp[0]&0x03)<<16) | (long)temp[1]<<8 | (long)temp[2];    // Combine values to get the actual number
		aun_ir_buffer[i] = (long)((long)((long)temp[3] & 0x03)<<16) |(long)temp[4]<<8 | (long)temp[5];   // Combine values to get the actual number
            
        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 500 samples (first 5 seconds of samples)
   maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid); 
    
   POINT_COLOR=RED;
    LCD_ShowString(30,100,200,16,16,"heart_rate:");
    LCD_ShowString(30,120,200,16,16,"heart_rate_yuzhi:");
    LCD_ShowxNum(160,120,hr_yuzhi,4,16,0);//显示心率阈值
    
	//sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将LCD ID打印到lcd_id数组。				 	
  	while(1) 
	{		 
		Get_Weight();
      LCD_ShowxNum(30,30,Weight_Shiwu,4,16,0);//显示重量  
      LCD_ShowString(65,30,200,16,16,"g");	      
      
		LCD_ShowString(30,60,200,24,24,"Mini STM32 ^_^");	
		
      if(KEY0==0)    
      {
         Heart_num();                 //获取数据
        // BEEP=1;
        
      }
      else
      {
         n_heart_rate=0;
        // BEEP=0;
      }
      
      if(KEY1==0)       //K1按下  电机转
      {
         IN1=1;
         IN2=0;
         BEEP=1;
      }
      else           //否则 不转
      {
          IN1=0;
          IN2=0;
          BEEP=0;
      }
      
      if( n_heart_rate<120)
      {
          LCD_ShowxNum(110,100,n_heart_rate,4,16,0);//显示心率
          if(n_heart_rate>hr_yuzhi)    //心率大于阈值
          {
            BEEP=1;     //报警
         for(i=0;i<7;i++)         //向手机发送报警信息
         {
            while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)	;	/* Loop until the end of transmission */
            USART_SendData(USART2,SendData[i]);
         }
          }
          else
          {
            BEEP=0;
          }
      }
      
		LED0=!LED0;	 
		delay_ms(100);	
	} 
}

 

文件工程截图:

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值