1. 项目概述:基于STM32的智能药箱系统设计
作为一名嵌入式开发工程师,我最近完成了一个基于STM32F103C8T6的智能药箱系统项目。这个系统不仅能够实现药品的智能管理,还整合了环境监测、远程控制等实用功能。在实际开发过程中,我发现这类系统在老年人和慢性病患者家庭中有着广泛的应用前景。
系统核心采用STM32F103C8T6作为主控芯片,这是一款性价比极高的ARM Cortex-M3内核单片机,72MHz主频足以应对各类传感器数据处理和控制逻辑。整套系统包含了WIFI通信、环境监测、人机交互等多个功能模块,通过精心设计的硬件电路和软件架构,实现了药品管理的智能化和自动化。
2. 系统硬件设计详解
2.1 主控芯片选型与电路设计
STM32F103C8T6是我们选择的主控芯片,这款芯片具有以下优势:
- 64KB Flash和20KB SRAM,满足程序存储和运行需求
- 丰富的GPIO接口(37个I/O口),可连接多个外设模块
- 内置多个定时器和通信接口(USART、SPI、I2C)
- 低功耗特性,适合长期运行的医疗设备
提示:在实际PCB布局时,建议将晶振电路尽可能靠近MCU,并保持走线对称,这样可以提高时钟信号的稳定性。
电源电路设计采用了AMS1117-3.3V稳压芯片,为整个系统提供稳定的3.3V工作电压。考虑到系统中有电机等大电流设备,我们为舵机单独设计了5V供电电路,避免电源干扰影响MCU正常工作。
2.2 传感器模块选型与接口设计
系统集成了多种传感器,构成了完整的环境监测体系:
-
DHT11温湿度传感器:
- 测量范围:温度0-50℃(±2℃精度),湿度20-90%RH(±5%精度)
- 单总线接口,节省IO资源
- 低功耗特性,适合长期监测
-
HC-SR04超声波传感器:
- 用于检测用户与药箱的距离(判断是否有人接近)
- 测量范围:2cm-400cm
- 精度可达3mm
- 通过Trig引脚发送触发信号,Echo引脚接收回波
-
光敏电阻模块:
- 用于检测环境光照强度
- 模拟量输出,连接至STM32的ADC接口
- 可根据环境光线自动调节显示屏亮度
-
红外人体感应模块:
- 检测是否有人接近药箱
- 数字信号输出,直接连接GPIO
- 探测距离可调(通常3-7米)
2.3 通信模块设计
ESP8266-01S WIFI模块是本系统实现远程监控的关键组件:
- 支持802.11 b/g/n协议
- 内置TCP/IP协议栈
- 通过AT指令与STM32通信
- 工作电压3.3V,需注意电平匹配
在实际应用中,我们发现ESP8266对电源稳定性要求较高,建议在VCC引脚附近添加100μF电解电容和0.1μF陶瓷电容进行滤波。
3. 系统软件架构与关键代码解析
3.1 主程序流程设计
系统软件采用前后台架构,主循环中轮询处理各类任务:
c复制int main(void) {
// 硬件初始化
delay_init();
TIM3_Int_Init(9,7199); // 定时器初始化
OLED_Init(); // OLED初始化
DHT11_Init(); // 温湿度传感器初始化
key_Init(); // 按键初始化
Adc_Init(); // ADC初始化
InitClock(); // 时钟初始化
SG90_Init(); // 舵机初始化
// 串口初始化
uart1_init(9600); // 调试串口
uart2_init(9600); // WIFI通信串口
uart3_init(9600); // 预留扩展串口
// WIFI模块初始化
gizwitsInit();
while(1) {
key_scan(); // 按键扫描
GetKeyInput(&Keystatus); // 菜单处理
SensorDataGet(); // 传感器数据采集
// 数据上传至云平台
currentDataPoint.valueTEMP = TEMP;
currentDataPoint.valueHUMI = HUMI;
currentDataPoint.valuemode = mode;
currentDataPoint.valueyaohe = yaohe;
currentDataPoint.valuefan = fan;
delay_ms(100); // 适当延时
}
}
3.2 传感器数据采集与处理
温湿度采集是系统的核心功能之一,DHT11的读取需要精确的时序控制:
c复制void DHT11_Read_Data(uint8_t *temp, uint8_t *humi) {
uint8_t buf[5] = {0};
uint8_t i, j;
// 主机发送开始信号
DHT11_IO_OUT();
DHT11_DQ_OUT_LOW;
delay_ms(18);
DHT11_DQ_OUT_HIGH;
delay_us(30);
// 切换为输入模式等待响应
DHT11_IO_IN();
// 等待DHT11响应
while(DHT11_DQ_IN);
while(!DHT11_DQ_IN);
// 读取40位数据
for(i=0; i<5; i++) {
for(j=0; j<8; j++) {
while(!DHT11_DQ_IN); // 等待低电平结束
delay_us(40);
if(DHT11_DQ_IN) {
buf[i] |= (1 << (7-j));
while(DHT11_DQ_IN);
}
}
}
// 校验数据
if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4]) {
*humi = buf[0];
*temp = buf[2];
}
}
注意:DHT11对时序要求严格,在实际调试中发现,delay_us()函数的精度直接影响数据读取成功率。建议使用定时器实现精确延时。
3.3 人机交互界面设计
OLED显示屏采用SSD1306驱动芯片,通过I2C接口与STM32通信。我们设计了多级菜单系统,方便用户操作:
c复制typedef struct {
uint8_t current; // 当前菜单项
uint8_t up; // 向上按键对应的菜单项
uint8_t down; // 向下按键对应的菜单项
uint8_t left; // 向左按键对应的菜单项
uint8_t right; // 向右按键对应的菜单项
void (*display)(void); // 菜单显示函数
} CaiDanJieGouTi;
// 菜单项定义
CaiDanJieGouTi KeyTab[SIZE_CAIDAN] = {
{0, 0, 0, 0, 0, Main_Menu0}, // 主界面
{1, 1, 1, 1, 1, Main_Menu1}, // 温湿度显示
{2, 2, 2, 2, 2, Main_Menu2}, // 光照强度显示
{3, 3, 3, 3, 3, Main_Menu3}, // 人体感应状态
{4, 4, 4, 4, 4, Main_Menu4}, // 系统设置
{5, 5, 5, 5, 5, Main_Menu5}, // 时间设置
{6, 6, 6, 6, 6, Main_Menu6}, // 报警设置
{7, 7, 7, 7, 7, Main_Menu7}, // WIFI设置
{8, 8, 8, 8, 8, Main_Menu8}, // 关于信息
};
4. 系统功能实现与调试经验
4.1 药品管理功能实现
药箱的智能管理主要通过超声波传感器和红外传感器实现:
- 超声波传感器检测用户与药箱的距离
- 红外传感器确认是否有用户接近
- 当用户接近时,系统自动点亮OLED屏幕显示药品信息
在实际测试中,我们发现超声波传感器容易受到环境温度影响,导致测距误差。解决方法是在代码中添加温度补偿算法:
c复制float getCorrectDistance(float rawDistance, float temperature) {
// 声速温度补偿公式:V = 331.4 + 0.6*T (m/s)
float speedOfSound = 331.4 + 0.6 * temperature;
float standardSpeed = 343.0; // 20℃时的声速
// 计算补偿后的距离
return rawDistance * standardSpeed / speedOfSound;
}
4.2 环境监测与自动控制
系统通过DHT11监测药箱内部温湿度,当环境参数超出设定阈值时,自动启动相应控制:
-
湿度控制:
- 当湿度超过设定上限,启动除湿装置
- 当湿度低于设定下限,关闭除湿装置
- 除湿控制采用继电器模块,驱动小型除湿器
-
温度监测:
- 实时显示药箱内部温度
- 温度异常时发出声光报警
- 通过蜂鸣器和LED指示灯提醒用户
-
光照控制:
- 根据环境光线自动调节OLED背光亮度
- 夜间模式自动降低屏幕亮度,减少光污染
4.3 远程监控功能实现
ESP8266模块实现了系统与手机APP的无线连接,关键实现步骤如下:
- WIFI模块初始化:
c复制void ESP8266_Init(void) {
// 发送AT指令测试模块
USART2_SendString("AT\r\n");
delay_ms(100);
// 设置WIFI模式为STA+AP
USART2_SendString("AT+CWMODE=3\r\n");
delay_ms(100);
// 连接到路由器
USART2_SendString("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n");
delay_ms(5000); // 连接需要较长时间
// 启用多连接
USART2_SendString("AT+CIPMUX=1\r\n");
delay_ms(100);
// 建立TCP服务器
USART2_SendString("AT+CIPSERVER=1,8080\r\n");
delay_ms(100);
}
- 数据上传处理:
c复制void uploadSensorData(void) {
char buffer[128];
// 格式化JSON数据
sprintf(buffer, "{\"temp\":%.1f,\"humi\":%.1f,\"light\":%d}",
currentDataPoint.valueTEMP,
currentDataPoint.valueHUMI,
currentDataPoint.valuelight);
// 发送数据到服务器
USART2_SendString("AT+CIPSEND=0,");
USART2_SendString(itoa(strlen(buffer), buffer, 10));
USART2_SendString("\r\n");
delay_ms(100);
USART2_SendString(buffer);
delay_ms(100);
}
5. 系统调试与优化经验
5.1 硬件调试常见问题
-
电源干扰问题:
- 现象:系统运行时OLED显示出现闪烁,传感器数据不稳定
- 原因:舵机工作时产生电流突变,影响3.3V电源稳定性
- 解决:在舵机电源端增加1000μF电解电容,3.3V电源增加LC滤波电路
-
传感器数据异常:
- 现象:DHT11偶尔读取失败,返回错误数据
- 原因:时序控制不精确,信号线过长引入干扰
- 解决:优化延时函数精度,缩短传感器连接线,增加上拉电阻
-
WIFI连接不稳定:
- 现象:ESP8266频繁断开连接
- 原因:天线设计不合理,信号强度不足
- 解决:调整PCB天线走线,避免靠近高频信号线
5.2 软件优化技巧
- 低功耗优化:
c复制void enterLowPowerMode(void) {
// 关闭不必要的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, DISABLE);
// 设置未使用的IO口为模拟输入
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 进入停止模式,等待外部中断唤醒
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
-
内存优化:
- 使用
__packed关键字优化结构体存储 - 合理使用const关键字将常量放入Flash
- 启用编译器的优化选项(-O2)
- 使用
-
实时性保障:
- 关键任务使用定时器中断处理
- 非关键任务采用时间片轮询
- 合理设置任务优先级
5.3 生产测试方案
为确保批量生产时的产品质量,我们设计了以下测试流程:
-
电源测试:
- 上电测试各电压点是否正常(3.3V、5V)
- 测量静态电流和工作电流
-
功能测试:
- 自动测试各传感器数据采集功能
- 测试舵机和继电器控制功能
- 验证WIFI连接和数据上传
-
老化测试:
- 连续运行72小时,监测系统稳定性
- 高温高湿环境测试(40℃, 85%RH)
- 低温测试(-10℃)
6. 项目扩展与改进方向
在实际使用过程中,我们发现系统还可以从以下几个方面进行改进:
-
增加药品识别功能:
- 集成RFID模块,实现药品自动识别
- 记录药品取用情况,生成用药报告
-
改进用户界面:
- 采用触摸屏替代按键操作
- 增加语音提示功能,方便视力不佳的用户
-
增强云平台功能:
- 对接医疗云平台,实现医生远程监控
- 增加用药提醒推送功能
-
提高安全性:
- 增加指纹识别或人脸识别模块
- 实现药品存取权限管理
-
优化电源管理:
- 增加锂电池备用电源
- 实现太阳能充电功能
这个智能药箱系统从设计到实现历时三个月,期间遇到了不少技术挑战,但最终都找到了解决方案。通过这个项目,我深刻体会到嵌入式系统开发需要硬件和软件的紧密配合,任何一个细节的疏忽都可能导致系统不稳定。希望我的经验分享能给正在开发类似项目的朋友一些启发和帮助。