加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

用chatGPT开发电量SOC功能

11/25 13:30
787
阅读需 14 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

今天开发一个小设备,需要显示一下当前电量,从ADC中获取到了原始采样值,换算出来电压值以后就不想搬砖了。

所以,找个免费劳动力,把后面的代码写一下吧。

直接下任务,不用先打招呼,也不用客套,甚至你都不需要给他讲太细,骂着他也好好的给你执行。

using System;
class Program{    static void Main(string[] args)    {        // 示例输入电压        double voltage = 3.7; // 单位: V        double 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];
        // 插值计算SOC        for (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 = 3700mV    int 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];
    // 插值计算SOC    for (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 = 2A    int soc;
    // 根据电压电流计算SOC    soc = 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);
    // 使用补偿后的电压计算SOC    int 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];
    // 插值计算SOC    for (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,计算结果单位为 mV    return 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计算的稳定性和准确性。

哎,搬砖这事以后就不能自己干。

相关推荐

电子产业图谱

多年硬件从业经验,专注分享从研发到供应链,再到精益制造过程中的经验和感悟!