从电子秤到智能设备:用STM32F4和HX711做个带蓝牙APP的迷你压力监测仪(附CubeMX工程)
从电子秤到智能终端:基于STM32F4与HX711的蓝牙称重系统开发实战
在创客圈子里,将传统电子秤升级为智能终端一直是个热门话题。想象一下:当你在厨房烘焙时,称重数据能实时同步到手机APP;或者在物流仓库,工作人员可以边移动边记录包裹重量。这种融合硬件与软件的微型物联网项目,正是STM32F4系列微控制器搭配HX711模数转换芯片的绝佳应用场景。
1. 硬件架构设计
1.1 核心元件选型指南
构建一个完整的蓝牙称重系统需要四大核心组件:
- STM32F407VET6:具备浮点运算单元,适合实时数据处理
- HX711模块:24位高精度ADC,市场均价约12元
- HC-05蓝牙模块:经典串口透传方案,兼容Android/iOS
- 应变式称重传感器:推荐5kg量程,灵敏度2.0mV/V
提示:选购HX711模块时注意VCC电压,3.3V版本可直接与STM32F4对接
1.2 电路连接方案
完整的硬件连接需要关注三个关键接口:
| 连接点 | STM32引脚 | 备注 |
|---|---|---|
| HX711_DOUT | PA0 | 配置为上拉输入 |
| HX711_SCK | PA1 | 推挽输出模式 |
| HC-05_TXD | PA2 | USART2_RX |
| HC-05_RXD | PA3 | USART2_TX |
| 传感器E+ | 5V | 桥压供电 |
| 传感器E- | GND |
// GPIO初始化示例(CubeMX生成) void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); // HX711 DOUT配置 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // HX711 SCK配置 GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); }2. CubeMX工程配置
2.1 时钟树优化策略
在RCC配置中启用外部晶振(HSE)后,按以下参数配置时钟树:
- 输入频率:8MHz(外部晶振)
- PLLM分频:8
- PLLN倍频:336
- PLLP分频:2
- 系统时钟:168MHz
- APB1分频:4(42MHz)
- APB2分频:2(84MHz)
注意:过高的时钟频率可能导致HX711时序异常,建议实测稳定性
2.2 外设模块配置
在CubeMX中需要完成三个关键配置:
- USART2:蓝牙模块通信接口
- 波特率:9600
- 字长:8bit
- 停止位:1
- 无流控
- SysTick:作为HAL库基础时钟源
- GPIO:如前文电路连接所示
// USART初始化代码片段 void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; HAL_UART_Init(&huart2); }3. HX711驱动开发
3.1 数据采集时序控制
HX711的24位数据读取需要严格遵循以下时序:
- 等待DOUT变为低电平(就绪信号)
- 发送25个时钟脉冲:
- 前24个脉冲读取数据位(MSB优先)
- 第25个脉冲设置增益(128/64/32)
- 每个时钟高电平持续至少1μs
- 数据在时钟下降沿有效
uint32_t HX711_Read() { uint32_t count = 0; while(HAL_GPIO_ReadPin(DT_GPIO_Port, DT_Pin) == GPIO_PIN_SET); for(uint8_t i=0; i<24; i++) { HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); delay_us(1); count <<= 1; HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); delay_us(1); if(HAL_GPIO_ReadPin(DT_GPIO_Port, DT_Pin) == GPIO_PIN_SET) count++; } // 设置增益为128 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); delay_us(1); return count ^ 0x800000; }3.2 重量校准算法
实际应用中需要解决两个关键问题:
- 去皮功能:存储空载时的基准值
- 线性校准:通过已知砝码建立转换公式
float calibration_factor = -106.5f; // 需要实际校准的参数 void Weight_Calibration() { float known_weight = 500.0f; // 500g标准砝码 uint32_t adc_value = HX711_Read(); calibration_factor = (adc_value - tare_value) / known_weight; printf("New calibration factor: %.2f\n", calibration_factor); }4. 蓝牙数据透传实现
4.1 数据协议设计
建议采用简单的JSON格式传输数据:
{ "weight": 325.6, "unit": "g", "stable": true }对应的C语言生成代码:
void Bluetooth_Send_Weight(float weight) { char buffer[64]; int len = snprintf(buffer, sizeof(buffer), "{\"weight\":%.1f,\"unit\":\"g\",\"stable\":%s}", weight, is_stable()?"true":"false"); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, len, 100); }4.2 MIT App Inventor客户端开发
在MIT App Inventor中构建基础界面需要以下组件:
- ListPicker:蓝牙设备选择
- BluetoothClient:通信组件
- Label:重量显示区域
- Clock:定时刷新数据
关键逻辑块示例:
当 BluetoothClient1.收到数据 时 设 接收文本 为 解码 BluetoothClient1.接收文本 UTF-8 设 jsonObj 为 从JSON文本转换 接收文本 设 重量值 为 从jsonObj获取 "weight" 设 Label1.文本 为 连接字符串 "当前重量: " 重量值 "g"5. 系统优化技巧
5.1 数字滤波方案对比
针对称重系统的抖动问题,实测三种滤波算法效果:
| 算法类型 | 实现复杂度 | 延迟时间 | 滤波效果 |
|---|---|---|---|
| 滑动平均 | ★★☆ | 50ms | ★★★ |
| 卡尔曼滤波 | ★★★★ | 10ms | ★★★★☆ |
| 中值+均值复合 | ★★★ | 30ms | ★★★★ |
推荐实现方案:
#define FILTER_WINDOW 5 float moving_average_filter(float new_val) { static float buffer[FILTER_WINDOW] = {0}; static uint8_t index = 0; static float sum = 0; sum -= buffer[index]; buffer[index] = new_val; sum += buffer[index]; index = (index + 1) % FILTER_WINDOW; return sum / FILTER_WINDOW; }5.2 低功耗优化策略
通过以下措施可降低50%以上功耗:
- 动态调整HX711采样率(空闲时降至10Hz)
- 使用STM32的STOP模式配合蓝牙模块唤醒
- 关闭未使用的外设时钟
- 降低CPU主频至84MHz(称重时恢复)
void Enter_Low_Power_Mode() { // 配置唤醒源(蓝牙模块中断) HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); // 设置电压调节器为低功耗模式 HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE3); // 进入STOP模式 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后重新初始化时钟 SystemClock_Config(); }在实际项目中,我发现蓝牙模块的配对时间往往成为用户体验瓶颈。通过预存常用设备的MAC地址,可以将首次连接时间从8秒缩短到2秒以内。另一个实用技巧是在HX711的电源路径上添加MOS管控制,需要采样时才供电,这样能显著降低系统整体功耗。
