syssi / esphome-ant-bms

ESPHome component to monitor and control a ANT-BMS via UART
Apache License 2.0
54 stars 13 forks source link

Decode v2021 frames #52

Open syssi opened 1 year ago

syssi commented 1 year ago

Battery types

0xfaf1 Ternary Lithium    
0xfaf2 Lithium Iron Phosphate    
0xfaf3 Lithium Titanate
0xfaf4 Custom

Battery status

0 Unknown
1 Idle
2 Charge
3 Discharge
4 Standby
5 Error

Charge Mosfet Status

0    Off
1    On
2    Cell overvoltage
3    Overcurrent protection
4    Battery full
5    Battery overvoltage
6    Battery overtemperature
7    Power overtemperature
8    Current exception
9    Balancer cable missing
10   Board overtemperature
11   Reserved
12   Open failed
13   Discharge Mosfet Exception
14   Waiting
15   Manual off
16   Two level exceed voltage
17   Low temperature protection
18   Voltage difference exceeded
19   Reserved
20   Self Detect Error

Discharge Mosfet Status

0    Off
1    On
2    Cell undervoltage
3    Overcurrent protection
4    Two current exceeded
5    Battery overvoltage
6    Battery overtemperature
7    Power overtemperature
8    Current exception
9    Balancer cable missing
10   Board overtemperature
11   Charge open
12   Short circuit protection
13   Discharge Mosfet Exception
14   Open failed
15   Manual off
16   Two level low voltage
17   Low temperature protection
18   Voltage difference exceeded
19   Self Detect Error
pwilkowski commented 6 months ago

This a proper way to decode new style frames, maybe you will find it useful: I happen to have entire code in C# including sending commands for new style ant bmses.

 public static RegisterData AntProtocol_FixedParse(byte[] dataBuf)
    {
        RegisterData registerData = new RegisterData();

        registerData.MsgType = 1;
        registerData.SysOperationAuth = dataBuf[6];
        registerData.SystemState = dataBuf[7];
        registerData.Temperature_Num = dataBuf[8];
        registerData.PACK_Cell_Num = dataBuf[9];
        registerData.ProtectMack_Bit = BitConverter.ToUInt64(dataBuf, 10);
        registerData.WarningMack_Bit = BitConverter.ToUInt64(dataBuf, 18);
        registerData.PushMack_Bit = BitConverter.ToUInt64(dataBuf, 26);

        int index = 34; // Starting index
        for (byte i = 0; i < registerData.PACK_Cell_Num; ++i)
        {
            registerData.Voltage_Cell_Value[i] = BitConverter.ToUInt16(dataBuf, index);
            index += 2;
        }

        for (byte i = 0; i < registerData.Temperature_Num; ++i)
        {
            registerData.Temperature_Value[i] = BitConverter.ToInt16(dataBuf, index);
            index += 2;
        }

        registerData.Temperature_MOS = BitConverter.ToInt16(dataBuf, index); index += 2;
        registerData.Temperature_Balance = BitConverter.ToInt16(dataBuf, index); index += 2;
        registerData.Voltage_Pack = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Current_Value = BitConverter.ToInt16(dataBuf, index); index += 2;
        registerData.Pack_SOC = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Pack_SOH = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.DIS_MOS_State = dataBuf[index++];
        registerData.CH_MOS_State = dataBuf[index++];
        registerData.Balance_State = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Pack_Physics_AH = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Pack_Remain_AH = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Pack_All_AH = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Pack_Power = BitConverter.ToInt32(dataBuf, index); index += 4;
        registerData.All_Timer_ms = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Balance_State_Bit = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Voltage_Cell_Max_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_Cell_Max_Pos = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_Cell_Min_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_Cell_Min_Pos = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_Cell_Difference = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_Cell_Average_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_DS_Value = BitConverter.ToInt16(dataBuf, index); index += 2;
        registerData.Voltage_DIS_MOS_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_CH_MOS_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Voltage_NH_MOS_Value = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.PackCellType = BitConverter.ToUInt16(dataBuf, index); index += 2;
        registerData.Pack_All_DisAH = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.Pack_All_ChAH = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.All_DisTimer_s = BitConverter.ToUInt32(dataBuf, index); index += 4;
        registerData.All_ChTimer_s = BitConverter.ToUInt32(dataBuf, index); index += 4;

        if (dataBuf[5] > registerData.PACK_Cell_Num * 2 + registerData.Temperature_Num * 2 + 106)
        {
            registerData.CHG_duration = BitConverter.ToUInt32(dataBuf, index); index += 4;
            registerData.CHG_interval = BitConverter.ToUInt32(dataBuf, index); index += 4;
            registerData.CT_remaining = BitConverter.ToUInt16(dataBuf, index); index += 2;
            registerData.RT_discharge = BitConverter.ToUInt16(dataBuf, index); index += 2;
        }
        else if (dataBuf[2] == 18 || dataBuf[2] == 66) {
            registerData.MsgType = 2;
            byte[] numArray123 = new byte[16];
            byte num324 = dataBuf[2];
            ushort num325 = (ushort) (((uint) (ushort) dataBuf[4] << 8) + (uint) dataBuf[3]);
            byte num326 = dataBuf[5];
            ushort[] numArray124 = new ushort[256];
            for (int newIndex = 0; newIndex < (int) num326; newIndex += 2)
            {
                ushort num327 = (ushort) ((uint) (ushort) ((uint) (ushort) dataBuf[newIndex + 7] << 8) + (uint) dataBuf[newIndex + 6]);
                numArray124[(newIndex + (int) num325) / 2] = num327;
            }
            registerData.MsgData = numArray124;
        }

        if (dataBuf[2] == byte.MaxValue) {
            ushort num328 = (ushort) (((uint) (ushort) dataBuf[11] << 8) + (uint) dataBuf[12]);
            byte[] numArray = new byte[16]
            {
                (byte) ((uint) dataBuf[2] >> 4),
                (byte) ((uint) dataBuf[2] & 15U),
                (byte) ((uint) dataBuf[3] >> 4),
                (byte) ((uint) dataBuf[3] & 15U),
                (byte) ((uint) dataBuf[4] >> 4),
                (byte) ((uint) dataBuf[4] & 15U),
                (byte) ((uint) dataBuf[5] >> 4),
                (byte) ((uint) dataBuf[5] & 15U),
                (byte) ((uint) dataBuf[6] >> 4),
                (byte) ((uint) dataBuf[6] & 15U),
                (byte) ((uint) dataBuf[7] >> 4),
                (byte) ((uint) dataBuf[7] & 15U),
                (byte) ((uint) dataBuf[8] >> 4),
                (byte) ((uint) dataBuf[8] & 15U),
                (byte) ((uint) dataBuf[9] >> 4),
                (byte) ((uint) dataBuf[9] & 15U)
            };
            registerData.Warning = (int) num328;
        }

        return registerData;
    }