Home

Awesome

FoxESS-Canbus-Protocol

FoxESS Canbus Protocol between BMS and H series inverter (extended V1 supporting cell mV and temps)

Can bus @ 500k - all Extended ID, little endian

For the BMS to HV2600 Battery RS485 protocol, see the following repo FoxESS BMS Battery RS485

Basic Protocol

When starting up, the Foxess battery storage system unlike other systems does not have a formal adoption process, the inverter 'polls' the BMS every 1 second and if the BMS responds with a valid message then it is assumed available.

The BMS responds to the inverter polls, but only after it has sent the inverter one copy of the BMS data and all pack data will it close it's contactor and become operational.

The inverter sends a number of different requests with specific time intervals and the BMS responds with the data requested.

Frames

Received frame

0x1871 [0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]

This is sent by the inverter every 1 second and appears to be the poll for bms_send_pack_statistics.

Response frames (complete pack statistics)

IDb0b1b2b3b4b5b6b7
0x1872batt_volt_maxbatt_volt_maxbatt_volt_minbatt_volt_minmax_charge_Amax_charge_Amax_discharge_Amax_discharge_A
0x1873pack_volt_nowpack_volt_nowpack_current sensepack_current sensepack_SoC0x00pack_kwh_remainpack_kwh_remain
0x1874pack_temp_maxpack_temp_maxpack_temp_minpack_temp_mincut_mv_maxcut_mV_maxcut_mV_mincut_mV_min
0x1875BMS_tempBMS_temppack_state(note5)number_packs0x01 contact0x00cycle_countcycle_count
0x1876charge inhibit(note6)0x00cells_volts_maxcells_volts_max0x000x00cells_volts_mincells_volts_min
0x1877packError(note7)0x000x000x00batt type(note 8)0x00** See Note 3pack_id 0x10
0x1878AC_volts_maxAC_volts_max0x000x00wh_totalwh_totalwh_totalwh_total
0x1879ErrorCode(note2)FLAGS (Note1)0x000x000x000x000x000x00

** Note1: FLAGS are binary bits

bits 0,1 & 2 are status, bit 3 set if discharging, bit 4 set if charging, bit 5 is 1 if on-line, bit 7 so far always 0

bitOff-lineOn-lineOn-lineErrorNotes
(charge)(discharge)Status
bit0011002=Error, 03=ok_Discharge
bit1101104=idle?
bit2110005=ok_Charge, 06=offline
bit31011discharge flag
bit41101charge flag
bit50110operational
bit60001active error
bit70000

** Note2: Error Code are binary bits

don't now what all states mean yet, x03 generated when forced pack comms error and contactor dropped out - inverter reports bat volt volt.

bitOn-lineErrorNotes
bit00103=Pack Comms Error
bit101
bit200
bit300
bit400
bit500
bit600
bit700

** Note3: 0x1877 b6 this is firmware version, the top nibble is major version, bottom nibble is minor version however BMS and packs represent it differently i.e.

for the packs (b7 =10,20,30,40,50,60,70,80) then b6 0x1F = 0001 1111, version is v1.15, and if b6 was 0x20 = 0010 0000 then = v2.0,

for the BMS (b7=01) then convert b6 hex to decimal 0x12 = 018 , and if b6 was 0x14 then = 020

** Note4: 0x1876 cell volts min / max - these appear to be used by the inverter to populate Home Assistant sensors (0x1874 b4-b7 are the BMS cut voltages usually a steady 3,200mV hi/lo)

** Note5: 0x1875 b2 contains status for operational packs (responding) in binary so 01111111 is pack 8 not operational, 11101101 is pack 5 & 2 not operational

** Note6: 0x1876 b0 bit 0 is 1 when maxsoc is observed and/or BMS master instructs charge is not permitted. Charge is permitted if 0. This is a critical safety element for inhibiting battery charging, KH series relies on this bit and ignores 100% SoC limits

** Note7: 0x1877 b0 appears to be an error code, 0x02 when pack is in error

** Note8: 0x1877 b4 defines BMS master modules/battery type, where 0x52 is HV2600 V2 BMS master, 0x82 is HV2600 V1 slave, 0x83 is ECS4100 v1 slave, 0x84 is HV2600 V2 slave

Screenshot

Screenshot

Received frames

0x1871 [0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00]

This is sent 0.5 seconds after the bms_send_pack_statistics appears to be a bms_stop_sending (or an 'ack'), it does not elicit a BMS response

Received frames

0x1871 [0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00]

This is only sent after BMS communications is established (a valid response to a poll request) and occurs 0.5 seconds after the bms_stop_sending message, the BMS responds with BMS and each battery pack serial numbers.

Response frames (pack serial numbers)

IDb0b1b2b3b4b5b6b7
0x1881pack_id (0=BMS)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)
0x1882pack_id (0=BMS)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)
0x1883pack_id (0=BMS)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)BMS_SN (ASC)
0x1881pack_id (1=1)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)
0x1882pack_id (1=1)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)
0x1883pack_id (1=1)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN (ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)Pack1 SN(ASC)

repeats up [num_packs]

IDb0b1b2b3b4b5b6b7
0x1881pack_id (8=1)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)
0x1882pack_id (8=1)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)
0x1883pack_id (8=1)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN (ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)Pack8 SN(ASC)

Received frame

0x1871 [0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00]

This is only sent after BMS communications is established (a valid response to a poll request) and occurs 6 seconds, the BMS responds with the individual battery pack status.

Response frames (individual pack data)

IDb0b1b2b3b4b5b6b7
0x0C05Pack_1_CurrentPack_1_CurrentPack_1_avg_hitempPack_1_avg_lotemppack_1_SoCb4-7chg/dis?pack_1_voltspack_1_volts
0x0C06Pack_2_CurrentPack_2_CurrentPack_2_avg_hitempPack_2_avg_lotemppack_2_SoCb4-7chg/dis?pack_2_voltspack_2_volts
0x0C07Pack_3_CurrentPack_3_CurrentPack_3_avg_hitempPack_3_avg_lotemppack_3_SoCb4-7chg/dis?pack_3_voltspack_3_volts
0x0C08Pack_4_CurrentPack_4_CurrentPack_4_avg_hitempPack_4_avg_lotemppack_4_SoCb4-7chg/dis?pack_4_voltspack_4_volts
0x0C09Pack_5_CurrentPack_5_CurrentPack_5_avg_hitempPack_5_avg_lotemppack_5_SoCb4-7chg/dis?pack_5_voltspack_5_volts
0x0C0APack_6_CurrentPack_6_CurrentPack_6_avg_hitempPack_6_avg_lotemppack_6_SoCb4-7chg/dis?pack_6_voltspack_6_volts
0x0C0BPack_7_CurrentPack_7_CurrentPack_7_avg_hitempPack_7_avg_lotemppack_7_SoCb4-7chg/dis?pack_7_voltspack_7_volts
0x0C0CPack_8_CurrentPack_8_CurrentPack_8_avg_hitempPack_8_avg_lotemppack_8_SoCb4-7chg/dis?pack_8_voltspack_8_volts

Screenshot

Screenshot

Received frame

0x1871 [0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00]

0x1871 [0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00]

These messages are only sent after BMS communications is established (a valid response to a poll request), they are sent together as a pair (100mS apart). They are sent by the inverter every 3 seconds and is the poll message for the bms to send extended data for individual cell data - bms_send_pack_cell_volts and bms_send_pack_cell_temps.

Response frames (cell mv values)

IDb0b1b2b3b4b5b6b7
0x0C1Dcell_1_mvcell_1_mvcell_2_mvcell_2_mvcell_3_mvcell_3_mvcell_4_mvcell_4_mv
0x0C21cell_5_mvcell_5_mvcell_6_mvcell_6_mvcell_7_mvcell_7_mvcell_8_mvcell_8_mv
0x0C25cell_9_mvcell_9_mvcell_10_mvcell_10_mvcell_11_mvcell_11_mvcell_12_mvcell_12_mv
0x0C29cell_13_mvcell_13_mvcell_14_mvcell_14_mvcell_15_mvcell_15_mvcell_16_mvcell_16_mv
0x0C2Dcell_17_mvcell_17_mvcell_18_mvcell_18_mvcell_19_mvcell_19_mvcell_20_mvcell_20_mv
0x0C31cell_21_mvcell_21_mvcell_22_mvcell_22_mvcell_23_mvcell_23_mvcell_24_mvcell_24_mv

repeats up [144_cells]

IDb0b1b2b3b4b5b6b7
0x0CA1cell_133_mvcell_133_mvcell_134_mvcell_134_mvcell_135_mvcell_135_mvcell_136_mvcell_136_mv
0x0CA5cell_137_mvcell_137_mvcell_138_mvcell_138_mvcell_139_mvcell_139_mvcell_140_mvcell_140_mv
0x0CA9cell_141_mvcell_141_mvcell_142_mvcell_142_mvcell_143_mvcell_143_mvcell_144_mvcell_144_mv

then immediately followed by cell temps (decimal 50 offset)

IDb0b1b2b3b4b5b6b7
0x0D21cell_1_tempcell_2_tempcell_3_tempcell_4_tempcell_5_tempcell_6_tempcell_7_tempcell_8_temp
0x0D29cell_9_tempcell_10_tempcell_11_tempcell_12_tempcell_13_tempcell_14_tempcell_15_tempcell_16_temp
0x0D31cell_17_tempcell_18_tempcell_19_tempcell_20_tempcell_21_tempcell_22_tempcell_23_tempcell_24_temp
0x0D39cell_25_tempcell_26_tempcell_27_tempcell_28_tempcell_29_tempcell_30_tempcell_31_tempcell_32_temp
0x0D41cell_33_tempcell_34_tempcell_35_tempcell_36_tempcell_37_tempcell_38_tempcell_39_tempcell_40_temp
0x0D49cell_41_tempcell_42_tempcell_43_tempcell_44_tempcell_45_tempcell_46_tempcell_47_tempcell_48_temp
0x0D51cell_49_tempcell_50_tempcell_51_tempcell_52_tempcell_53_tempcell_54_tempcell_55_tempcell_56_temp
0x0D59cell_57_tempcell_58_tempcell_59_tempcell_60_tempcell_61_tempcell_62_tempcell_63_tempcell_64_temp

Screenshots

Screenshot

Screenshot

Received frame

0x1871 [0x03, 0x06, 0x17, 0x05, 0x09, 0x09, 0x28, 0x22]

This message is sent by the inverter every '6' seconds (0.5s after the pack serial numbers) and contains a timestamp in bytes 2-7 i.e. <YY>,<MM>,<DD>,<HH>,<mm>,<ss>

.....................

. . . . .

**Disclaimer**: Any information on this wiki is informal advice, and is not supported nor endorsed by FoxESS.
There is no warranty expressed or implied: you take sole responsibility for everything you do with this information and your equipment.
There is no warranty to the accuracy of the content, nor any affiliation, or in any way a connection to FoxESS Co. Ltd