今天开发一个小设备,需要显示一下当前电量,从ADC中获取到了原始采样值,换算出来电压值以后就不想搬砖了。
所以,找个免费劳动力,把后面的代码写一下吧。
直接下任务,不用先打招呼,也不用客套,甚至你都不需要给他讲太细,骂着他也好好的给你执行。
using System;class Program{static void Main(string[] args){// 示例输入电压值double voltage = 3.7; // 单位: Vdouble soc = CalculateSOC(voltage);Console.WriteLine($"电压: {voltage}V, SOC: {soc:F2}%");}static double CalculateSOC(double voltage){// 常见锂电池开路电压与SOC的近似关系// 数据可以根据具体电池调整,这里用一个常见的线性插值示例double[] voltagePoints = { 3.0, 3.2, 3.4, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2 }; // 电压点double[] socPoints = { 0, 10, 20, 40, 50, 60, 70, 85, 95, 100 }; // 对应SOC点 (%)// 边界处理if (voltage <= voltagePoints[0]) return socPoints[0];if (voltage >= voltagePoints[voltagePoints.Length - 1]) return socPoints[socPoints.Length - 1];// 插值计算SOCfor (int i = 0; i < voltagePoints.Length - 1; i++){if (voltage >= voltagePoints[i] && voltage <= voltagePoints[i + 1]){// 线性插值公式double slope = (socPoints[i + 1] - socPoints[i]) / (voltagePoints[i + 1] - voltagePoints[i]);return socPoints[i] + slope * (voltage - voltagePoints[i]);}}// 默认返回0(正常情况下不会到达这里)return 0;}}
不说太细还真不行,因为他能力太强了,以至于给我的是一个C#代码,而需要的是一个跑在单片机上的C语言代码。我只能骂他一下了。
#include <stdio.h>int calculateSOC(int voltage);int main() {// 示例输入电压值(单位: mV)int voltage = 3700; // 3.7V = 3700mVint soc = calculateSOC(voltage);printf("电压: %dmV, SOC: %d%%n", voltage, soc);return 0;}int calculateSOC(int voltage) {// 使用整数表示电压 (单位: mV) 和 SOC (%)int voltagePoints[] = { 3000, 3200, 3400, 3600, 3700, 3800, 3900, 4000, 4100, 4200 }; // 电压点 (单位: mV)int socPoints[] = { 0, 10, 20, 40, 50, 60, 70, 85, 95, 100 }; // 对应SOC点 (%)int numPoints = sizeof(voltagePoints) / sizeof(voltagePoints[0]);// 边界处理if (voltage <= voltagePoints[0]) return socPoints[0];if (voltage >= voltagePoints[numPoints - 1]) return socPoints[numPoints - 1];// 插值计算SOCfor (int i = 0; i < numPoints - 1; i++) {if (voltage >= voltagePoints[i] && voltage <= voltagePoints[i + 1]) {// 线性插值公式,完全用整数计算int deltaVoltage = voltagePoints[i + 1] - voltagePoints[i];int deltaSOC = socPoints[i + 1] - socPoints[i];int voltageOffset = voltage - voltagePoints[i];// 计算插值的SOC,返回整数return socPoints[i] + (voltageOffset * deltaSOC) / deltaVoltage;}}// 默认返回0(正常情况下不会到达这里)return 0;}
他懂得蛮多的,一听说是单片机,不单把C#语言改成了C语言,然后还知道把浮点运算全部转换成整形数来运算,提高效率。
贴心的注释,以及简单的使用教程,接口调用都码的明明白白。
电量显示似乎还有点问题,负载变化的时候,电压不稳定,电量百分百总是跳动。
以下是他的回答,我不贴图了,粘贴蚊子到这里吧。
1. 内阻模型补偿
利用电池的内阻模型,根据当前电流(I)和内阻(R)计算出补偿后的开路电压:
#include <stdio.h>int calculateSOC(int voltage, int current);int compensateVoltage(int voltage, int current, int resistance);int main() {// 示例输入,电压和电流以整数表示int voltage = 3650; // 3.65V = 3650mV (负载电压)int current = 2000; // 2000mA = 2Aint soc;// 根据电压电流计算SOCsoc = calculateSOC(voltage, current);printf("负载电压: %dmV, 电流: %dmA, SOC: %d (0.1%% 精度)n", voltage, current, soc);return 0;}// 补偿后的SOC计算int calculateSOC(int voltage, int current) {// 定义内阻值(单位: mΩ)int resistance = 50; // 内阻50mΩ,可根据电池类型调整// 补偿后的电压(估算开路电压)int compensatedVoltage = compensateVoltage(voltage, current, resistance);// 使用补偿后的电压计算SOCint voltagePoints[] = { 3000, 3200, 3400, 3600, 3700, 3800, 3900, 4000, 4100, 4200 }; // 电压点 (单位: mV)int socPoints[] = { 0, 100, 200, 400, 500, 600, 700, 850, 950, 1000 }; // 对应SOC点 (扩大10倍, 单位: 0.1%)int numPoints = sizeof(voltagePoints) / sizeof(voltagePoints[0]);// 边界处理if (compensatedVoltage <= voltagePoints[0]) return socPoints[0];if (compensatedVoltage >= voltagePoints[numPoints - 1]) return socPoints[numPoints - 1];// 插值计算SOCfor (int i = 0; i < numPoints - 1; i++) {if (compensatedVoltage >= voltagePoints[i] && compensatedVoltage <= voltagePoints[i + 1]) {int deltaVoltage = voltagePoints[i + 1] - voltagePoints[i];int deltaSOC = socPoints[i + 1] - socPoints[i];int voltageOffset = compensatedVoltage - voltagePoints[i];return socPoints[i] + (voltageOffset * deltaSOC) / deltaVoltage;}}return 0; // 默认返回0}// 电压补偿函数int compensateVoltage(int voltage, int current, int resistance) {// 使用 I * R 进行电压补偿// resistance 单位为 mΩ,current 单位为 mA,计算结果单位为 mVreturn voltage + (current * resistance) / 1000;}
2. 动态内阻调整
锂电池的内阻(R)会随着SOC和温度的变化而变化,可以通过查表或实时监控内阻调整补偿系数:
低SOC(<20%)或高SOC(>80%):内阻通常较大。
温度低时(如<0°C):内阻显著增大。
实现建议:
使用一个二维查表机制,根据SOC和温度动态调整 resistance 的值。
在上面的 compensateVoltage 函数中替换固定内阻值为动态值。
3. 时间加权平均
如果负载波动较大,可以通过时间加权平均法平滑SOC计算:
SOCsmooth=α⋅SOCnew+(1−α)⋅SOCold
其中,α 是平滑因子(0-1之间,通常取0.1到0.3)。
4. 扩展方法:结合电流积分法
对负载电流(Coulomb计数法)与电压估算法结合,可以在动态负载情况下得到更稳定的SOC值:
使用补偿后的电压计算初步SOC。
通过电流积分法对SOC进行调整(例如长期负载或高电流放电时)。
总结
通过对负载电压的补偿,可以有效减小负载变化对SOC估算的影响。结合动态内阻调整或平滑方法,能够进一步提高SOC计算的稳定性和准确性。
哎,搬砖这事以后就不能自己干。
1862