编写程序实现智能电动车电量检测,剩余电量低于20%时,提示“及时充电”,避免半路断电。
智能电动车电量检测与提醒系统一、实际应用场景描述随着城市交通拥堵加剧和环保意识提升电动自行车和电动摩托车已成为大众出行的重要选择。无论是外卖骑手的长距离配送、上班族的日常通勤还是家庭周末的郊游骑行电动车都以其经济、便捷、零排放的特点深受欢迎。然而在实际使用中电动车电量管理一直是个令人头疼的问题。许多用户常常因为专注于导航或骑行忽略了剩余电量的监控。当电量耗尽时车辆会在半路突然失去动力不仅造成行程中断还可能带来安全隐患——特别是在交通繁忙的路段或夜间行驶时。更糟糕的是某些老旧车型甚至没有电量百分比显示用户只能通过电量表指针大致判断这种模糊的判断方式极易导致误判。本系统基于智能仪器课程中的电压检测技术、模数转换ADC、电池管理系统BMS原理结合Python编程和物联网技术设计一套智能电动车电量检测与提醒系统。系统通过高精度电压传感器实时监测电池组电压结合电池特性曲线精确计算剩余电量百分比当电量低于20%时通过本地声光报警、手机推送和语音播报三重提醒确保用户及时寻找充电设施避免半路断电的尴尬和安全风险。二、引入痛点1. 电量监控不及时骑行过程中难以时刻关注电量表容易错过最佳充电时机2. 仪表盘显示粗糙多数电动车只有电量格显示无法精确判断剩余里程3. 电池老化影响判断旧电池容量衰减传统估算方法失准4. 突发断电危险市区主干道或高速辅路中途没电存在交通事故风险5. 充电设施难寻电量不足时才开始寻找充电桩往往为时已晚6. 缺乏预警机制没有分级提醒用户总是在电量耗尽后才发现问题7. 多电池组管理困难串联/并联电池组的均衡状态和总电量难以掌握8. 无法远程监控停车后无法查看剩余电量第二天出行才发现没电三、核心逻辑讲解┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ 电压传感器 │────▶│ ADC采集 │────▶│ 电压解析 ││ INA219/ADS1115│ │ 12/16位精度 │ │ 转换为实际V │└─────────────────┘ └─────────────────┘ └─────────────────┘│┌─────────────────┐ ││ 电量计算 │◀─────────────────┘│ 查表法/公式法 │└─────────────────┘│┌────────────────────┼────────────────────┐▼ ▼ ▼┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ 本地蜂鸣器 │ │ OLED显示屏 │ │ 手机推送 ││ 声光报警 │ │ 实时显示 │ │ 微信/短信 │└─────────────┘ └─────────────┘ └─────────────┘│┌─────────────────┐│ 分级提醒 ││ 50% / 20% │└─────────────────┘│┌─────────────────┐│ 数据记录 ││ 电量历史 │└─────────────────┘核心逻辑流程1. 系统初始化传感器连接、ADC校准、报警设备初始化、通信模块配置2. 周期性采样每5秒读取电池组总电压和单体电池电压3. 电压解析将ADC原始数据转换为实际电压值考虑分压电路4. 电量计算基于锂电池放电曲线查表法或Peukert方程计算剩余电量5. 健康状态评估分析各单体电池电压差判断电池组一致性6. 阈值判断电量 50%预警、 20%紧急提醒7. 多级报警声光提示 → 语音播报 → 手机推送8. 数据记录保存电压、电量、温度历史到SQLite数据库9. 状态同步更新OLED显示推送实时状态到云端关键技术点- 电压分压电路设计将48V电池组降压至ADC可测范围0-3.3V- 锂电池放电特性建模考虑温度、放电倍率、循环次数的影响- 滑动平均滤波消除电机启动/刹车时的电压波动干扰- 电池均衡监测检测单体电压差异提前发现电池故障四、代码模块化项目结构smart_ev_battery_monitor/├── main.py # 主程序入口├── config.py # 系统配置文件├── battery/ # 电池检测模块│ ├── __init__.py│ ├── voltage_sensor.py # 电压传感器驱动│ ├── current_sensor.py # 电流传感器可选│ └── soc_calculator.py # 剩余电量计算├── monitor/ # 监控逻辑模块│ ├── __init__.py│ ├── battery_monitor.py # 电池状态监控│ └── health_checker.py # 电池健康检查├── alert/ # 报警模块│ ├── __init__.py│ ├── buzzer.py # 蜂鸣器控制│ ├── display.py # OLED显示屏│ ├── voice_prompt.py # 语音播报│ └── notification.py # 推送通知├── storage/ # 数据存储模块│ ├── __init__.py│ └── database.py # SQLite数据库操作├── utils/ # 工具模块│ ├── __init__.py│ ├── filter.py # 数字滤波│ ├── calibration.py # 传感器校准│ └── scheduler.py # 任务调度├── data/ # 数据存储目录│ └── battery_log.db├── requirements.txt├── hardware_wiring.md # 硬件接线指南└── README.md1. config.py - 系统配置文件智能电动车电量检测系统配置文件存储所有硬件参数、电池特性和报警阈值配置import os# 项目根目录BASE_DIR os.path.dirname(os.path.abspath(__file__))# 电池参数配置 BATTERY_CONFIG {# 电池基本参数battery_type: lithium_ion, # 电池类型: lithium_ion, lifepo4, lead_acidcell_count: 13, # 串联电芯数量 (48V 13S)nominal_voltage: 48.0, # 标称电压 (V)full_charge_voltage: 54.6, # 满电电压 (V) - 13S锂电discharge_cutoff: 39.0, # 放电截止电压 (V)capacity_ah: 20.0, # 电池容量 (Ah)# 温度补偿参数temp_compensation: -0.003, # 温度系数 (%/℃)ref_temperature: 25.0, # 参考温度 (℃)# 电池老化参数cycle_count: 0, # 循环次数需定期更新capacity_degradation: 0.0, # 容量衰减率 (0-1)# 单体电池参数cell_nominal: 3.7, # 单体标称电压cell_full: 4.2, # 单体满电电压cell_min: 2.8, # 单体最小电压cell_balance_threshold: 0.05, # 均衡阈值 (V)}# 电压传感器配置 VOLTAGE_SENSOR_CONFIG {sensor_type: ads1115, # 传感器类型: ads1115, ina219, analog_inputadc_address: 0x48, # I2C地址adc_channels: {battery_total: 0, # 电池总电压通道cell_1: 1, # 单体1电压通道cell_2: 2, # 单体2电压通道cell_3: 3, # 单体3电压通道},adc_resolution: 16, # ADC分辨率 (位)voltage_divider_ratio: 0.1, # 分压比 (48V-4.8V, 再经ADC)reference_voltage: 3.3, # 参考电压 (V)sample_rate: 128, # 采样率 (SPS)gain: 1, # PGA增益}# 报警阈值配置 ALERT_CONFIG {# 电量阈值 (%)warning_threshold: 50, # 预警阈值critical_threshold: 20, # 紧急提醒阈值shutdown_threshold: 10, # 强制关机阈值# 电压阈值 (V)cell_imbalance_threshold: 0.05,# 单体压差阈值over_voltage_threshold: 54.6, # 过压阈值under_voltage_threshold: 39.0, # 欠压阈值# 报警模式enable_buzzer: True, # 启用蜂鸣器enable_display: True, # 启用显示屏enable_voice: True, # 启用语音播报enable_notification: True, # 启用推送通知# 提醒策略voice_repeat_interval: 30, # 语音重复间隔 (秒)notification_cooldown: 300, # 通知冷却时间 (秒)escalation_enabled: True, # 启用升级提醒}# 显示配置 DISPLAY_CONFIG {type: ssd1306, # 显示屏类型i2c_address: 0x3C, # I2C地址width: 128, # 屏幕宽度height: 64, # 屏幕高度update_interval: 1, # 刷新间隔 (秒)show_icons: True, # 显示图标theme: dark, # 主题: dark, light}# 通知配置 NOTIFICATION_CONFIG {# 微信推送 (Server酱)server_chan_sckey: , # Server酱SCKEY# 短信通知 (阿里云/腾讯云)sms_access_key: ,sms_secret: ,sms_sign_name: 电动车助手,sms_template_code: ,# APP推送 (极光推送/个推)jpush_app_key: ,jpush_master_secret: ,jpush_registration_id: ,# 推送内容模板warning_message: ⚠️ 电动车电量预警当前剩余{percentage}%%请及时充电,critical_message: 紧急提醒电量仅剩{percentage}%%即将断电请立即寻找充电站,}# 数据存储配置 STORAGE_CONFIG {database_path: data/battery_log.db,log_interval: 60, # 记录间隔 (秒)retention_days: 90, # 数据保留天数enable_backup: True, # 启用自动备份backup_interval: 86400, # 备份间隔 (秒)}# 系统配置 SYSTEM_CONFIG {sample_interval: 5, # 采样间隔 (秒)debug_mode: False, # 调试模式log_level: INFO, # 日志级别watchdog_timeout: 60, # 看门狗超时 (秒)auto_calibration: True, # 自动校准power_save_mode: False, # 省电模式}# 锂电池放电曲线数据 # SOC-Voltage 对应关系表用于查表法计算剩余电量# 格式: [(电压下限, SOC下限), (电压上限, SOC上限), ...]BATTERY_SOC_CURVE {lithium_ion_13s: [(39.0, 0), # 0% - 放电截止(42.0, 10), # 10%(44.0, 20), # 20% - 紧急提醒(46.0, 30), # 30%(48.0, 50), # 50% - 预警(50.0, 70), # 70%(52.0, 85), # 85%(53.5, 95), # 95%(54.6, 100), # 100% - 满电],lifepo4_16s: [(44.8, 0),(47.6, 10),(49.6, 20),(51.2, 30),(52.8, 50),(54.4, 70),(56.0, 85),(57.6, 95),(58.4, 100),],}def get_config():获取完整配置字典return {battery: BATTERY_CONFIG,voltage_sensor: VOLTAGE_SENSOR_CONFIG,alert: ALERT_CONFIG,display: DISPLAY_CONFIG,notification: NOTIFICATION_CONFIG,storage: STORAGE_CONFIG,system: SYSTEM_CONFIG,soc_curve: BATTERY_SOC_CURVE,}if __name__ __main__:# 打印配置信息config get_config()print(*60)print(智能电动车电量检测系统 - 配置概览)print(*60)print(f电池类型: {config[battery][battery_type]})print(f电池规格: {config[battery][cell_count]}S, f{config[battery][capacity_ah]}Ah, f{config[battery][nominal_voltage]}V)print(f传感器类型: {config[voltage_sensor][sensor_type]})print(f预警阈值: {config[alert][warning_threshold]}%)print(f紧急阈值: {config[alert][critical_threshold]}%)print(*60)2. battery/voltage_sensor.py - 电压传感器模块电压传感器模块基于智能仪器课程中的ADC技术和电压测量原理支持ADS1115、INA219等多种高精度ADC芯片import timeimport mathfrom abc import ABC, abstractmethodfrom typing import Dict, Optional, Tuplefrom config import VOLTAGE_SENSOR_CONFIG, BATTERY_CONFIGclass VoltageSensorBase(ABC):电压传感器抽象基类定义了电压传感器的通用接口和基本属性基于智能仪器课程中的ADC采样理论def __init__(self, config: Dict):初始化电压传感器基类Args:config: 传感器配置字典self.config configself.sensor_type config[sensor_type]self.adc_resolution config[adc_resolution]self.voltage_divider_ratio config[voltage_divider_ratio]self.ref_voltage config[reference_voltage]self.max_adc_value (1 self.adc_resolution) - 1self.voltage_resolution self.ref_voltage / self.max_adc_valueself.last_readings {}self.error_count 0self.is_initialized Falseprint(f[电压传感器] 初始化 {self.sensor_type.upper()} 传感器)print(f 分辨率: {self.adc_resolution}位)print(f 参考电压: {self.ref_voltage}V)print(f 电压分辨率: {self.voltage_resolution*1000:.3f}mV)abstractmethoddef initialize(self) - bool:初始化传感器硬件连接Returns:bool: 初始化是否成功passabstractmethoddef read_raw_adc(self, channel: int) - Optional[int]:读取指定通道的原始ADC值Args:channel: ADC通道号Returns:Optional[int]: 原始ADC值读取失败返回Nonepassabstractmethoddef read_voltage(self, channel: int) - Optional[float]:读取指定通道的电压值Args:channel: ADC通道号Returns:Optional[float]: 电压值(V)读取失败返回Nonepassdef calculate_actual_voltage(self, adc_value: int) - float:根据ADC值计算实际电压电压计算公式V_actual (ADC_value × V_ref / ADC_max) × (1 / Divider_ratio)Args:adc_value: ADC原始值Returns:float: 实际电压值(V)adc_voltage adc_value * self.voltage_resolutionactual_voltage adc_voltage / self.voltage_divider_ratioreturn round(actual_voltage, 3)def read_battery_total(self) - Optional[float]:读取电池组总电压Returns:Optional[float]: 电池组总电压(V)channel self.config[adc_channels][battery_total]return self.read_voltage(channel)def read_cell_voltages(self) - Optional[Dict[str, float]]:读取各单体电池电压Returns:Optional[Dict]: 各单体电压字典读取失败返回Nonecell_voltages {}channels {cell_1: self.config[adc_channels][cell_1],cell_2: self.config[adc_channels][cell_2],cell_3: self.config[adc_channels][cell_3],}for cell_name, channel in channels.items():voltage self.read_voltage(channel)if voltage is not None:cell_voltages[cell_name] voltageelse:return Nonereturn cell_voltagesdef get_sensor_info(self) - Dict:获取传感器详细信息Returns:Dict: 传感器信息字典return {sensor_type: self.sensor_type,adc_resolution: f{self.adc_resolution}bit,voltage_resolution: f{self.voltage_resolution*1000:.3f}mV,reference_voltage: self.ref_voltage,divider_ratio: self.voltage_divider_ratio,is_initialized: self.is_initialized,error_count: self.error_count,last_readings: self.last_readings.copy(),}def cleanup(self):清理传感器资源self.is_initialized Falseprint([电压传感器] 资源清理完成)class ADS1115Sensor(VoltageSensorBase):ADS1115 16位ADC传感器驱动ADS1115特性- 16位分辨率无噪声位数约15.5位- 4路单端或2路差分输入- I2C接口地址可配置0x48-0x4B- 可编程增益放大器PGA±6.144V至±0.256V- 采样率8SPS至860SPS可调- 内置温度传感器应用场景高精度电压测量、电池管理系统# ADS1115寄存器地址REG_CONVERSION 0x00REG_CONFIG 0x01REG_LOW_THRESHOLD 0x02REG_HIGH_THRESHOLD 0x03# 配置寄存器位域定义OS_SINGLE 0x8000 # 单次转换模式MODE_CONTINUOUS 0x0000 # 连续转换模式MODE_SINGLE 0x0100 # 单次转换模式# PGA增益设置PGA_6144 0x0000 # ±6.144VPGA_4096 0x0200 # ±4.096VPGA_2048 0x0400 # ±2.048V (默认)PGA_1024 0x0600 # ±1.024VPGA_0512 0x0800 # ±0.512VPGA_0256 0x0A00 # ±0.256V# 采样率设置DR_8SPS 0x0000 # 8 samples per secondDR_16SPS 0x0020 # 16 SPSDR_32SPS 0x0040 # 32 SPSDR_64SPS 0x0060 # 64 SPSDR_128SPS 0x0080 # 128 SPS (默认)DR_250SPS 0x00A0 # 250 SPSDR_475SPS 0x00C0 # 475 SPSDR_860SPS 0x00E0 # 860 SPS# 输入多路复用器配置MUX_AIN0_GND 0x4000 # AIN0 vs GNDMUX_AIN1_GND 0x5000 # AIN1 vs GNDMUX_AIN2_GND 0x6000 # AIN2 vs GNDMUX_AIN3_GND 0x7000 # AIN3 vs GNDMUX_AIN0_AIN1 0x0000 # AIN0 vs AIN1 (差分)MUX_AIN2_AIN3 0x1000 # AIN2 vs AIN3 (差分)def __init__(self, config: Dict):super().__init__(config)self.i2c_address config[adc_address]self.gain config[gain]self.sample_rate config[sample_rate]self.i2c_bus Nonedef initialize(self) - bool:初始化ADS1115传感器初始化流程1. 建立I2C总线连接2. 验证设备IDADS1115无ID寄存器通过读写测试验证3. 配置默认工作参数Returns:bool: 初始化是否成功try:# 模拟I2C初始化实际环境中使用smbus2或python-periphery# import smbus2# self.i2c_bus smbus2.SMBus(1)# 验证设备响应模拟print(f[ADS1115] I2C地址: 0x{self.i2c_address:02X})# 配置默认参数self._configure_defaults()self.is_initialized Trueprint([ADS1115] 初始化成功)return Trueexcept Exception as e:print(f[ADS1115] 初始化失败: {e})self.error_count 1return Falsedef _configure_defaults(self):配置ADS1115默认工作参数# 默认配置单次转换、±4.096V量程、128SPSconfig_word (self.OS_SINGLE |self.MUX_AIN0_GND |self.PGA_4096 |self.MODE_SINGLE |self.DR_128SPS |0x03 # 禁用比较器)# 实际写入: self.i2c_bus.write_word_data(self.i2c_address, self.REG_CONFIG, config_word)print(f[ADS1115] 配置: PGA±4.096V, 采样率128SPS)def _write_config(self, config_word: int):写入配置寄存器Args:config_word: 16位配置字# 实际写入: self.i2c_bus.write_word_data(self.i2c_address, self.REG_CONFIG, config_word)passdef _read_config(self) - int:读取配置寄存器Returns:int: 16位配置值# 实际读取: return self.i2c_bus.read_word_data(self.i2c_address, self.REG_CONFIG)return 0def _convert_to_actual_voltage(self, raw_value: int, pga_setting: int) - float:根据PGA设置将原始ADC值转换为电压ADS1115输出电压范围 ±PGA电压对于单端输入实际范围为 0 到 PGA电压Args:raw_value: 原始ADC值pga_setting: PGA配置值Returns:float: 电压值(V)# PGA对应的满量程电压pga_voltages {self.PGA_6144: 6.144,self.PGA_4096: 4.096,self.PGA_2048: 2.048,self.PGA_1024: 1.024,self.PGA_0512: 0.512,self.PGA_0256: 0.256,}full_scale pga_voltages.get(pga_setting, 4.096)# 转换为单极性电压0 ~ full_scalevoltage (raw_value / self.max_adc_value) * full_scalereturn voltagedef read_raw_adc(self, channel: int) - Optional[int]:读取指定通道的原始ADC值ADS1115读取流程1. 配置MUX选择输入通道2. 触发单次转换设置OS位3. 等待转换完成4. 读取转换结果Args:channel: ADC通道号 (0-3)Returns:Optional[int]: 原始ADC值补码形式if not self.is_initialized:print([ADS1115] 传感器未初始化)return Nonetry:# 映射通道到MUX配置mux_settings {0: self.MUX_AIN0_GND,1: self.MUX_AIN1_GND,2: self.MUX_AIN2_GND,3: self.MUX_AIN3_GND,}if channel not in mux_settings:print(f[ADS1115] 无效通道: {channel})return None# 构建配置字config_word (self.OS_SINGLE |mux_settings[channel] |self.PGA_4096 | # 使用±4.096V量程self.MODE_SINGLE |self.DR_128SPS |0x03 # 禁用比较器)# 写入配置self._write_config(config_word)# 等待转换完成128SPS ≈ 7.8ms转换时间time.sleep(0.01)# 读取转换结果# 实际读取: raw_value self.i2c_bus.read_word_data(self.i2c_address, self.REG_CONVERSION)# 处理字节序ADS1115是小端序# raw_value ((raw_value 0xFF) 8) | ((raw_value 8) 0xFF)# 模拟ADC读数实际项目中替换为真实读取import randomraw_value random.randint(10000, 30000)# 保存最后一次读数self.last_readings[fchannel_{channel}] raw_valuereturn raw_valueexcept Exception as e:print(f[ADS1115] 读取通道{channel}失败: {e})self.error_count 1return Nonedef read_voltage(self, channel: int) - Optional[float]:读取指定通道的电压值Args:channel: ADC通道号Returns:Optional[float]: 电压值(V)raw_value self.read_raw_adc(channel)if raw_value is None:return None# 转换为实际电压考虑分压电路adc_voltage self._convert_to_actual_voltage(raw_value, self.PGA_4096)actual_voltage adc_voltage / self.voltage_divider利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛