今天開發(fā)一個小設(shè)備,需要顯示一下當前電量,從ADC中獲取到了原始采樣值,換算出來電壓值以后就不想搬磚了。
所以,找個免費勞動力,把后面的代碼寫一下吧。
直接下任務(wù),不用先打招呼,也不用客套,甚至你都不需要給他講太細,罵著他也好好的給你執(zhí)行。
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的近似關(guān)系
// 數(shù)據(jù)可以根據(jù)具體電池調(diào)整,這里用一個常見的線性插值示例
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 }; // 對應(yīng)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) {
// 使用整數(shù)表示電壓 (單位: 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 }; // 對應(yīng)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]) {
// 線性插值公式,完全用整數(shù)計算
int deltaVoltage = voltagePoints[i + 1] - voltagePoints[i];
int deltaSOC = socPoints[i + 1] - socPoints[i];
int voltageOffset = voltage - voltagePoints[i];
// 計算插值的SOC,返回整數(shù)
return socPoints[i] + (voltageOffset * deltaSOC) / deltaVoltage;
}
}
// 默認返回0(正常情況下不會到達這里)
return 0;
}
他懂得蠻多的,一聽說是單片機,不單把C#語言改成了C語言,然后還知道把浮點運算全部轉(zhuǎn)換成整形數(shù)來運算,提高效率。
貼心的注釋,以及簡單的使用教程,接口調(diào)用都碼的明明白白。
電量顯示似乎還有點問題,負載變化的時候,電壓不穩(wěn)定,電量百分百總是跳動。
以下是他的回答,我不貼圖了,粘貼蚊子到這里吧。
1. 內(nèi)阻模型補償
利用電池的內(nèi)阻模型,根據(jù)當前電流(I)和內(nèi)阻(R)計算出補償后的開路電壓:
#include <stdio.h>
int calculateSOC(int voltage, int current);
int compensateVoltage(int voltage, int current, int resistance);
int main() {
// 示例輸入,電壓和電流以整數(shù)表示
int voltage = 3650; // 3.65V = 3650mV (負載電壓)
int current = 2000; // 2000mA = 2A
int soc;
// 根據(jù)電壓電流計算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) {
// 定義內(nèi)阻值(單位: mΩ)
int resistance = 50; // 內(nèi)阻50mΩ,可根據(jù)電池類型調(diào)整
// 補償后的電壓(估算開路電壓)
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 }; // 對應(yīng)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
}
// 電壓補償函數(shù)
int compensateVoltage(int voltage, int current, int resistance) {
// 使用 I * R 進行電壓補償
// resistance 單位為 mΩ,current 單位為 mA,計算結(jié)果單位為 mV
return voltage + (current * resistance) / 1000;
}
2. 動態(tài)內(nèi)阻調(diào)整
鋰電池的內(nèi)阻(R)會隨著SOC和溫度的變化而變化,可以通過查表或?qū)崟r監(jiān)控內(nèi)阻調(diào)整補償系數(shù):
低SOC(<20%)或高SOC(>80%):內(nèi)阻通常較大。
溫度低時(如<0°C):內(nèi)阻顯著增大。
實現(xiàn)建議:
使用一個二維查表機制,根據(jù)SOC和溫度動態(tài)調(diào)整 resistance
的值。
在上面的 compensateVoltage
函數(shù)中替換固定內(nèi)阻值為動態(tài)值。
3. 時間加權(quán)平均
如果負載波動較大,可以通過時間加權(quán)平均法平滑SOC計算:
SOCsmooth=α?SOCnew+(1?α)?SOCold
其中,α 是平滑因子(0-1之間,通常取0.1到0.3)。
4. 擴展方法:結(jié)合電流積分法
對負載電流(Coulomb計數(shù)法)與電壓估算法結(jié)合,可以在動態(tài)負載情況下得到更穩(wěn)定的SOC值:
使用補償后的電壓計算初步SOC。
通過電流積分法對SOC進行調(diào)整(例如長期負載或高電流放電時)。
總結(jié)
通過對負載電壓的補償,可以有效減小負載變化對SOC估算的影響。結(jié)合動態(tài)內(nèi)阻調(diào)整或平滑方法,能夠進一步提高SOC計算的穩(wěn)定性和準確性。
哎,搬磚這事以后就不能自己干。