Fórum | MyPower.CZ | Obnovitelné zdroje energie - energetická soběstačnost | Poslední návštěva: úte říj 04, 2022 2:16 am


BMS s komunikací RS485/232/Modbus

LiFePO4, LiFeYPO4, atd., zkušenosti, rady, tipy ...
Předchozí

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod Marcus81 » ned úno 27, 2022 1:38 pm

Nikto mi tu nevie s tym poradit?
Je mozne na bms 16s pripojit napr. iba 4s?
Hybrid, 4x260Wp Amerisolar, 6x260Wp Mono CSun, 2x260Wp Aleo, 9x 230Wp JuliSolar, 32x Astronergy 245Wp, 3f-Victron Energy Multiplus 48/5000, 750 Ah trakčná, 800 Ah OPzV stacionarne, 3xMPPT Victron Energy 150/70-Tr, 1xMPPT Victron Energy 150/45-Tr, AC-out Coupling Fronius Symo 4.5-3-M
zatial vsetko vo výstavbe...
Uživatelský avatar
Marcus81
 
Příspěvky: 337
Registrován: pát dub 28, 2017 7:05 pm
Bydliště: Blízko Senec, SVK

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod FRSO » ned úno 27, 2022 2:02 pm

Marcus81 píše:Nikto mi tu nevie s tym poradit?
Je mozne na bms 16s pripojit napr. iba 4s?

Dle mě určitě ne, nevím o tom, zeptej se ještě mikela na fóru.
5,4 kWp JJZ, do 13.8.2022 bylo 3,6 kWp, MPII 5k, Victron MPPT 250/85-TR, aku 9,45 kWh Lion 15S, BMS 200A, Smart Shunt 500A.
Od 6 března 2022 vyrobeno k 9/6 1000 kWh, k 17/8 2000 kWH, k 1.10.2022 už 2500kWH
?
FRSO
 
Příspěvky: 1851
Registrován: ned srp 14, 2011 9:13 pm

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod Lui » ned úno 27, 2022 3:21 pm

Marcus81 píše:Nikto mi tu nevie s tym poradit?
Je mozne na bms 16s pripojit napr. iba 4s?


večšinou každý výrobca udáva na aký počet článkov má BMS,tie čo napríklad ja používam fungujú 8-16S ak by som potreboval inú možnú kombináciu článkov,tak si vyberiem nejakú inú...je trebars aj 8-24S alebo aj 10-32S iné kombinácie nepoznám,kedže v mojom systéme som neriešil nikdy,kedže to nie je pre mňa potrebné...
Cca 35kwp ::pv:: , 60V 1,2kAh , 15S 600P Lion *batt* + 60V 198Ah Lifepo4 *batt* , 10 x MPPT VT-80, 12kw menič , BMV-600S , 4xStuder XTH 8000 vo výstavbe ,
Záloha:260Wp ::pv:: ,12V LiFePO4 60Ah *batt* , epsolar 10 dvakrát ,victron 350w sinus
Uživatelský avatar
Lui
 
Příspěvky: 1164
Registrován: pon srp 08, 2011 2:14 pm
Bydliště: Slovensko

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod Joskob » ned úno 27, 2022 3:41 pm

Marcus81 píše:Nikto mi tu nevie s tym poradit?
Je mozne na bms 16s pripojit napr. iba 4s?

Mam 7S bms od cinana z lithiumbatterypcb a da sa nastavit od 1S az po 10S. Taktiez bms Mgod (vyzera ako nejaky klon Daly bms)
9x Solar frontier 70W ; 16x Trinasolar TSM-235PC05 235W ; 5x Moser Baer 222W (5210Wp)
Epsolar LS3024b,LS2024b,Xtra3210,Tracer3215 ; 2x smart BMS 30A ; DalyBMS 150A
Easun PWM 3000w 24/230 sinus ; Soluowill NP1200-24/230 sinus
7S120P Li-ion 18650 210+Ah ; 7S CATL 100Ah ; 7S CATL 150Ah
?
Joskob
 
Příspěvky: 549
Registrován: ned kvě 12, 2019 8:56 pm
Bydliště: Poprad

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod ViktorEX » ned úno 27, 2022 10:21 pm

marsal64 píše:
ViktorEX píše:hmm, hezky ... ale dal mi to nepomohlo... nemate prosim nekdo nejaky vzorovy programek?

Tak je to ten Foxtrot, třeba trochu pomůže pro inspiraci.

Kód: Vybrat vše
VAR_GLOBAL
  NUM_DALYS : USINT := 2;  // number of Dalys present
  CH_DALYS : UINT := CH3_UNI;  // UNI channel for the communication
  DALYADDR : ARRAY[1..3] of BYTE := [16#40, 16#41, 0];  // Daly addresses
  Timeout_recv_Daly : TIME := T#100MS;        // How long wait for Daly response
  CurrentBatSum : Real;   // sum of battery current from all BMS
  CurrentBatSum_cl : CL;   // color of battery current from all BMS: > 0.5 green; < -0.5 orange; else green

END_VAR


// Structure for receiving and storing raw Daly data
TYPE
  DALYBMSDATA : STRUCT

    LastError_text : STRING;
    LastError_datetime : DT;
    ErrorCount : USINT;
    LastReceive_datetime : DT;
    ReceiveOKCount : USINT;  // counter of correct communications
    maxvoltage : REAL; // maximum cell voltage
    minvoltage : REAL; // minimum cell voltage
    totvoltage : REAL; // total battery voltage "pressure"
    current : REAL; // proud
    SOC : REAL; // SOC
    minVcellNo: USINT;  // cell no with minimum voltage
    maxVcellNo: USINT;  // cell no with maximum voltage
    temperature : INT; // temperatureplota
    state : USINT; // 0 - static  1 - charge   2 - discharge
    statea : CL; // rgb
    balancing : string[4];   // 16 battery cells in pack expected here
    MOScharging : USINT; // 1 - MOS for charging on
    MOSLoad : USINT;   // 1 - MOS for discharging on
    faultstatus1 : string[8];  // bits indicating error
    faultstatus2 : string[8];  // bits indicating error 2
  END_STRUCT
END_TYPE

// Daly values store
VAR_GLOBAL RETAIN
  dalys : ARRAY[1..3] OF DALYBMSDATA;
  daly_diffvoltage_1 : real; // difference of voltage between min and max for battery 1
  daly_diffvoltage_2 : real; // difference of voltage between min and max for battery 2
END_VAR



Kód: Vybrat vše
// Communicate with Daly BMS

// Expected RS-485, all Dalys to use a single communication channel


// function to calculate checksum
FUNCTION bchksm : USINT
  VAR_INPUT
    cfrom : PTR_TO USINT; // USINT pointer to start from
    numbytes : UINT; // number of bytes
  END_VAR
  VAR
    a : USINT;
  END_VAR

  REPEAT
    a := a + cfrom^;
    cfrom := cfrom + 1;
    numbytes := numbytes - 1;
  UNTIL numbytes = 0 END_REPEAT;
  bchksm := a;
END_FUNCTION

// Structure for received message
TYPE
  Dalyrecv : STRUCT
    error : STRING[250]; // error found, '' if none
    status : USINT; // processing status: 0: ready, 1: sending, 2: receiving, 3: result ready, 4: error
    lenmesrec : UINT; // length of the raw received message
    datarec : STRING[13]; // raw content of the received message
  END_STRUCT
END_TYPE


// send and receive one message from/to Daly
FUNCTION_BLOCK fbDalySendRec1
  VAR_INPUT
    init : BOOL; // trigger to start processing
    dst_addr : BYTE;    // address of Daly to send data to
    data_id : BYTE;   // command id
  END_VAR
  VAR_OUTPUT
    rm : Dalyrecv; // Daly status and data structure
  END_VAR
  VAR
    m : STRING[13]; // message data to send
    r : STRING[13]; // message data received
    pb : PTR_TO BYTE;
    pd : PTR_TO DWORD;
    // helpers
    chs : USINT;
    SendToDaly : fbSendTo;
    RecvFromDaly : fbRecvFrom;
    recvTimer : TON; // receiving timer
  END_VAR

  // init and send the message?
  IF init THEN
    recvTimer(IN := False, PT := Timeout_Recv_Daly);

    // construct the message to be sent
    rm.error := ''; // expect no error
    pb := adr(m); // to initial byte
    pb^ := 16#A5;
    pb := pb + 1; // to communication module address
    pb^ := dst_addr;
    //pb^ := SHL(dst_addr, 4);
    pb := pb + 1; // to data id
    pb^ := data_id;
    pb := pb + 1; // to data legth
    pb^ := 8;
    // may process data to send here, if any
    pd := pb + 1; // to first data DWORD
    pd^ := 0;
    pd := pd + 4; // to second data DWORD
    pd^ := 0;
    pb := pd + 4; // to checksum
    pb^ := USINT_TO_BYTE(bchksm(adr(m), 12));

    // send
    SendToDaly(rq :=True, chanCode := CH_DALYS, lenTx := 13, data := void(m));

    // initiate receiving timer
    recvTimer(IN := True);
   
    rm.status := 2; // receiving
  END_IF;

  // exit if the main program did not processed the response (3 = response data, 4 = error), then return without further processing
  IF rm.status > 2 THEN
    RETURN;
  END_IF;

  // initiate message receive if status = 2
  RecvFromDaly(rq :=True, chanCode := CH_DALYS, lenRx := 13, data := void(r));

  // message not received?
  IF not RecvFromDaly.mesRec THEN
    // timeout?
    IF recvTimer.Q THEN
      rm.error := 'General receive error: response timeout';
      rm.status := 4; // present the error
      return;
    ELSE
      return; // message not received and no timeout - continue waiting for response
    END_IF;
  ELSE // message received

    // message received - check general error
    IF RecvFromDaly.error <> 0 THEN
      rm.error := concat('General receive error: ', GetLastComErrTxt(RecvFromDaly.error));
      rm.status := 4; // indicate the error
      return;
    END_IF;
    // no error, start parsing
    rm.lenmesrec := RecvFromDaly.lenData;
    // despite potenital error, copy the received data to the output variable, if not too long
    IF rm.lenmesrec <= 13 THEN
      Memcpy(length := rm.lenmesrec, source := void(r), dest := void(rm.datarec));
    END_IF;
    pb := adr(rm.datarec); // to start_byte
    // check start byte
    IF not pb^ = 16#a5 THEN
      // first byte is not A5
      rm.error := 'Daly receive error: the first byte is not A5';
      rm.status := 4; // indicate the error
      return;
    END_IF;
    // verify checksum
    pb := pb + 12;
    chs := BYTE_TO_USINT(pb^);
    IF chs <> bchksm(adr(rm.datarec), 12) THEN
      rm.error := 'Daly receive error: checksum verification failed';
      rm.status := 4; // indicate the error
      return;
    ELSE
      // indicate correctly received data
      rm.status := 3;
    END_IF;
  END_IF;
END_FUNCTION_BLOCK


PROGRAM DalyBMS
  VAR
    a : fbDalySendRec1; // function block to send one message to Studer and receive response
    s : Dalyrecv; // structure with receive data
    tinit : BOOL := True; // for the first run, lanuch
    pw : PTR_TO WORD;
    pb : PTR_TO BYTE;
    pd : PTR_TO DWORD;
    daly_id : USINT := 1;           //current Daly to process
    daly_addr : BYTE ;               // current Daly address
    COMMAND_MIN : USINT := 16#90;    // minimum no of command to be sent
    COMMAND_MAX : USINT := 16#98;   // maximum no of command to be sent
    command_id : USINT := 16#90;  // work variable - current command_id
    i : USINT;
  END_VAR

  // if tinit, go to next command or next Daly
  if tinit THEN
    command_id := command_id + 1;
    if command_id > COMMAND_MAX THEN
       // first command id
       command_id := COMMAND_MIN;
       // next daly
       daly_id := daly_id + 1;
       if daly_id > NUM_DALYS THEN daly_id := 1; END_IF;
    end_if;
  END_IF;

  // take daly address
  daly_addr := DALYADDR[daly_id];

  // process the current command for the current Daly
  a(init := tinit, dst_addr := daly_addr, data_id := USINT_TO_BYTE(command_id), rm => s);
  tinit := False; // synchronous - wait for response

    // verify if response or came and process
  CASE s.status OF
    2:
       RETURN;

    4 :
      // mark error to the Daly data
      dalys[daly_id].LastError_text  := s.error;
      dalys[daly_id].LastError_datetime  := GetDateTime();
      dalys[daly_id].ErrorCount  := dalys[daly_id].ErrorCount + 1;
      tinit := True;

    3 :
      // mark last received data to Daly
      dalys[daly_id].LastReceive_datetime := GetDateTime();
      dalys[daly_id].ReceiveOKCount := dalys[daly_id].ReceiveOKCount + 1;
      tinit := True;
     
      // parse - go to the first data byte
      pw := adr(s.datarec) + 4;
      pb := pw;
      pd := pw;

      case command_id of

      16#90:
         dalys[daly_id].totvoltage := int_to_real(int_to_int(word_to_int(pw^))) * 0.1;
         pw := pw + 4;
         dalys[daly_id].current := - (int_to_real(int_to_int(word_to_int(pw^))) - 30000) * 0.1; // A
         pw := pw + 2;
         dalys[daly_id].SOC := int_to_real(int_to_int(word_to_int(pw^))) * 0.1; // perc.

      16#91:
         dalys[daly_id].maxvoltage := int_to_real(int_to_int(word_to_int(pw^))) / 1000; // mV
         pb := pw + 2;
         dalys[daly_id].maxVcellNo := byte_to_usint(pb^);
         pw := pw + 3;
         dalys[daly_id].minvoltage := int_to_real(int_to_int(word_to_int(pw^))) / 1000;
         pb := pb + 3;
         dalys[daly_id].minVcellNo := byte_to_usint(pb^);
      16#92:
         dalys[daly_id].temperature := byte_to_int(pb^) - 40;  // only one thermometer expected here
      16#93:
         dalys[daly_id].state := byte_to_usint(pb^);  // 0 - static  1 - charge   2 - discharge

         case dalys[daly_id].state of
         // static - grey
         0: dalys[daly_id].statea.r := 212;
            dalys[daly_id].statea.g := 212;
            dalys[daly_id].statea.b := 212;

         // charge - green
         1: dalys[daly_id].statea.r := 0;
            dalys[daly_id].statea.g := 200;
            dalys[daly_id].statea.b := 0;

         // discharge - orange
         2: dalys[daly_id].statea.r := 255;
            dalys[daly_id].statea.g := 128;
            dalys[daly_id].statea.b := 0;
         end_case;

         pb := pb + 1;
         dalys[daly_id].MosCharging := byte_to_usint(pb^);
         pb := pb + 1;
         dalys[daly_id].MosLoad := byte_to_usint(pb^);
         
         // force switch to nearest processed command
         // switches also 95 and 96 which could not be processes in this program
         
         command_id := 16#96;  // will be incremented
         
      16#97:
         dalys[daly_id].balancing := word_to_stringf(pw^, '%04X');         // bit = the cell is balancing
      16#98:
         dalys[daly_id].faultstatus1 := dword_to_stringf(pd^,'%08X');
         pd := pd + 4;
         dalys[daly_id].faultstatus2 := dword_to_stringf(pd^,'%08X');
      END_CASE;

  END_CASE;


  // calculate total current from batteries
  CurrentBatSum := 0;
 
  for i := 1 to NUM_DALYS DO
    CurrentBatSum := CurrentBatSum + dalys[i].current;
  end_for;

  if CurrentBatSum > 0.5 THEN // charge - green
    CurrentBatSum_cl.r := 0;CurrentBatSum_cl.g := 200;CurrentBatSum_cl.b := 0;
  elsif CurrentBatSum < -0.5 THEN // discharge - orange
     CurrentBatSum_cl.r := 255;CurrentBatSum_cl.g := 128;CurrentBatSum_cl.b := 0;
  else // static - grey
     CurrentBatSum_cl.r := 212;CurrentBatSum_cl.g := 212;CurrentBatSum_cl.b := 212;
  end_if;

  // actualization of the global variables
  daly_diffvoltage_1 := dalys[1].maxvoltage - dalys[1].minvoltage;
  daly_diffvoltage_2 := dalys[2].maxvoltage - dalys[2].minvoltage;
END_PROGRAM


ach jo, sotva jsem se prokousal zacatky arduina. takze stake stejne v pr... jako pred tim. :cry:
(polo) - Ostrov 13,8 kWp (bude 15 kWp, už to tu leží), 2x Mppt Epever 5kW, Batt Lifepo4 18kWh, 3x invertor 6kW (čistý sinus) .... 300K CZK bez práce, všechno nějaká čína,

14.7. -31.12.2021
21,4 kwh/den, 57% soběstačnost
Celkem spotřeba ... 3,69 MWh

1.1. -27.3.2022,
20,6 kwh/den, 57% soběstačnost
Celkem spotřeba ... 1,8 MWh
Uživatelský avatar
ViktorEX
 
Příspěvky: 416
Registrován: stř zář 16, 2020 4:45 pm

Re: BMS s komunikací RS485/232/Modbus

Příspěvekod Frantisekcon » sob zář 17, 2022 5:01 pm

Dobrý den, poradí někdo s typem bms, který bude komunikovat s goodwe? Mám dva paky 16s lifepo4 200ah a slyšel jsem že dvě bms jdou propojit komunikací mezi sebou a komunikovat protokolem třeba Pylontech. Děkuji Fanda
?
Frantisekcon
 
Příspěvky: 3
Registrován: čtv dub 07, 2022 10:03 am

Předchozí

Zpět na LiFe*

Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků

Reputation System ©'