#include <Wire.h> // I2C 通信库(OLED 依赖)
#include <SSD1306.h> // OLED 显示库(按需替换为实际屏驱动)
#include <HX711.h> // HX711 压力传感器库
#include <NewPing.h> // 超声波传感器库(可选,身高测量)
// -------------- 硬件引脚定义 --------------
///// HX711
const int HX711_DT = 21;
const int HX711_SCK = 22;
// OLED(SSD1306 128x64 示例)
SSD1306 display(0x3C, 21, 22); // 地址 0x3C,SDA=21,SCL=22(依硬件接线调整)
// HC-SR04(可选,身高测量)
const int SONAR_TRIGGER = 5;
const int SONAR_ECHO = 18;
NewPing sonar(SONAR_TRIGGER, SONAR_ECHO, 400); // 最大测距 400cm
// HX711 实例
HX711 scale;
// -------------- 校准参数(需实际标定) --------------
float calibrationFactor = 12345.0; // HX711 校准系数(需用已知重量标定)
float offset = 0; // 零点偏移(去皮用)
// -------------- 全局变量 --------------
float weight = 0.0; // 重量(kg)
float height = 170.0; // 身高(cm,默认值,可手动改或传感器获取)
float BMI = 0.0; // BMI 指数
float bodyFat = 0.0; // 体脂率(%)
// -------------- 函数声明 --------------
void setupHardware(); // 硬件初始化
void calibrateScale(); // 校准 HX711(可选,实际需手动标定)
void getWeight(); // 读取重量
void getHeight(); // (可选)用 HC-SR04 测身高
void calculateBMI(); // 计算 BMI
void calculateBodyFat();// 估算体脂率
void displayData(); // OLED 显示数据
void setup() {
Serial.begin(115200);
setupHardware();
// (可选)执行校准(首次使用或换传感器需标定)
// calibrateScale();
// (可选)读取身高(若用 HC-SR04)
// getHeight();
}
void loop() {
getWeight(); // 读取重量
calculateBMI(); // 计算 BMI
calculateBodyFat();// 估算体脂率
displayData(); // 显示数据
delay(1000); // 每秒刷新
}
// -------------- 函数实现 --------------
void setupHardware() {
// HX711 初始化
scale.begin(HX711_DT, HX711_SCK);
scale.set_scale(calibrationFactor); // 设置校准系数
scale.tare(); // 去皮(清零)
// OLED 初始化
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_16);
display.setTextAlignment(TEXT_ALIGN_CENTER);
}
void calibrateScale() {
// 【校准步骤】:
// 1. 传感器空载时,执行 tare() 清零;
// 2. 放置已知重量(如 1kg)的物体;
// 3. 读取 scale.get_units(10) 平均值,调整 calibrationFactor 使输出接近 1.0;
Serial.println("=== 开始 HX711 校准 ===");
scale.tare(); // 去皮
delay(1000);
float knownWeight = 1.0; // 已知重量(kg,需实际放置)
Serial.print("放置已知重量(");
Serial.print(knownWeight);
Serial.println("kg)的物体...");
delay(3000);
// 多次采样求平均
float avgUnits = 0;
for (int i = 0; i < 10; i++) {
avgUnits += scale.get_units();
delay(100);
}
avgUnits /= 10;
// 计算校准系数(calibrationFactor = 读数 / 已知重量)
calibrationFactor = avgUnits / knownWeight;
scale.set_scale(calibrationFactor); // 应用新系数
Serial.print("校准完成!新的校准系数:");
Serial.println(calibrationFactor);
}
void getWeight() {
// 读取重量(kg),多次采样求稳
float sum = 0;
for (int i = 0; i < 5; i++) {
sum += scale.get_units();
delay(50);
}
weight = sum / 5;
Serial.print("重量:");
Serial.print(weight);
Serial.println(" kg");
}
void getHeight() {
// (示例)用 HC-SR04 测身高(需固定传感器安装高度,计算逻辑仅参考)
// 原理:传感器到地面距离 - 传感器到头顶距离 = 身高
float sensorHeight = 200.0; // 传感器安装高度(cm,需实际测量)
float distance = sonar.ping_cm(); // 测传感器到头顶距离
if (distance > 0 && distance < sensorHeight) {
height = sensorHeight - distance; // 计算身高
Serial.print("身高:");
Serial.print(height);
Serial.println(" cm");
} else {
Serial.println("身高测量异常");
}
}
void calculateBMI() {
// BMI 公式:体重(kg) / 身高(m)²
float heightM = height / 100.0; // 转米
BMI = weight / (heightM * heightM);
Serial.print("BMI:");
Serial.println(BMI);
}
void calculateBodyFat() {
// 【经验公式示例】:仅作演示,实际需更精准算法(如考虑性别、年龄等)
// 男性:体脂率(%) = (1.20×BMI) + (0.23×年龄) - 16.2
// 女性:体脂率(%) = (1.20×BMI) + (0.23×年龄) - 5.4
// 这里简化为通用示例(仅演示逻辑):
bodyFat = 1.2 * BMI + 0.23 * 25 - 10; // 假设年龄 25,仅示例!
Serial.print("体脂率:");
Serial.print(bodyFat);
Serial.println(" %");
}
void displayData() {
display.clear();
display.drawString(64, 10, "Weight: " + String(weight, 2) + " kg");
display.drawString(64, 30, "BMI: " + String(BMI, 1));
display.drawString(64, 50, "Fat: " + String(bodyFat, 1) + " %");
display.display();
}