智能书包重量检测与脊椎保护系统一、实际应用场景描述现代中小学生课业负担日益加重书包重量往往超过儿童身体承受的安全范围。据医学研究表明儿童书包重量不应超过体重的10%-15%否则长期背负会导致脊柱侧弯、驼背、肌肉劳损等健康问题。典型场景- 小学生小明体重25kg每天背着4-5公斤的书包上学内含语文、数学、英语、科学等课本加上作业本、文具盒、水壶等物品- 初中生小红体重40kg面临中考压力书包重量达到7-8公斤包含各种教辅资料- 高中生小华体重50kg书包重量超过8公斤长期单肩背负导致肩膀高低不平传统解决方案的局限- 家长凭经验判断缺乏客观数据支撑- 学校无检测设备无法实时监控- 学生自身无感知直到出现疼痛才意识到问题- 没有实时提醒机制无法及时卸重- 缺乏历史数据无法追踪书包重量变化趋势- 无个性化建议不同体重学生使用统一标准本系统功能- 实时检测书包重量精度±10g- 根据学生体重计算安全负重阈值- 超重时语音提示减轻书本- 可视化显示重量状态和健康建议- 记录每日书包重量历史- 脊椎健康风险评估与个性化建议二、引入痛点1. 健康隐患严重过重书包导致儿童脊柱发育畸形据统计我国中小学生脊柱侧弯发病率已达5%-10%2. 主观判断不准家长和老师难以准确估算书包重量容易低估实际负重3. 缺乏实时监控学生在校期间无人监督书包重量长时间背负超限物品4. 即时反馈缺失没有实时提醒机制学生往往在感到疲劳时才发现问题5. 数据记录空白缺乏历史数据追踪无法评估书包重量变化趋势6. 个性化缺失不同年龄、体重的学生使用统一标准不够科学合理7. 预防意识薄弱学生和家长对书包重量的健康影响认识不足8. 家校联动困难学校与家长缺乏有效的书包重量沟通渠道三、核心逻辑讲解重量安全标准学生体重(kg) 安全负重(kg) 最大负重(kg) 健康风险20-25 2.0-3.0 3.5-4.0 低风险25-35 3.0-4.5 4.5-6.0 中低风险35-45 4.5-6.0 6.0-7.5 中风险45-55 6.0-7.5 7.5-9.0 中高风险55 7.5-9.0 9.0-12.0 高风险压力传感器HX711特性HX711是一款24位A/D转换器专用于电子秤设计- 输入电压范围±20mV- 输出数据速率10Hz或80Hz- 内置放大器和稳压器- 差分输入抗干扰能力强- 典型连接方式Load Cell → HX711 → MCU核心算法流程1. 重量采集- HX711读取24位原始数据- 多次采样取平均值- 温度补偿和线性校准2. 用户配置- 输入学生体重- 计算个性化安全阈值- 设置提醒灵敏度3. 实时分析- 重量与阈值比较- 连续超重检测防误报- 趋势分析和预测4. 多级提醒- 绿色安全范围- 黄色接近上限- 红色超重报警- 语音提示减轻书本5. 数据记录- 时间戳记录- 重量历史存储- 健康报告生成关键技术难点及解决方案难点 解决方案传感器零点漂移 上电自动归零定期校准温度影响精度 温度补偿算法NTC热敏电阻机械振动干扰 数字滤波软件去抖不同书包差异 用户自定义校准系数误报问题 连续3次超重确认机制功耗优化 休眠唤醒机制动态采样四、代码模块化含安全设计项目结构smart_backpack/├── main.py # 主程序入口├── sensors/ # 传感器模块│ ├── __init__.py│ ├── hx711_weight.py # HX711重量传感器驱动│ └── calibration.py # 校准模块├── core/ # 核心逻辑模块│ ├── __init__.py│ ├── weight_analyzer.py # 重量分析引擎│ ├── health_assessor.py # 健康评估模块│ └── alert_manager.py # 提醒管理器├── actuators/ # 执行器模块│ ├── __init__.py│ ├── lcd_display.py # LCD显示屏控制│ ├── voice_prompt.py # 语音提示模块│ ├── led_indicator.py # LED指示灯控制│ └── buzzer.py # 蜂鸣器控制├── storage/ # 数据存储模块│ ├── __init__.py│ ├── data_logger.py # 数据记录器│ └── report_generator.py # 报告生成器├── config.py # 系统配置├── requirements.txt # 依赖清单├── README.md # 项目文档└── utils/├── __init__.py├── logger.py # 日志工具└── decorators.py # 装饰器工具核心代码实现1. config.py系统配置智能书包重量检测与脊椎保护系统配置文件包含传感器、执行器、健康标准等所有配置参数from dataclasses import dataclass, fieldfrom typing import List, Optional, Dict, Any, Tuplefrom enum import Enum, autofrom pathlib import Pathimport os# 确保配置目录存在Path(config).mkdir(parentsTrue, exist_okTrue)class WeightStatus(Enum):重量状态枚举SAFE auto() # 安全范围WARNING auto() # 警告接近上限OVERWEIGHT auto() # 超重CRITICAL auto() # 严重超重class AlertLevel(Enum):提醒级别枚举NONE auto() # 无提醒MILD auto() # 轻度提醒MODERATE auto() # 中度提醒URGENT auto() # 紧急提醒dataclassclass SensorConfig:传感器配置# HX711配置hx711_dt_pin: int 5 # 数据引脚hx711_sck_pin: int 6 # 时钟引脚hx711_reference_unit: float 1.0 # 参考单位校准系数hx711_offset: int 0 # 零点偏移hx711_gain: int 128 # 增益设置128或64# 采样配置sample_count: int 10 # 采样次数sample_interval: float 0.1 # 采样间隔秒filter_window: int 5 # 滤波窗口大小# 校准配置calibration_weight: float 1.0 # 校准砝码重量kgcalibration_samples: int 20 # 校准采样次数# 模拟模式开发测试用simulation_mode: bool Truedataclassclass UserConfig:用户配置# 学生信息student_name: str 学生student_weight: float 30.0 # 学生体重kgstudent_age: int 10 # 学生年龄# 安全阈值配置safe_load_ratio: float 0.15 # 安全负重比例体重的15%max_load_ratio: float 0.20 # 最大负重比例体重的20%warning_threshold: float 0.85 # 警告阈值安全上限的85%# 个性化设置sensitivity: float 1.0 # 敏感度0.5-2.0reminder_interval: float 30.0 # 提醒间隔秒enable_voice: bool True # 启用语音提醒enable_display: bool True # 启用显示enable_led: bool True # 启用LED指示dataclassclass HealthThresholds:健康阈值配置# 按年龄段的健康建议age_groups: Dict[Tuple[int, int], Dict[str, Any]] field(default_factorylambda: {(6, 8): {safe_min: 1.5, safe_max: 3.0, warning_msg: 低年级学生书包不宜过重},(9, 11): {safe_min: 2.0, safe_max: 4.5, warning_msg: 中年级学生注意减负},(12, 14): {safe_min: 3.0, safe_max: 6.0, warning_msg: 高年级学业繁重合理整理书包},(15, 18): {safe_min: 4.0, safe_max: 8.0, warning_msg: 初高中生注意脊柱健康}})# 脊椎健康风险评估spine_risk_levels: Dict[str, Tuple[float, float]] field(default_factorylambda: {低风险: (0.0, 0.12),中低风险: (0.12, 0.15),中风险: (0.15, 0.18),中高风险: (0.18, 0.22),高风险: (0.22, 1.0)})dataclassclass AlertConfig:提醒配置# LCD配置lcd_enabled: bool Truelcd_i2c_address: int 0x27lcd_columns: int 16lcd_rows: int 2# LED配置led_enabled: bool Trueled_green_pin: int 17led_yellow_pin: int 27led_red_pin: int 22# 蜂鸣器配置buzzer_enabled: bool Truebuzzer_pin: int 23buzzer_frequency_safe: int 1000buzzer_frequency_warning: int 1500buzzer_frequency_overweight: int 2000# 语音配置voice_enabled: bool Truevoice_volume: int 80 # 音量百分比voice_language: str zh-CN# 提醒模式vibration_enabled: bool False # 震动提醒可选配件vibration_pin: int 24dataclassclass StorageConfig:存储配置# 数据记录log_enabled: bool Truelog_directory: str data/logslog_filename: str weight_history.csvlog_interval: float 300.0 # 记录间隔秒# 历史数据max_history_days: int 30export_enabled: bool Trueexport_format: str csv# 报告配置weekly_report: bool Truemonthly_report: bool Truedataclassclass SystemConfig:系统总配置sensor: SensorConfig field(default_factorySensorConfig)user: UserConfig field(default_factoryUserConfig)health: HealthThresholds field(default_factoryHealthThresholds)alert: AlertConfig field(default_factoryAlertConfig)storage: StorageConfig field(default_factoryStorageConfig)# 系统设置debug_mode: bool Falselog_level: str INFOlog_file: str smart_backpack.log# 安全限制min_weight: float 0.0max_weight: float 20.0 # 最大可测重量min_student_weight: float 15.0max_student_weight: float 100.0def __post_init__(self):# 确保目录存在for directory in [self.storage.log_directory, data, reports]:Path(directory).mkdir(parentsTrue, exist_okTrue)# 计算实际阈值self._calculate_thresholds()def _calculate_thresholds(self):根据学生体重计算实际重量阈值weight self.user.student_weight# 根据年龄组调整for (age_min, age_max), params in self.health.age_groups.items():if age_min self.user.student_age age_max:self.user.safe_load_ratio params[safe_max] / weight if weight 0 else 0.15break# 计算各级阈值self.safe_threshold weight * self.user.safe_load_ratio * self.user.sensitivityself.warning_threshold self.safe_threshold * self.user.warning_thresholdself.max_threshold weight * self.user.max_load_ratio * self.user.sensitivitylogger.info(f阈值计算完成: 安全{self.safe_threshold:.2f}kg, f警告{self.warning_threshold:.2f}kg, f最大{self.max_threshold:.2f}kg)# 全局配置实例config SystemConfig()# 重量状态颜色映射STATUS_COLORS {WeightStatus.SAFE: (0, 255, 0), # 绿色WeightStatus.WARNING: (255, 255, 0), # 黄色WeightStatus.OVERWEIGHT: (255, 165, 0), # 橙色WeightStatus.CRITICAL: (255, 0, 0) # 红色}# 提醒级别消息ALERT_MESSAGES {AlertLevel.NONE: ,AlertLevel.MILD: 书包略重请注意,AlertLevel.MODERATE: 书包较重建议减负,AlertLevel.URGENT: 书包超重请减轻书本}# 脊椎健康建议SPINE_HEALTH_ADVICE {低风险: 书包重量适中继续保持良好习惯,中低风险: 书包稍重可适当减少不必要物品,中风险: 书包偏重建议每日检查书包内容,中高风险: 书包过重请及时减负保护脊椎,高风险: 书包严重超重立即停止背负咨询医生}# 年级对应建议AGE_GROUP_ADVICE {(6, 8): 低年级同学只带当天需要的课本使用轻便文具盒,(9, 11): 中年级同学学会整理书包定期清理不需要的物品,(12, 14): 高年级同学合理安排学习计划避免携带过多参考资料,(15, 18): 初高中同学使用拉杆书包分担重量注意双肩背负}# 工厂函数def create_config() - SystemConfig:创建配置实例return configdef update_user_config(name: str None, weight: float None, age: int None):更新用户配置global configif name:config.user.student_name nameif weight:config.user.student_weight weightconfig._calculate_thresholds()if age:config.user.student_age ageconfig._calculate_thresholds()logger None # 将在main中初始化2. sensors/hx711_weight.pyHX711重量传感器模块HX711重量传感器模块24位A/D转换器专用于电子秤和压力检测支持校准、滤波、温度补偿等功能import timeimport loggingimport randomfrom typing import Optional, List, Tuple, Dequefrom dataclasses import dataclass, fieldfrom enum import Enum, autofrom collections import dequefrom config import config, SensorConfiglogger logging.getLogger(__name__)class SensorError(Exception):传感器异常类passclass CalibrationError(SensorError):校准异常类passclass GainChannel(Enum):HX711增益通道CHANNEL_A_GAIN_128 1 # 通道A增益128默认CHANNEL_A_GAIN_64 3 # 通道A增益64CHANNEL_B_GAIN_32 2 # 通道B增益32dataclassclass WeightReading:重量读数数据类timestamp: floatraw_value: intweight_kg: floatis_valid: bool Truequality: float 1.0 # 数据质量分数 0-1temperature: Optional[float] None # 温度补偿用class HX711WeightSensor:HX711 24位重量传感器驱动特性- 24位高精度A/D转换- 内置可编程增益放大器- 差分输入抗干扰能力强- 支持温度补偿- 数字滤波和校准- 模拟模式支持开发测试用工作原理1. 称重传感器应变片将重量转换为微伏级电压2. HX711内部PGA将信号放大3. 24位Σ-Δ ADC将模拟信号转换为数字量4. 通过参考单位和零点偏移计算实际重量接线方式HX711 → Raspberry PiVCC → 3.3V/5VGND → GNDDT(Data) → GPIO5SCK(Clock)→ GPIO6E(红) → 传感器红线E-(黑) → 传感器黑线A(绿) → 传感器绿线A-(白) → 传感器白线# HX711命令码CMD_READ_CH_A_128 0x01 # 读通道A增益128CMD_READ_CH_A_64 0x03 # 读通道A增益64CMD_READ_CH_B_32 0x02 # 读通道B增益32# 时序参数微秒TIMING_CLOCK_HIGH 1TIMING_CLOCK_LOW 1TIMING_READ_DELAY 1def __init__(self, dt_pin: int 5, sck_pin: int 6, gain: int 128):初始化HX711传感器Args:dt_pin: 数据引脚GPIO编号sck_pin: 时钟引脚GPIO编号gain: 增益设置128或64self.dt_pin dt_pinself.sck_pin sck_pinself.gain gain# 校准参数self._reference_unit config.sensor.hx711_reference_unitself._offset config.sensor.hx711_offset# 滤波缓冲区self._filter_buffer: Deque[float] deque(maxlenconfig.sensor.filter_window)# 状态管理self._is_initialized Falseself._is_ready Falseself._last_reading: Optional[WeightReading] None# 模拟模式self._simulation_mode config.sensor.simulation_modeself._simulation_base_weight 2.0 # 模拟基础重量# 统计信息self._readings_count 0self._error_count 0self._max_errors 10# 温度补偿参数self._temperature_coefficient -0.02 # 每度温度变化的影响%/°Cself._reference_temperature 25.0 # 参考温度logger.info(fHX711重量传感器初始化: DT引脚{dt_pin}, fSCK引脚{sck_pin}, 增益{gain})def initialize(self) - bool:初始化传感器硬件Returns:bool: 初始化是否成功try:if self._simulation_mode:logger.info(HX711传感器运行在模拟模式)self._is_initialized Trueself._is_ready Truereturn True# 实际硬件初始化# import RPi.GPIO as GPIO# self.GPIO GPIO# self.GPIO.setmode(GPIO.BCM)# self.GPIO.setup(self.dt_pin, GPIO.IN, pull_up_downGPIO.PUD_UP)# self.GPIO.setup(self.sck_pin, GPIO.OUT)# self.GPIO.output(self.sck_pin, GPIO.LOW)# 等待传感器稳定time.sleep(0.5)# 检查传感器是否就绪DT引脚应为高电平# ready self.GPIO.input(self.dt_pin)# if ready:# logger.warning(传感器未就绪可能有重物压着)self._is_initialized Trueself._is_ready Truelogger.info(HX711重量传感器初始化成功)return Trueexcept Exception as e:logger.error(fHX711传感器初始化失败: {e})return Falsedef _set_gain(self, gain: int):设置增益if gain 128:self._gain_channel GainChannel.CHANNEL_A_GAIN_128elif gain 64:self._gain_channel GainChannel.CHANNEL_A_GAIN_64elif gain 32:self._gain_channel GainChannel.CHANNEL_B_GAIN_32else:raise ValueError(f不支持的增益值: {gain})def _read_raw_value(self) - Optional[int]:读取24位原始数据HX711通信协议1. 等待DT引脚变低数据准备好2. 发送24个时钟脉冲在每个上升沿读取数据位3. 发送额外的1-3个时钟脉冲选择下一次的增益通道Returns:Optional[int]: 24位原始数据有符号if not self._is_initialized:logger.error(传感器未初始化)return Nonetry:if self._simulation_mode:# 模拟数据模拟不同重量和噪声time.sleep(0.1)# 模拟重量波动weight_variation random.uniform(-0.1, 0.1)noise random.uniform(-50, 50)# 模拟一些日常场景import mathtime_factor (time.time() % 60) / 60 # 0-1循环# 模拟放书包前5秒重量增加if time_factor 0.08:loading_progress time_factor / 0.08simulated_weight self._simulation_base_weight * loading_progress# 模拟稳定负重elif time_factor 0.85:simulated_weight self._simulation_base_weight weight_variation# 模拟减重最后15秒else:unloading_progress (time_factor - 0.85) / 0.15simulated_weight self._simulation_base_weight * (1 - unloading_progress)# 转换为原始ADC值raw_value int(simulated_weight * self._reference_unit * 1000) noisereturn raw_value# 实际硬件读取# import RPi.GPIO as GPIO# 等待数据准备好DT变低# timeout 1000 # 超时计数# while self.GPIO.input(self.dt_pin) and timeout 0:# time.sleep(0.001)# timeout - 1## if timeout 0:# logger.warning(等待数据就绪超时)# return None# 读取24位数据# raw_data 0# for _ in range(24):# self.GPIO.output(self.sck_pin, GPIO.HIGH)# time.sleep(self.TIMING_CLOCK_HIGH / 1000000)# raw_data (raw_data 1) | self.GPIO.input(self.dt_pin)# self.GPIO.output(self.sck_pin, GPIO.LOW)# time.sleep(self.TIMING_CLOCK_LOW / 1000000)## # 选择下一个增益通道# extra_clocks self._gain_channel.value# for _ in range(extra_clocks):# self.GPIO.output(self.sck_pin, GPIO.HIGH)# time.sleep(self.TIMING_CLOCK_HIGH / 1000000)# self.GPIO.output(self.sck_pin, GPIO.LOW)# time.sleep(self.TIMING_CLOCK_LOW / 1000000)## # 转换补码HX711输出是二进制补码# if raw_data 0x800000:# raw_data - 0x1000000## return raw_datareturn int(random.uniform(1000, 50000))except Exception as e:logger.error(f读取原始数据失败: {e})self._error_count 1if self._error_count self._max_errors:logger.critical(传感器错误过多进入保护模式)self._is_initialized Falsereturn Nonedef read_weight(self, temperature: Optional[float] None) - Optional[WeightReading]:读取重量值Args:temperature: 环境温度用于补偿Returns:Optional[WeightReading]: 重量读数对象if not self._is_initialized:logger.error(传感器未初始化)return None# 多次采样取平均samples: List[float] []for _ in range(config.sensor.sample_count):raw_value self._read_raw_value()if raw_value is None:continue# 减去零点偏移adjusted_value raw_value - self._offset# 转换为重量weight adjusted_value / self._reference_unit / 1000.0 # 转换为kg# 温度补偿if temperature is not None:weight self._apply_temperature_compensation(weight, temperature)# 限制范围weight max(config.min_weight, min(config.max_weight, weight))samples.append(weight)time.sleep(config.sensor.sample_interval)if len(samples) config.sensor.sample_count // 2:logger.error(有效样本不足)return None# 计算平均重量avg_weight sum(samples) / len(samples)# 应用数字滤波filtered_weight self._apply_filter(avg_weight)# 计算数据质量quality self._calculate_data_quality(samples)# 创建读数对象reading WeightReading(timestamptime.time(),raw_valueint(sum(samples) / len(samples) * self._reference_unit * 1000),weight_kground(filtered_weight, 3),is_validquality 0.5,qualityquality,temperaturetemperature)self._last_reading readingself._readings_count 1logger.debug(f重量读数: 原始{reading.raw_value}, f重量{filtered_weight:.3f}kg, 质量{quality:.2f})return readingdef _apply_temperature_compensation(self, weight: float, temperature: float) - float:应用温度补偿金属应变片受温度影响需要补偿Args:weight: 原始重量temperature: 当前温度Returns:float: 补偿后的重量if self._reference_temperature is None:return weight# 计算温度差temp_diff temperature - self._reference_temperature# 温度补偿系数需要根据实际传感器校准compensation_factor 1.0 (self._temperature_coefficient * temp_diff)# 限制补偿范围compensation_factor max(0.95, min(1.05, compensation_factor))compensated_weight weight * compensation_factorlogger.debug(f温度补偿: 温度{temperature}°C, f温差{temp_diff:.1f}°C, f补偿系数{compensation_fa利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛
编写程序实现智能书包重量检测,超重时提示“减轻书本”,保护脊椎。
发布时间:2026/6/3 18:42:02
智能书包重量检测与脊椎保护系统一、实际应用场景描述现代中小学生课业负担日益加重书包重量往往超过儿童身体承受的安全范围。据医学研究表明儿童书包重量不应超过体重的10%-15%否则长期背负会导致脊柱侧弯、驼背、肌肉劳损等健康问题。典型场景- 小学生小明体重25kg每天背着4-5公斤的书包上学内含语文、数学、英语、科学等课本加上作业本、文具盒、水壶等物品- 初中生小红体重40kg面临中考压力书包重量达到7-8公斤包含各种教辅资料- 高中生小华体重50kg书包重量超过8公斤长期单肩背负导致肩膀高低不平传统解决方案的局限- 家长凭经验判断缺乏客观数据支撑- 学校无检测设备无法实时监控- 学生自身无感知直到出现疼痛才意识到问题- 没有实时提醒机制无法及时卸重- 缺乏历史数据无法追踪书包重量变化趋势- 无个性化建议不同体重学生使用统一标准本系统功能- 实时检测书包重量精度±10g- 根据学生体重计算安全负重阈值- 超重时语音提示减轻书本- 可视化显示重量状态和健康建议- 记录每日书包重量历史- 脊椎健康风险评估与个性化建议二、引入痛点1. 健康隐患严重过重书包导致儿童脊柱发育畸形据统计我国中小学生脊柱侧弯发病率已达5%-10%2. 主观判断不准家长和老师难以准确估算书包重量容易低估实际负重3. 缺乏实时监控学生在校期间无人监督书包重量长时间背负超限物品4. 即时反馈缺失没有实时提醒机制学生往往在感到疲劳时才发现问题5. 数据记录空白缺乏历史数据追踪无法评估书包重量变化趋势6. 个性化缺失不同年龄、体重的学生使用统一标准不够科学合理7. 预防意识薄弱学生和家长对书包重量的健康影响认识不足8. 家校联动困难学校与家长缺乏有效的书包重量沟通渠道三、核心逻辑讲解重量安全标准学生体重(kg) 安全负重(kg) 最大负重(kg) 健康风险20-25 2.0-3.0 3.5-4.0 低风险25-35 3.0-4.5 4.5-6.0 中低风险35-45 4.5-6.0 6.0-7.5 中风险45-55 6.0-7.5 7.5-9.0 中高风险55 7.5-9.0 9.0-12.0 高风险压力传感器HX711特性HX711是一款24位A/D转换器专用于电子秤设计- 输入电压范围±20mV- 输出数据速率10Hz或80Hz- 内置放大器和稳压器- 差分输入抗干扰能力强- 典型连接方式Load Cell → HX711 → MCU核心算法流程1. 重量采集- HX711读取24位原始数据- 多次采样取平均值- 温度补偿和线性校准2. 用户配置- 输入学生体重- 计算个性化安全阈值- 设置提醒灵敏度3. 实时分析- 重量与阈值比较- 连续超重检测防误报- 趋势分析和预测4. 多级提醒- 绿色安全范围- 黄色接近上限- 红色超重报警- 语音提示减轻书本5. 数据记录- 时间戳记录- 重量历史存储- 健康报告生成关键技术难点及解决方案难点 解决方案传感器零点漂移 上电自动归零定期校准温度影响精度 温度补偿算法NTC热敏电阻机械振动干扰 数字滤波软件去抖不同书包差异 用户自定义校准系数误报问题 连续3次超重确认机制功耗优化 休眠唤醒机制动态采样四、代码模块化含安全设计项目结构smart_backpack/├── main.py # 主程序入口├── sensors/ # 传感器模块│ ├── __init__.py│ ├── hx711_weight.py # HX711重量传感器驱动│ └── calibration.py # 校准模块├── core/ # 核心逻辑模块│ ├── __init__.py│ ├── weight_analyzer.py # 重量分析引擎│ ├── health_assessor.py # 健康评估模块│ └── alert_manager.py # 提醒管理器├── actuators/ # 执行器模块│ ├── __init__.py│ ├── lcd_display.py # LCD显示屏控制│ ├── voice_prompt.py # 语音提示模块│ ├── led_indicator.py # LED指示灯控制│ └── buzzer.py # 蜂鸣器控制├── storage/ # 数据存储模块│ ├── __init__.py│ ├── data_logger.py # 数据记录器│ └── report_generator.py # 报告生成器├── config.py # 系统配置├── requirements.txt # 依赖清单├── README.md # 项目文档└── utils/├── __init__.py├── logger.py # 日志工具└── decorators.py # 装饰器工具核心代码实现1. config.py系统配置智能书包重量检测与脊椎保护系统配置文件包含传感器、执行器、健康标准等所有配置参数from dataclasses import dataclass, fieldfrom typing import List, Optional, Dict, Any, Tuplefrom enum import Enum, autofrom pathlib import Pathimport os# 确保配置目录存在Path(config).mkdir(parentsTrue, exist_okTrue)class WeightStatus(Enum):重量状态枚举SAFE auto() # 安全范围WARNING auto() # 警告接近上限OVERWEIGHT auto() # 超重CRITICAL auto() # 严重超重class AlertLevel(Enum):提醒级别枚举NONE auto() # 无提醒MILD auto() # 轻度提醒MODERATE auto() # 中度提醒URGENT auto() # 紧急提醒dataclassclass SensorConfig:传感器配置# HX711配置hx711_dt_pin: int 5 # 数据引脚hx711_sck_pin: int 6 # 时钟引脚hx711_reference_unit: float 1.0 # 参考单位校准系数hx711_offset: int 0 # 零点偏移hx711_gain: int 128 # 增益设置128或64# 采样配置sample_count: int 10 # 采样次数sample_interval: float 0.1 # 采样间隔秒filter_window: int 5 # 滤波窗口大小# 校准配置calibration_weight: float 1.0 # 校准砝码重量kgcalibration_samples: int 20 # 校准采样次数# 模拟模式开发测试用simulation_mode: bool Truedataclassclass UserConfig:用户配置# 学生信息student_name: str 学生student_weight: float 30.0 # 学生体重kgstudent_age: int 10 # 学生年龄# 安全阈值配置safe_load_ratio: float 0.15 # 安全负重比例体重的15%max_load_ratio: float 0.20 # 最大负重比例体重的20%warning_threshold: float 0.85 # 警告阈值安全上限的85%# 个性化设置sensitivity: float 1.0 # 敏感度0.5-2.0reminder_interval: float 30.0 # 提醒间隔秒enable_voice: bool True # 启用语音提醒enable_display: bool True # 启用显示enable_led: bool True # 启用LED指示dataclassclass HealthThresholds:健康阈值配置# 按年龄段的健康建议age_groups: Dict[Tuple[int, int], Dict[str, Any]] field(default_factorylambda: {(6, 8): {safe_min: 1.5, safe_max: 3.0, warning_msg: 低年级学生书包不宜过重},(9, 11): {safe_min: 2.0, safe_max: 4.5, warning_msg: 中年级学生注意减负},(12, 14): {safe_min: 3.0, safe_max: 6.0, warning_msg: 高年级学业繁重合理整理书包},(15, 18): {safe_min: 4.0, safe_max: 8.0, warning_msg: 初高中生注意脊柱健康}})# 脊椎健康风险评估spine_risk_levels: Dict[str, Tuple[float, float]] field(default_factorylambda: {低风险: (0.0, 0.12),中低风险: (0.12, 0.15),中风险: (0.15, 0.18),中高风险: (0.18, 0.22),高风险: (0.22, 1.0)})dataclassclass AlertConfig:提醒配置# LCD配置lcd_enabled: bool Truelcd_i2c_address: int 0x27lcd_columns: int 16lcd_rows: int 2# LED配置led_enabled: bool Trueled_green_pin: int 17led_yellow_pin: int 27led_red_pin: int 22# 蜂鸣器配置buzzer_enabled: bool Truebuzzer_pin: int 23buzzer_frequency_safe: int 1000buzzer_frequency_warning: int 1500buzzer_frequency_overweight: int 2000# 语音配置voice_enabled: bool Truevoice_volume: int 80 # 音量百分比voice_language: str zh-CN# 提醒模式vibration_enabled: bool False # 震动提醒可选配件vibration_pin: int 24dataclassclass StorageConfig:存储配置# 数据记录log_enabled: bool Truelog_directory: str data/logslog_filename: str weight_history.csvlog_interval: float 300.0 # 记录间隔秒# 历史数据max_history_days: int 30export_enabled: bool Trueexport_format: str csv# 报告配置weekly_report: bool Truemonthly_report: bool Truedataclassclass SystemConfig:系统总配置sensor: SensorConfig field(default_factorySensorConfig)user: UserConfig field(default_factoryUserConfig)health: HealthThresholds field(default_factoryHealthThresholds)alert: AlertConfig field(default_factoryAlertConfig)storage: StorageConfig field(default_factoryStorageConfig)# 系统设置debug_mode: bool Falselog_level: str INFOlog_file: str smart_backpack.log# 安全限制min_weight: float 0.0max_weight: float 20.0 # 最大可测重量min_student_weight: float 15.0max_student_weight: float 100.0def __post_init__(self):# 确保目录存在for directory in [self.storage.log_directory, data, reports]:Path(directory).mkdir(parentsTrue, exist_okTrue)# 计算实际阈值self._calculate_thresholds()def _calculate_thresholds(self):根据学生体重计算实际重量阈值weight self.user.student_weight# 根据年龄组调整for (age_min, age_max), params in self.health.age_groups.items():if age_min self.user.student_age age_max:self.user.safe_load_ratio params[safe_max] / weight if weight 0 else 0.15break# 计算各级阈值self.safe_threshold weight * self.user.safe_load_ratio * self.user.sensitivityself.warning_threshold self.safe_threshold * self.user.warning_thresholdself.max_threshold weight * self.user.max_load_ratio * self.user.sensitivitylogger.info(f阈值计算完成: 安全{self.safe_threshold:.2f}kg, f警告{self.warning_threshold:.2f}kg, f最大{self.max_threshold:.2f}kg)# 全局配置实例config SystemConfig()# 重量状态颜色映射STATUS_COLORS {WeightStatus.SAFE: (0, 255, 0), # 绿色WeightStatus.WARNING: (255, 255, 0), # 黄色WeightStatus.OVERWEIGHT: (255, 165, 0), # 橙色WeightStatus.CRITICAL: (255, 0, 0) # 红色}# 提醒级别消息ALERT_MESSAGES {AlertLevel.NONE: ,AlertLevel.MILD: 书包略重请注意,AlertLevel.MODERATE: 书包较重建议减负,AlertLevel.URGENT: 书包超重请减轻书本}# 脊椎健康建议SPINE_HEALTH_ADVICE {低风险: 书包重量适中继续保持良好习惯,中低风险: 书包稍重可适当减少不必要物品,中风险: 书包偏重建议每日检查书包内容,中高风险: 书包过重请及时减负保护脊椎,高风险: 书包严重超重立即停止背负咨询医生}# 年级对应建议AGE_GROUP_ADVICE {(6, 8): 低年级同学只带当天需要的课本使用轻便文具盒,(9, 11): 中年级同学学会整理书包定期清理不需要的物品,(12, 14): 高年级同学合理安排学习计划避免携带过多参考资料,(15, 18): 初高中同学使用拉杆书包分担重量注意双肩背负}# 工厂函数def create_config() - SystemConfig:创建配置实例return configdef update_user_config(name: str None, weight: float None, age: int None):更新用户配置global configif name:config.user.student_name nameif weight:config.user.student_weight weightconfig._calculate_thresholds()if age:config.user.student_age ageconfig._calculate_thresholds()logger None # 将在main中初始化2. sensors/hx711_weight.pyHX711重量传感器模块HX711重量传感器模块24位A/D转换器专用于电子秤和压力检测支持校准、滤波、温度补偿等功能import timeimport loggingimport randomfrom typing import Optional, List, Tuple, Dequefrom dataclasses import dataclass, fieldfrom enum import Enum, autofrom collections import dequefrom config import config, SensorConfiglogger logging.getLogger(__name__)class SensorError(Exception):传感器异常类passclass CalibrationError(SensorError):校准异常类passclass GainChannel(Enum):HX711增益通道CHANNEL_A_GAIN_128 1 # 通道A增益128默认CHANNEL_A_GAIN_64 3 # 通道A增益64CHANNEL_B_GAIN_32 2 # 通道B增益32dataclassclass WeightReading:重量读数数据类timestamp: floatraw_value: intweight_kg: floatis_valid: bool Truequality: float 1.0 # 数据质量分数 0-1temperature: Optional[float] None # 温度补偿用class HX711WeightSensor:HX711 24位重量传感器驱动特性- 24位高精度A/D转换- 内置可编程增益放大器- 差分输入抗干扰能力强- 支持温度补偿- 数字滤波和校准- 模拟模式支持开发测试用工作原理1. 称重传感器应变片将重量转换为微伏级电压2. HX711内部PGA将信号放大3. 24位Σ-Δ ADC将模拟信号转换为数字量4. 通过参考单位和零点偏移计算实际重量接线方式HX711 → Raspberry PiVCC → 3.3V/5VGND → GNDDT(Data) → GPIO5SCK(Clock)→ GPIO6E(红) → 传感器红线E-(黑) → 传感器黑线A(绿) → 传感器绿线A-(白) → 传感器白线# HX711命令码CMD_READ_CH_A_128 0x01 # 读通道A增益128CMD_READ_CH_A_64 0x03 # 读通道A增益64CMD_READ_CH_B_32 0x02 # 读通道B增益32# 时序参数微秒TIMING_CLOCK_HIGH 1TIMING_CLOCK_LOW 1TIMING_READ_DELAY 1def __init__(self, dt_pin: int 5, sck_pin: int 6, gain: int 128):初始化HX711传感器Args:dt_pin: 数据引脚GPIO编号sck_pin: 时钟引脚GPIO编号gain: 增益设置128或64self.dt_pin dt_pinself.sck_pin sck_pinself.gain gain# 校准参数self._reference_unit config.sensor.hx711_reference_unitself._offset config.sensor.hx711_offset# 滤波缓冲区self._filter_buffer: Deque[float] deque(maxlenconfig.sensor.filter_window)# 状态管理self._is_initialized Falseself._is_ready Falseself._last_reading: Optional[WeightReading] None# 模拟模式self._simulation_mode config.sensor.simulation_modeself._simulation_base_weight 2.0 # 模拟基础重量# 统计信息self._readings_count 0self._error_count 0self._max_errors 10# 温度补偿参数self._temperature_coefficient -0.02 # 每度温度变化的影响%/°Cself._reference_temperature 25.0 # 参考温度logger.info(fHX711重量传感器初始化: DT引脚{dt_pin}, fSCK引脚{sck_pin}, 增益{gain})def initialize(self) - bool:初始化传感器硬件Returns:bool: 初始化是否成功try:if self._simulation_mode:logger.info(HX711传感器运行在模拟模式)self._is_initialized Trueself._is_ready Truereturn True# 实际硬件初始化# import RPi.GPIO as GPIO# self.GPIO GPIO# self.GPIO.setmode(GPIO.BCM)# self.GPIO.setup(self.dt_pin, GPIO.IN, pull_up_downGPIO.PUD_UP)# self.GPIO.setup(self.sck_pin, GPIO.OUT)# self.GPIO.output(self.sck_pin, GPIO.LOW)# 等待传感器稳定time.sleep(0.5)# 检查传感器是否就绪DT引脚应为高电平# ready self.GPIO.input(self.dt_pin)# if ready:# logger.warning(传感器未就绪可能有重物压着)self._is_initialized Trueself._is_ready Truelogger.info(HX711重量传感器初始化成功)return Trueexcept Exception as e:logger.error(fHX711传感器初始化失败: {e})return Falsedef _set_gain(self, gain: int):设置增益if gain 128:self._gain_channel GainChannel.CHANNEL_A_GAIN_128elif gain 64:self._gain_channel GainChannel.CHANNEL_A_GAIN_64elif gain 32:self._gain_channel GainChannel.CHANNEL_B_GAIN_32else:raise ValueError(f不支持的增益值: {gain})def _read_raw_value(self) - Optional[int]:读取24位原始数据HX711通信协议1. 等待DT引脚变低数据准备好2. 发送24个时钟脉冲在每个上升沿读取数据位3. 发送额外的1-3个时钟脉冲选择下一次的增益通道Returns:Optional[int]: 24位原始数据有符号if not self._is_initialized:logger.error(传感器未初始化)return Nonetry:if self._simulation_mode:# 模拟数据模拟不同重量和噪声time.sleep(0.1)# 模拟重量波动weight_variation random.uniform(-0.1, 0.1)noise random.uniform(-50, 50)# 模拟一些日常场景import mathtime_factor (time.time() % 60) / 60 # 0-1循环# 模拟放书包前5秒重量增加if time_factor 0.08:loading_progress time_factor / 0.08simulated_weight self._simulation_base_weight * loading_progress# 模拟稳定负重elif time_factor 0.85:simulated_weight self._simulation_base_weight weight_variation# 模拟减重最后15秒else:unloading_progress (time_factor - 0.85) / 0.15simulated_weight self._simulation_base_weight * (1 - unloading_progress)# 转换为原始ADC值raw_value int(simulated_weight * self._reference_unit * 1000) noisereturn raw_value# 实际硬件读取# import RPi.GPIO as GPIO# 等待数据准备好DT变低# timeout 1000 # 超时计数# while self.GPIO.input(self.dt_pin) and timeout 0:# time.sleep(0.001)# timeout - 1## if timeout 0:# logger.warning(等待数据就绪超时)# return None# 读取24位数据# raw_data 0# for _ in range(24):# self.GPIO.output(self.sck_pin, GPIO.HIGH)# time.sleep(self.TIMING_CLOCK_HIGH / 1000000)# raw_data (raw_data 1) | self.GPIO.input(self.dt_pin)# self.GPIO.output(self.sck_pin, GPIO.LOW)# time.sleep(self.TIMING_CLOCK_LOW / 1000000)## # 选择下一个增益通道# extra_clocks self._gain_channel.value# for _ in range(extra_clocks):# self.GPIO.output(self.sck_pin, GPIO.HIGH)# time.sleep(self.TIMING_CLOCK_HIGH / 1000000)# self.GPIO.output(self.sck_pin, GPIO.LOW)# time.sleep(self.TIMING_CLOCK_LOW / 1000000)## # 转换补码HX711输出是二进制补码# if raw_data 0x800000:# raw_data - 0x1000000## return raw_datareturn int(random.uniform(1000, 50000))except Exception as e:logger.error(f读取原始数据失败: {e})self._error_count 1if self._error_count self._max_errors:logger.critical(传感器错误过多进入保护模式)self._is_initialized Falsereturn Nonedef read_weight(self, temperature: Optional[float] None) - Optional[WeightReading]:读取重量值Args:temperature: 环境温度用于补偿Returns:Optional[WeightReading]: 重量读数对象if not self._is_initialized:logger.error(传感器未初始化)return None# 多次采样取平均samples: List[float] []for _ in range(config.sensor.sample_count):raw_value self._read_raw_value()if raw_value is None:continue# 减去零点偏移adjusted_value raw_value - self._offset# 转换为重量weight adjusted_value / self._reference_unit / 1000.0 # 转换为kg# 温度补偿if temperature is not None:weight self._apply_temperature_compensation(weight, temperature)# 限制范围weight max(config.min_weight, min(config.max_weight, weight))samples.append(weight)time.sleep(config.sensor.sample_interval)if len(samples) config.sensor.sample_count // 2:logger.error(有效样本不足)return None# 计算平均重量avg_weight sum(samples) / len(samples)# 应用数字滤波filtered_weight self._apply_filter(avg_weight)# 计算数据质量quality self._calculate_data_quality(samples)# 创建读数对象reading WeightReading(timestamptime.time(),raw_valueint(sum(samples) / len(samples) * self._reference_unit * 1000),weight_kground(filtered_weight, 3),is_validquality 0.5,qualityquality,temperaturetemperature)self._last_reading readingself._readings_count 1logger.debug(f重量读数: 原始{reading.raw_value}, f重量{filtered_weight:.3f}kg, 质量{quality:.2f})return readingdef _apply_temperature_compensation(self, weight: float, temperature: float) - float:应用温度补偿金属应变片受温度影响需要补偿Args:weight: 原始重量temperature: 当前温度Returns:float: 补偿后的重量if self._reference_temperature is None:return weight# 计算温度差temp_diff temperature - self._reference_temperature# 温度补偿系数需要根据实际传感器校准compensation_factor 1.0 (self._temperature_coefficient * temp_diff)# 限制补偿范围compensation_factor max(0.95, min(1.05, compensation_factor))compensated_weight weight * compensation_factorlogger.debug(f温度补偿: 温度{temperature}°C, f温差{temp_diff:.1f}°C, f补偿系数{compensation_fa利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛