目录

一、项目概述

二、实现功能(功能详解、清单、演示视频)

1、功能详解:

2、项目清单:

3、演示视频:

三、硬件介绍

1、原理图:

2、PCB硬件设计:

四、程序设计

五、项目成品效果

六、项目总结

七、包含资料



一、项目概述

智能药盒 是一款以 STM32F103C8T6 为主控核心的嵌入式护理设备,专为需长期服药的慢病患者或老年人设计。系统集成了 DS1302实时时钟 与 OLED 屏幕 实现时间显示与菜单交互,用户可通过按键手动设置当前时间及 5组独立定时任务,每组定时均可单独开启或关闭。

在触发服药时刻,JR6001语音模块 通过扬声器播报语音提醒,同时 光电红外传感器 实时监测药盒盖状态——一旦检测到用户取药动作,播报立即停止。DHT11 持续采集药盒内部温湿度,HX711 配合称重传感器动态追踪药品余量;当药品重量归零时,有源蜂鸣器 发出急促报警,提示用户及时补药。

借助 BT04A蓝牙模块,手机APP(如“蓝牙调试助手”或自研小程序)可远程查看温湿度、药品剩余量及当前定时配置,并支持在线修改定时时间与开关状态,实现“本地执行 + 远程监控”的闭环管理。整个系统采用 USB 5V 供电,结构紧凑,成本可控,适用于家庭、养老机构或社区医疗场景。

二、实现功能

  • 1、功能详解:

  • 主控单元:采用STM32F103C8T6单片机作为核心控制

  • 时间显示:支持实时时间显示与手动设置

  • 定时提醒:可设置5组独立定时,每组均可单独开启或关闭

  • 语音播报:定时到点时扬声器播报服药提醒,检测到取药动作后自动停止播报

  • 监测功能:DHT11检测药盒温湿度,HX711称重模块检测药品余量,光电红外传感器检测取药状态

  • 缺药报警:药品重量归零时蜂鸣器发出报警提示

  • APP控制:通过蓝牙连接手机APP,可查看环境数据并远程设置定时时间与开关

  • 2、项目清单:

  • STM32F103C8T6最小系统板

  • OLED屏幕(0.96)

  • DHT11温湿度传感器

  • 光电红外传感器

  • HX711称重模块

  • JR6001语音模块

  • BT04A蓝牙模块

  • 有源蜂鸣器

  • 3、演示视频:

  • 哔哩哔哩视频链接点击观看: https://www.bilibili.com/video/BV1niKM6GEe3/?share_source=copy_web&vd_source=f4437c8e4429101e5bf1054c39d5474f

三、硬件介绍

  • PCB硬件设计:

四、程序设计

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "control.h"
#include "adc.h"
#include "key.h"
#include "timer.h"
#include "oled.h"
#include "rtc.h"
#include "dht11.h"
#include "IoData.h"
#include "hx711.h"
#include "uln2003.h"
#include "esp8266.h"
#include "aliyun.h"

/****  数据变量  ****/
DATES Timed_One;
DATES Timed_Two;
DATES Timed_Three;
DATES Timed_Four;
DATES Timed_Five;
DATES Timed_Init;

int timeone_flag = 0;		//定时提醒一开关
int timetwo_flag = 0;		//定时提醒二
int timethree_flag = 0;		//定时提醒三
int timeFour_flag = 0;	
int timeFive_flag = 0;	

int rem_time_one = 0;  
int rem_time_two= 0;  
int rem_time_three = 0;  
int rem_time_four= 0;  
int rem_time_five= 0;  

int remind_flag = 0;		//提醒开关

int remind_time = 0;		//提醒时间

/****  菜单变量  ****/
uint8_t keu_num = 0;		//按键赋值
uint8_t page_num = 1;		//页面ID
uint8_t option = 0;			//阈值选项
uint8_t net_flag    = 1;

/****  功能函数声明  ****/
void get_all_sensor_data();		//传感器数据采集
void Sensor_Data_Handle();		//不同模式下控制效果
void Key_event_handle(void);	//按键功能函数

void OLED_Show_FirstPage();		//第一屏显示内容
void OLED_Show_SecondPage();	//第二屏显示内容
void OLED_Show_ThirdPage();		//第三屏显示内容
void OLED_Show_FourPage();		//第四屏显示内容
void net_page();

int main(void)
{

	u8 err=0;
	SystemInit();
	delay_init();				//系统延时函数初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//改变指定管脚的映射,JTAG-DP 禁用 + SW-DP 使能
	OLED_Init();				//屏幕初始化
	uart3_init(115200);			//串口3初始化,波特率115200
	uart1_init(9600);			//串口1初始化,波特率9600
	uart2_init(9600);			//串口2初始化,波特率9600
	DHT11_Init();				//DHT11温湿度初始化
	KEY_Init();					//按键初始化
	TIME_Config();				//定时器初始化
	Control_Init();				//蜂鸣器初始化
	IoData_Init();
	BEEP=0;
	Uln2003_Init();

    /* 初始化RTC */
    if (RTC_Init() == SUCCESS)
    {
		OLED_Clear(); 
		OLED_ShowString(16*0,48,"RTC CRY OK!",16,1); 
		
		OLED_Refresh();
        delay_ms(1000);
		OLED_Clear(); 
        /* 首次使用或需要重置时间时,设置初始时间(2026年6月19日 10:30:00) */
        
//        RTC_Set_Time(10, 30, 0);
//		RTC_Set_Date(26, 6, 19);
    }else{
		OLED_Clear(); 
		OLED_ShowString(16*0,48,"RTC CRY ERR!",16,1); 
		OLED_Refresh();
		delay_ms(3000);
		OLED_Clear(); 
    }
	HX711_Init();		//称重模块初始化
	reset = HX711_GetData();	//去皮置零
	net_page();
	while(net_flag){
		keu_num = KEY_Scan(0);		//按键扫描赋值
		if(keu_num==1){net_flag=0;}
		else if(keu_num==2){net_flag=0;ESP8266_Init();}
	}
	OLED_Clear();
	while(1)	
	{	
		Key_event_handle();			//按键监测
		if(Time_Period[1]>1000)		//Time_Period[1] 在定时器中累加
		{
			RTC_Get_Date(&SysTime.year, &SysTime.mon, &SysTime.day);
			RTC_Get_Time(&SysTime.hour, &SysTime.min, &SysTime.sec);
			get_all_sensor_data();	//传感器数据采集
            Mqtt_Publiash_Aliyun();
            if((int)weight==0){
                BEEP=1;delay_ms(100);BEEP=0;
            }	//药物缺少提醒
            
			Time_Period[1] = 0;
		}	        
		if(page_num == 1){			//屏幕更新
			OLED_Show_FirstPage();
		}else if(page_num == 2){
			OLED_Show_SecondPage();
		}else if(page_num == 3){
			OLED_Show_ThirdPage();
		}else if(page_num == 4){
			OLED_Show_FourPage();
		}
		Sensor_Data_Handle();		//数据处理
	}
}

void Key_event_handle(void)
{
	keu_num = KEY_Scan(1);		//按键扫描赋值
	switch(keu_num)
	{
		case 1:		//按键1按下
			if(page_num==1){
				page_num=2;option=0;
				OLED_Clear();
			}else if(page_num==2){
				page_num = 3;option=0;
				OLED_Clear();
			}else if(page_num==3){
				Timed_Init.year=SysTime.year;
				Timed_Init.mon=SysTime.mon;
				Timed_Init.day=SysTime.day;
				Timed_Init.hour=SysTime.hour;
				Timed_Init.min=SysTime.min;
				Timed_Init.sec=SysTime.sec;
				page_num = 4;option=0;
				OLED_Clear();
			}else if(page_num==4){
				if(option>0){
					RTC_Set_Time(Timed_Init.hour, Timed_Init.min, Timed_Init.sec);
					RTC_Set_Date(Timed_Init.year%100, Timed_Init.mon, Timed_Init.day);
				}
				page_num = 1;option=0;
				OLED_Clear();
			}
			break;
		case 2:		//按键2按下
			if(page_num==2){
				option++;
				if(option==10)option=0;
				OLED_Show_SecondPage();
			}else if(page_num==3){
				option++;
				if(option==7)option=0;
				OLED_Show_ThirdPage();
			}else if(page_num==4){
				option++;
				if(option==7)option=0;
				OLED_Show_FourPage();
			}
			break;
		case 3:		//按键3按下
			if(page_num==2){
				if(option==1){
					Timed_One.hour++;
					if(Timed_One.hour>23)Timed_One.hour=0;
				}else if(option==2){
					Timed_One.min++;
					if(Timed_One.min>59)Timed_One.min=0;
				}else if(option==3){
					timeone_flag = 1;
				}else if(option==4){
					Timed_Two.hour++;
					if(Timed_Two.hour>23)Timed_Two.hour=0;
				}else if(option==5){
					Timed_Two.min++;
					if(Timed_Two.min>59)Timed_Two.min=0;
				}else if(option==6){
					timetwo_flag = 1;
				}else if(option==7){
					Timed_Three.hour++;
					if(Timed_Three.hour>23)Timed_Three.hour=0;
				}else if(option==8){
					Timed_Three.min++;
					if(Timed_Three.min>59)Timed_Three.min=0;
				}else if(option==9){
					timethree_flag = 1;
				}
		
			}else if(page_num==3){
				if(option==1){
					Timed_Four.hour++;
					if(Timed_Four.hour>23)Timed_Four.hour=0;
				}else if(option==2){
					Timed_Four.min++;
					if(Timed_Four.min>59)Timed_Four.min=0;
				}else if(option==3){
					timeFour_flag = 1;
				}else if(option==4){
					Timed_Five.hour++;
					if(Timed_Five.hour>23)Timed_Five.hour=0;
				}else if(option==5){
					Timed_Five.min++;
					if(Timed_Five.min>59)Timed_Five.min=0;
				}else if(option==6){
					timeFive_flag = 1;
				}
					
			}else if(page_num==4){
				if(option==1)Timed_Init.year++;
				else if(option==2)Timed_Init.mon++;
				else if(option==3)Timed_Init.day++;
				else if(option==4)Timed_Init.hour++;
				else if(option==5)Timed_Init.min++;
				else if(option==6)Timed_Init.sec++;
		
			}else if(page_num==1){
//				box_flag = 0;
			}
			break;
		case 4:		//按键4按下

			if(page_num==2){
				if(option==1){
					Timed_One.hour--;
					if(Timed_One.hour>23)Timed_One.hour=0;
				}else if(option==2){
					Timed_One.min--;
					if(Timed_One.min>59)Timed_One.min=0;
				}else if(option==3){
					timeone_flag = 0;
				}else if(option==4){
					Timed_Two.hour--;
					if(Timed_Two.hour>23)Timed_Two.hour=0;
				}else if(option==5){
					Timed_Two.min--;
					if(Timed_Two.min>59)Timed_Two.min=0;
				}else if(option==6){
					timetwo_flag = 0;
				}else if(option==7){
					Timed_Three.hour--;
					if(Timed_Three.hour>23)Timed_Three.hour=0;
				}else if(option==8){
					Timed_Three.min--;
					if(Timed_Three.min>59)Timed_Three.min=0;
				}else if(option==9){
					timethree_flag = 0;
				}
		
			}else if(page_num==3){
				if(option==1){
					Timed_Four.hour--;
					if(Timed_Four.hour>23)Timed_Four.hour=0;
				}else if(option==2){
					Timed_Four.min--;
					if(Timed_Four.min>59)Timed_Four.min=0;
				}else if(option==3){
					timeFour_flag = 0;
				}else if(option==4){
					Timed_Five.hour--;
					if(Timed_Five.hour>23)Timed_Five.hour=0;
				}else if(option==5){
					Timed_Five.min--;
					if(Timed_Five.min>59)Timed_Five.min=0;
				}else if(option==6){
					timeFive_flag = 0;
				}
					
			}else if(page_num==4){
				if(option==1)Timed_Init.year--;
				else if(option==2)Timed_Init.mon--;
				else if(option==3)Timed_Init.day--;
				else if(option==4)Timed_Init.hour--;
				else if(option==5)Timed_Init.min--;
				else if(option==6)Timed_Init.sec--;
		
			}else if(page_num==1){
//				box_flag = 0;
			}
			break;
		}
}

void get_all_sensor_data()
{
	DHT11_Read_Data(&temp,&hum);
	Get_Body_Value(&body_status);
	Get_HX711_Data();
}


void Sensor_Data_Handle()
{
	//定时提醒一打开
	if(timeone_flag==1){
		if(SysTime.hour==Timed_One.hour&&SysTime.min==Timed_One.min&&SysTime.sec==0){
			if(remind_flag==0){
                remind_flag=1;
            }
		}
	}
	//定时提醒二打开
	if(timetwo_flag==1){
		if(SysTime.hour==Timed_Two.hour&&SysTime.min==Timed_Two.min&&SysTime.sec==0){
			if(remind_flag==0){
                remind_flag=1;
            }
		}
	}
	//定时提醒三打开
	if(timethree_flag==1){
		if(SysTime.hour==Timed_Three.hour&&SysTime.min==Timed_Three.min&&SysTime.sec==0){
			if(remind_flag==0){
                remind_flag=1;
            }
		}
	}
	//定时提醒四打开
	if(timeFour_flag==1){
		if(SysTime.hour==Timed_Four.hour&&SysTime.min==Timed_Four.min&&SysTime.sec==0){
			if(remind_flag==0){
                remind_flag=1;
            }
		}
	}
	//定时提醒五打开
	if(timeFive_flag==1){
		if(SysTime.hour==Timed_Five.hour&&SysTime.min==Timed_Five.min&&SysTime.sec==0){
			if(remind_flag==0){
                remind_flag=1;
            }
		}
	}
    
	if(remind_flag==1){
        remind_time++;
        if(remind_time>=100){
            remind_time=0;
            U2_SendBuff(sound2_buf,6);
            printf("qqqqqqqqqq\r\n");
        }
	}else{
        remind_time = 99;
    }
	
	if(body_status==1){
		if(remind_flag==1)remind_flag=0;
	}

}

// 温(0) 湿(1) 度(2) 水(3) 位(4) 重(5) 量(6) 模(7) 式(8) 自(9) 手(10) 动(11) 光(12) 照(13) ℃(14) 阈(15)
// 值(16) 设(17) 置(18) 投(19) 食(20) 中(21) 时(22) 间(23) 一(24) 二(25) 三(26) 开(27) 关(28)
// 杯(29) 盖(30) 正(31) 常(32) 偏(33) 低(34) 开(35) 启(36) 关(37) 闭(38)
// 上(39) 下(40) 限(41) 系(42) 统(43) 时(44) 间(45)
void OLED_Show_FirstPage()
{
	OLED_ShowNum(16*4,0,SysTime.year%100,2,16,1);		//显示的系统时间"年"
	OLED_ShowChar(16*5,0,'-',16,1);					
	OLED_ShowNum(16*5+8,0,SysTime.mon,2,16,1);			//显示的系统时间"月"
	OLED_ShowChar(16*6+8,0,'-',16,1);
	OLED_ShowNum(16*7,0,SysTime.day,2,16,1);			//显示的系统时间"日"
	
	OLED_ShowNum(16*4,16,SysTime.hour,2,16,1);			//显示的系统时间"小时"
	OLED_ShowChar(16*5,16,':',16,1);
	OLED_ShowNum(16*5+8,16,SysTime.min,2,16,1);			//显示的系统时间"分钟"
	OLED_ShowChar(16*6+8,16,':',16,1);
	OLED_ShowNum(16*7,16,SysTime.sec,2,16,1);			////显示的系统时间"秒"


	OLED_ShowString(16*0,0,"T:",16,1);	
	OLED_ShowNum(16*1,0,temp,2,16,1);		//	temp
	OLED_ShowChinese(16*2,0,14,16,1);
	

	OLED_ShowString(16*0,16*1,"H:",16,1);
	OLED_ShowNum(16*1,16*1,hum,2,16,1);		//	temp1
	OLED_ShowString(16*2,16*1,"%RH",16,1);

	OLED_ShowChinese(16*0,16*2,55,16,1);			//药盒重量
	OLED_ShowChinese(16*1,16*2,56,16,1);
	OLED_ShowChinese(16*2,16*2,57,16,1);			
	OLED_ShowChinese(16*3,16*2,49,16,1);
	OLED_ShowString(16*4,16*2,":",16,1);
	OLED_ShowNum(16*4+8,16*2,weight,4,16,1);

	OLED_ShowChinese(16*0,16*3,55,16,1);			//药盒状态
	OLED_ShowChinese(16*1,16*3,56,16,1);
	OLED_ShowString(16*2,16*3,":",16,1);
	if(body_status==1){	
        OLED_ShowChinese(16*2+8,16*3,27,16,1);		//开
	}else{
        OLED_ShowChinese(16*2+8,16*3,37,16,1);		//关
	}
    
//    OLED_ShowNum(16*7,16*3,remind_flag,1,16,1);
    
	
	OLED_Refresh();
}

void OLED_Show_SecondPage()
{
	uint8_t a,b,c,d,e,f,g,h,i;
	if(option==1){a=0;b=1;c=1;d=1;e=1;f=1;g=1;h=1;i=1;}
	else if(option==2){a=1;b=0;c=1;d=1;e=1;f=1;g=1;h=1;i=1;}
	else if(option==3){a=1;b=1;c=0;d=1;e=1;f=1;g=1;h=1;i=1;}
	else if(option==4){a=1;b=1;c=1;d=0;e=1;f=1;g=1;h=1;i=1;}
	else if(option==5){a=1;b=1;c=1;d=1;e=0;f=1;g=1;h=1;i=1;}
	else if(option==6){a=1;b=1;c=1;d=1;e=1;f=0;g=1;h=1;i=1;}
	else if(option==7){a=1;b=1;c=1;d=1;e=1;f=1;g=0;h=1;i=1;}
	else if(option==8){a=1;b=1;c=1;d=1;e=1;f=1;g=1;h=0;i=1;}
	else if(option==9){a=1;b=1;c=1;d=1;e=1;f=1;g=1;h=1;i=0;}
	else {a=1;b=1;c=1;d=1;e=1;f=1;g=1;h=1;i=1;}

	OLED_ShowChinese(16*2,0,22,16,0);			//时间设置
	OLED_ShowChinese(16*3,0,23,16,0);
	OLED_ShowChinese(16*4,0,17,16,0);
	OLED_ShowChinese(16*5,0,18,16,0);
	
	OLED_ShowChinese(16*0,16,24,16,1);	//一
	OLED_ShowNum(16*2,16,Timed_One.hour,2,16,a);
	OLED_ShowChar(16*3,16,':',16,1);
	OLED_ShowNum(16*3+8,16,Timed_One.min,2,16,b);
	
	if(timeone_flag==1)OLED_ShowChinese(16*5,16,27,16,c);
	else OLED_ShowChinese(16*5,16,28,16,c);
	
	OLED_ShowChinese(16*0,32,25,16,1);	//二
	OLED_ShowNum(16*2,32,Timed_Two.hour,2,16,d);
	OLED_ShowChar(16*3,32,':',16,1);
	OLED_ShowNum(16*3+8,32,Timed_Two.min,2,16,e);
	
	if(timetwo_flag==1)OLED_ShowChinese(16*5,32,27,16,f);
	else OLED_ShowChinese(16*5,32,28,16,f);

	OLED_ShowChinese(16*0,48,26,16,1);	//三
	OLED_ShowNum(16*2,48,Timed_Three.hour,2,16,g);
	OLED_ShowChar(16*3,48,':',16,1);
	OLED_ShowNum(16*3+8,48,Timed_Three.min,2,16,h);
	
	if(timethree_flag==1)OLED_ShowChinese(16*5,48,27,16,i);
	else OLED_ShowChinese(16*5,48,28,16,i);	
	
	OLED_Refresh();
}

void OLED_Show_ThirdPage()
{
	uint8_t a,b,c,d,e,f;
	if(option==1){a=0;b=1;c=1;d=1;e=1;f=1;}
	else if(option==2){a=1;b=0;c=1;d=1;e=1;f=1;}
	else if(option==3){a=1;b=1;c=0;d=1;e=1;f=1;}
	else if(option==4){a=1;b=1;c=1;d=0;e=1;f=1;}
	else if(option==5){a=1;b=1;c=1;d=1;e=0;f=1;}
	else if(option==6){a=1;b=1;c=1;d=1;e=1;f=0;}
	else {a=1;b=1;c=1;d=1;e=1;f=1;}
	
	
	OLED_ShowChinese(16*2,0,22,16,0);			//时间设置
	OLED_ShowChinese(16*3,0,23,16,0);
	OLED_ShowChinese(16*4,0,17,16,0);
	OLED_ShowChinese(16*5,0,18,16,0);

	
	OLED_ShowChinese(16*0,16*1,58,16,1);	//四
	OLED_ShowNum(16*2,16*1,Timed_Four.hour,2,16,a);
	OLED_ShowChar(16*3,16*1,':',16,1);
	OLED_ShowNum(16*3+8,16*1,Timed_Four.min,2,16,b);
	
	if(timeFour_flag==1)OLED_ShowChinese(16*5,16*1,27,16,c);
	else OLED_ShowChinese(16*5,16*1,28,16*1,c);	
	
	OLED_ShowChinese(16*0,16*2,59,16,1);	//五
	OLED_ShowNum(16*2,16*2,Timed_Five.hour,2,16,d);
	OLED_ShowChar(16*3,16*2,':',16,1);
	OLED_ShowNum(16*3+8,16*2,Timed_Five.min,2,16,e);
	
	OLED_Refresh();
}


void  OLED_Show_FourPage()
{
	uint8_t a,b,c,d,e,f;
	if(option==1){a=0;b=1;c=1;d=1;e=1;f=1;}
	else if(option==2){a=1;b=0;c=1;d=1;e=1;f=1;}
	else if(option==3){a=1;b=1;c=0;d=1;e=1;f=1;}
	else if(option==4){a=1;b=1;c=1;d=0;e=1;f=1;}
	else if(option==5){a=1;b=1;c=1;d=1;e=0;f=1;}
	else if(option==6){a=1;b=1;c=1;d=1;e=1;f=0;}
	else {a=1;b=1;c=1;d=1;e=1;f=1;}

	OLED_ShowChinese(16*2,0,42,16,0);			//系统时间
	OLED_ShowChinese(16*3,0,43,16,0);
	OLED_ShowChinese(16*4,0,22,16,0);
	OLED_ShowChinese(16*5,0,23,16,0);

	OLED_ShowNum(16*2,20,Timed_Init.year%100,2,16,a);
	OLED_ShowChar(16*3,20,'-',16,1);
	OLED_ShowNum(16*3+8,20,Timed_Init.mon,2,16,b);
	OLED_ShowChar(16*4+8,20,'-',16,1);
	OLED_ShowNum(16*5,20,Timed_Init.day,2,16,c);
	
	OLED_ShowNum(16*2,36,Timed_Init.hour,2,16,d);
	OLED_ShowChar(16*3,36,':',16,1);
	OLED_ShowNum(16*3+8,36,Timed_Init.min,2,16,e);
	OLED_ShowChar(16*4+8,36,':',16,1);
	OLED_ShowNum(16*5,36,Timed_Init.sec,2,16,f);

	OLED_Refresh();

}
void net_page(){

	uint8_t a,b,c,d,i;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else {a=1;b=1;c=1;d=1;}
	
	i = 61;
	OLED_ShowChinese(16*2,16,i,16,1);			//	“是”
	OLED_ShowChinese(16*3,16,i+1,16,1);			//	“否”
	OLED_ShowChinese(16*4,16,i+2,16,1);			//	“配”
	OLED_ShowChinese(16*5,16,i+3,16,1);			//	“网”
	OLED_ShowChar(16*6,16,'?',16,1);				//	“:”
	
	OLED_ShowString(16*0,32,"KEY1        KEY2",16,1);
	OLED_ShowChinese(16*0,48,i+4,16,1);		//	“跳”
	OLED_ShowChinese(16*1,48,i+5,16,1);		//	“过”
	
	OLED_ShowChinese(16*6,48,i+6,16,1);		//	“确”
	OLED_ShowChinese(16*7,48,i+7,16,1);		//	“认”
	
	OLED_Refresh();
}

五、项目成品效果

六、项目总结

本设计完成了从硬件选型、电路搭建到嵌入式软件逻辑的全流程开发。核心难点在于 多中断源协同(定时器、外部按键、串口蓝牙中断)与 低功耗轮询策略 的平衡,以及 HX711 零点漂移 的软件补偿。实测表明:语音播报响应延迟 < 200ms,称重精度达 ±1g,蓝牙数据传输稳定(波特率 9600)。

项目不仅验证了 STM32 在健康护理设备中的可行性,还提供了一套可复用的“定时播报 + 重量监测 + 远程控制”框架。后续可升级为 Wi-Fi + 云平台 方案,增加多用户服药记录云端同步与家属预警推送,进一步贴近智慧养老需求。

七、包含资料

1)本资料免费分享,获取全套资料请看主页,并将告诉助手需要资料的项目编号,助手收到消息后,会发送百度网盘链接。每人限领两份开源资料。

  2)需要实物或者定制的小伙伴可以添加工作室微信,发送项目需求,可以按照需求定制项目。定制包含源码、原理图、全套实物、模块参考资料、更详细的参考资料。

  3)重点!!!在本工作室定制的项目,提供一年的技术支持和答疑服务,定制功能范围内的代码和原理图工程师一对一解疑答惑!

资料获取:查看主页介绍“充哥单片机设计”

如果需要项目源码与配套工程文件,欢迎大家在评论区留言交流~
文章若对你有所帮助,期待点赞收藏,后续会持续分享各类单片机实战案例。
内容仅作为学习参考,有任何不妥之处,欢迎大家一起探讨!

更多推荐