Benachrichtigungen
Alles löschen

JK BMS Venus OS falsche Werte. Brauche Hilfe :-/

8 Beiträge
5 Benutzer
3 Likes
951 Ansichten
(@nicoc83)
Vorsichtiger Stromfühler
Beigetreten: Vor 1 Jahr
Beiträge: 4
Themenstarter  

Moin Leute Smile

Ich komme bei mir leider nicht weiter und hoffe das mir vielleicht jemand von euch weiterhelfen kann.

Ich zähle mal kurz auf was ich hier habe und auch schon gemach habe: 

  • 6x 410WP Solarpanels
  • 1x MPPT 150/35 (2x2Panele)
  • 1x MultiPlus 24/1600 (Nulleinspeisung)
  • Akku mit 8 Zellen 24V mit JK BMS
  • 1x Hoymiles 600 + Ahoy DTU (2Panele)
  • Raspi 3b mit Venus OS 

Ich habe hier mit einem Kollegen der mir alles besorgt hat alles zusammengebaut und eingerichtet. In den letzten Tagen schien hier bei uns auch ganz gut die Sonne und ich konnte meine erste Sonnenenergie verbrauchen Smile Ich habe nun aber gemerkt das der Akku laut Venus OS nie auf 100% geht. Laut JK BMS App sagt er mir das ich 28V habe und 220AH von 245AH (laut Hersteller und Prüfprotokoll) gibt ca 90% von den AH. Die 28V würde ich aber eigentlich schon als voll bezeichnen. Ich habe momentan leider kein Multimeter zum nachmessen 🙁 Victron zeigt mir 90% an und lädt den Akku auch nicht mehr weiter auf. In der Utils.py ist Max V ist auch auf 28V gesetzt und ab 27,5V sollte er dann anfangen langsamer zu laden. Aber das funktioniert auch nicht.

Ich habe das JK BMS per USB Adapter an die Raspi angeschlossen und den GitHub Treiber verwendet. Kommunikation ist auch alles da. Der MPPT und der Multiplus laufen natürlich ebenfalls per Adapter an der Raspi.

Im Venus ist DVCC aktiviert und die Utils.py ist angepasst mit meiner Zellspannung.Im Venus OS unter Einstellungen/System Setup ist das JK BMS als Wächter aktiv. Im VE Configure für den Multi ist unter Charge bei Absorption 28V und unter Float 27,5V eingestellt.  Ich hatte auch schon gedacht Ich habe irgendwo bestimmt was übersehen aber ich komme hier leider nicht weiter. Ich habe jetzt bestimmt die hälfte an Infos vergessen zu schreiben und hoffe Ihr verzeiht mir das. Ich wollte hier nun auch keinen Roman schreiben 

Ich hänge nochmal meine utils.py mit ran. Ich wäre euch mega dankbar für Tipps was ich noch überprüfen kann Link entfernt Und wenn Ihr noch Infos braucht, falls irgendwas fehlen sollte, schreibe ich es natürlich schnellstmöglich hier rein.

Einen schönen Abend für euch 

Nico

Spoiler
BMS Settings

Cell Count: 8

Battery Capacity (AH):245

Balance Trig. Volt. (V):0.010

Calibrating Volt. (V): 28.00

Calibrating Curr.(A):0.100

Cell OVP(V):3.600

Cell OVPR(V):3.550

Cell UVPR(V):2.650

Cell UVP(V):2.600

Power Off Vol. (V):2.50

Start Balance Volt. (V):3.00

Max Balance Cur.(A):0.6

Spoiler
utils.py

# -*- coding: utf-8 -*-

import logging

import serial

from time import sleep

from struct import *

import bisect

 

# Logging

logging.basicConfig()

logger = logging.getLogger("SerialBattery")

logger.setLevel(logging.INFO)

 

# battery types

# if not specified: baud = 9600

battery_types = [

    {'bms' : "LltJbd"},

    {'bms' : "Ant", "baud" : 19200},

    {"bms" : "Daly", "address" : b"\x40"},

    {"bms" : "Daly", "address" : b"\x80"},

    {"bms" : "Jkbms", "baud" : 115200},

#    {"bms" : "Sinowealth"},

    {"bms" : "Lifepower"},

    {"bms" : "Renogy", "address": b"\x30"},

    {"bms" : "Renogy", "address": b"\xF7"},

    {"bms" : "Ecs", "baud" : 19200},

#    {"bms" : "MNB"},

]

 

# Constants - Need to dynamically get them in future

DRIVER_VERSION = 0.14

DRIVER_SUBVERSION = '.3'

zero_char = chr(48)

degree_sign = u'\N{DEGREE SIGN}'

 

# Choose the mode for voltage / current limitations (True / False)

# False is a Step mode. This is the default with limitations on hard boundary steps

# True "Linear"    # New linear limitations by WaldemarFech for smoother values

LINEAR_LIMITATION_ENABLE = False

 

######### Cell Voltage limitation #########

# Description:

# Maximal charge / discharge current will be in-/decreased depending on min- and max->

# Example: 18cells * 3.55V/cell = 63.9V max charge voltage. 18 * 2.7V = 48,6V min dis>

#          ... but the (dis)charge current will be (in-/)decreased, if even ONE SINGL>

 

# Charge current control management referring to cell-voltage enable (True/False).

CCCM_CV_ENABLE = True

# Discharge current control management referring to cell-voltage enable (True/False).

DCCM_CV_ENABLE = True

 

# Set Steps to reduce battery current. The current will be changed linear between tho>

CELL_VOLTAGES_WHILE_CHARGING         = [3.55, 3.50, 3.45, 3.30]

MAX_CHARGE_CURRENT_CV                = [   0,    2,  30,  60]

 

CELL_VOLTAGES_WHILE_DISCHARGING      = [2.70, 2.80, 2.90, 3.10]

MAX_DISCHARGE_CURRENT_CV             = [   0,    5,  30,  60]

 

######### Temperature limitation #########

# Description:

# Maximal charge / discharge current will be in-/decreased depending on temperature

# Example: The temperature limit will be monitored to control the currents. If there >

#          then the worst case will be calculated and the more secure lower current w>

# Charge current control management referring to temperature enable (True/False).

CCCM_T_ENABLE = True

# Charge current control management referring to temperature enable (True/False).

DCCM_T_ENABLE = True

 

# Set Steps to reduce battery current. The current will be changed linear between tho>

TEMPERATURE_LIMITS_WHILE_CHARGING    = [55, 40,  35,   5,  2, 0]

MAX_CHARGE_CURRENT_T                 = [ 0, 28, 60, 60, 28, 0]

 

TEMPERATURE_LIMITS_WHILE_DISCHARGING = [55, 40,  35,   5,  0, -20]

MAX_DISCHARGE_CURRENT_T              = [ 0, 28, 60, 60, 28,   0]

 

# if the cell voltage reaches 3.55V, then reduce current battery-voltage by 0.01V

# if the cell voltage goes over 3.6V, then the maximum penalty will not be exceeded

# there will be a sum of all penalties for each cell, which exceeds the limits

PENALTY_AT_CELL_VOLTAGE  = [3.45, 3.55, 3.6]

PENALTY_BATTERY_VOLTAGE  = [0.01, 1.0, 2.0]  # this voltage will be subtracted

 

 

######### SOC limitation #########

# Description:

# Maximal charge / discharge current will be increased / decreased depending on State>

# The State of Charge (SoC) charge / discharge current will be in-/decreased dependin>

# Example: 16cells * 3.45V/cell = 55,2V max charge voltage. 16*2.9V = 46,4V min disch>

# Cell min/max voltages - used with the cell count to get the min/max battery voltage

MIN_CELL_VOLTAGE = 2.65

MAX_CELL_VOLTAGE = 3.50

FLOAT_CELL_VOLTAGE = 3.46

MAX_VOLTAGE_TIME_SEC = 15*60

SOC_LEVEL_TO_RESET_VOLTAGE_LIMIT = 90

 

# battery Current limits

MAX_BATTERY_CHARGE_CURRENT = 50.0

MAX_BATTERY_DISCHARGE_CURRENT = 60.0

 

# Charge current control management enable (True/False).

CCCM_SOC_ENABLE = True

# Discharge current control management enable (True/False).

DCCM_SOC_ENABLE = True

 

#charge current soc limits

CC_SOC_LIMIT1 = 98

CC_SOC_LIMIT2 = 95

CC_SOC_LIMIT3 = 91

 

#charge current limits

CC_CURRENT_LIMIT1 = 5

CC_CURRENT_LIMIT2 = MAX_BATTERY_CHARGE_CURRENT/4

CC_CURRENT_LIMIT3 = MAX_BATTERY_CHARGE_CURRENT/2

 

#discharge current soc limits

DC_SOC_LIMIT1 = 10

DC_SOC_LIMIT2 = 20

DC_SOC_LIMIT3 = 30

 

#discharge current limits

DC_CURRENT_LIMIT1 = 5

DC_CURRENT_LIMIT2 = MAX_BATTERY_DISCHARGE_CURRENT/4

DC_CURRENT_LIMIT3 = MAX_BATTERY_DISCHARGE_CURRENT/2

 

# Charge voltage control management enable (True/False).

CVCM_ENABLE = False

 

# Simulate Midpoint graph (True/False).

MIDPOINT_ENABLE = False

 

#soc low levels

SOC_LOW_WARNING = 20

SOC_LOW_ALARM = 10

 

# Daly settings

# Battery capacity (amps) if the BMS does not support reading it

BATTERY_CAPACITY = 50

# Invert Battery Current. Default non-inverted. Set to -1 to invert

INVERT_CURRENT_MEASUREMENT = 1

 

# TIME TO SOC settings [Valid values 0-100, but I don't recommend more that 20 interv>

# Set of SoC percentages to report on dbus. The more you specify the more it will imp>

# TIME_TO_SOC_POINTS = [100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, >

# TIME_TO_SOC_POINTS = [100, 95, 90, 85, 75, 50, 25, 20, 10, 0]

TIME_TO_SOC_POINTS = [] # No data set to disable

# Specify TimeToSoc value type: [Valid values 1,2,3]

# TIME_TO_SOC_VALUE_TYPE = 1   # Seconds

# TIME_TO_SOC_VALUE_TYPE = 2   # Time string HH:MN:SC

TIME_TO_SOC_VALUE_TYPE = 3        # Both Seconds and time str "<seconds> [days, HR:MN>

# Specify how many loop cycles between each TimeToSoc updates

TIME_TO_SOC_LOOP_CYCLES = 5

# Include TimeToSoC points when moving away from the SoC point. [Valid values True,Fa>

# These will be as negative time. Disabling this improves performance slightly.

TIME_TO_SOC_INC_FROM = False

 

 

# Select the format of cell data presented on dbus. [Valid values 0,1,2,3]

# 0 Do not publish all the cells (only the min/max cell data as used by the default GX

# 1 Format: /Voltages/Cell# (also available for display on Remote Console)

# 2 Format: /Cell/#/Volts

# 3 Both formats 1 and 2

BATTERY_CELL_DATA_FORMAT = 1

 

# Settings for ESC GreenMeter and Lipro devices

GREENMETER_ADDRESS = 1

LIPRO_START_ADDRESS = 2

LIPRO_END_ADDRESS = 4

LIPRO_CELL_COUNT = 15

 

def constrain(val, min_val, max_val):

    if min_val > max_val:

        min_val, max_val = max_val, min_val

    return min(max_val, max(min_val, val))

 

def mapRange(inValue, inMin, inMax, outMin, outMax):

    return outMin + (((inValue - inMin) / (inMax - inMin)) * (outMax - outMin))

 

def mapRangeConstrain(inValue, inMin, inMax, outMin, outMax):

    return constrain(mapRange(inValue, inMin, inMax, outMin, outMax), outMin, outMax)

 

def calcLinearRelationship(inValue, inArray, outArray):

    if inArray[0] > inArray[-1]:    # change compare-direction in array

        return calcLinearRelationship(inValue, inArray[::-1], outArray[::-1])

    else:

 

        # Handle out of bounds

        if inValue <= inArray[0]:

            return outArray[0]

        if inValue >= inArray[-1]:

            return outArray[-1]

 

        # else calculate linear current between the setpoints

        idx = bisect.bisect(inArray, inValue)

        upperIN  = inArray[idx - 1]  # begin with idx 0 as max value

        upperOUT = outArray[idx - 1]

        lowerIN  = inArray[idx]

        lowerOUT = outArray[idx]

        return  mapRangeConstrain(inValue, lowerIN, upperIN, lowerOUT, upperOUT)

 

def calcStepRelationship(inValue, inArray, outArray, returnLower):

    if inArray[0] > inArray[-1]:    # change compare-direction in array

        return calcStepRelationship(inValue, inArray[::-1], outArray[::-1], returnLow>

 

    # Handle out of bounds

    if inValue <= inArray[0]:

        return outArray[0]

    if inValue >= inArray[-1]:

        return outArray[-1]

 

    # else get index between the setpoints

    idx = bisect.bisect(inArray, inValue)

 

    return outArray[idx] if returnLower else outArray[idx-1]

 

def is_bit_set(tmp):

    return False if tmp == zero_char else True

 

def kelvin_to_celsius(kelvin_temp):

    return kelvin_temp - 273.1

 

def format_value(value, prefix, suffix):

    return None if value is None else ('' if prefix is None else prefix) + \

                                      str(value) + \

                                      ('' if suffix is None else suffix)

 

def read_serial_data(command, port, baud, length_pos, length_check, length_fixed=None>

    try:

        with serial.Serial(port, baudrate=baud, timeout=0.1) as ser:

            return read_serialport_data(ser, command, length_pos, length_check, lengt>

 

    except serial.SerialException as e:

        logger.error(e)

        return False

 

 

# Open the serial port

# Return variable for the openned port

def open_serial_port(port, baud):

    ser = None

    tries = 3

    while tries > 0:

        try:

            ser = serial.Serial(port, baudrate=baud, timeout=0.1)

            tries = 0

        except serial.SerialException as e:

            logger.error(e)

            tries -= 1

 

    return ser

 

# Read data from previously openned serial port

def read_serialport_data(ser, command, length_pos, length_check, length_fixed=None, l>

    try:

        ser.flushOutput()

        ser.flushInput()

        ser.write(command)

 

        length_byte_size = 1

        if length_size is not None:

            if length_size.upper() == 'H':

                length_byte_size = 2

            elif length_size.upper() == 'I' or length_size.upper() == 'L':

                length_byte_size = 4

 

        count = 0

        toread = ser.inWaiting()

 

        while toread < (length_pos+length_byte_size):

            sleep(0.005)

            toread = ser.inWaiting()

            count += 1

            if count > 50:

                logger.error(">>> ERROR: No reply - returning")

                return False

 

        #logger.info('serial data toread ' + str(toread))

        res = ser.read(toread)

        if length_fixed is not None:

            length = length_fixed

        else:

            if len(res) < (length_pos+length_byte_size):

                logger.error(">>> ERROR: No reply - returning [len:" + str(len(res)) >

                return False

            length_size = length_size if length_size is not None else 'B'

            length = unpack_from('>'+length_size, res,length_pos)[0]

 

        #logger.info('serial data length ' + str(length))

count = 0

        data = bytearray(res)

        while len(data) <= length + length_check:

            res = ser.read(length + length_check)

            data.extend(res)

            #logger.info('serial data length ' + str(len(data)))

            sleep(0.005)

            count += 1

            if count > 150:

                logger.error(">>> ERROR: No reply - returning [len:" + str(len(data))>

                return False

 

        return data

 

    except serial.SerialException as e:

        logger.error(e)

        return False


   
Zitat
(@bennyb21)
Autarkiekönig
Beigetreten: Vor 2 Jahren
Beiträge: 547
 

Wurde der Akku initial mal gebalanced? Wie sahen die Zellspannungen beim Ladevorgang aus bzw. zu dem Zeitpunkt als er die Ladung beendet hat?


   
AntwortZitat
(@nicoc83)
Vorsichtiger Stromfühler
Beigetreten: Vor 1 Jahr
Beiträge: 4
Themenstarter  

Moin Benny

Die zellspannung ist gerade bei 3,3

er ist jetzt 1% runter also bei 89% 

Heute am Abend kann ich mal nachmessen ob die Werte stimmen und würde dann nochmal ein paar Werte posten 

 

kann ich das initial balancing erzwingen über die App ? Muss ich da was beachten ? 


   
AntwortZitat
(@bennyb21)
Autarkiekönig
Beigetreten: Vor 2 Jahren
Beiträge: 547
 

Es ist klar das die Zellspannung gerade wenn nicht geladen wird um die 3,3V ist. Das meinte ich nicht, sondern während des Ladevorgangs, als er abgebrochen hat. 

Bitte lies Dich mal in das Ladeverhalten von LiFePo Zellen ein. Im FAQ-Bereich gibt es auch eine sehr gute Anleitung von Carolus zur Initialisierung eines Akkus. Sofern das nicht durchgeführt wurde und man versteht was da passiert, wird das nicht funktionieren!!!

Ich gehe einfach mal davon aus, dass der SerialBattery Treiber die Ladung blockiert hat, weil eine Zelle in das oberste Spannungslimit lief beim Ladevorgang. Das wirst Du ohne ordentliches Balancing auch nicht gelöst bekommen.


   
AntwortZitat
U-F-O
(@u-f-o)
Autarkiekönig
Beigetreten: Vor 2 Jahren
Beiträge: 792
 

Oje... ich kann dir nur raten dich auf jeden Fall besser einzulesen zum Thema, und zwar sehr viel besser😉.

Zellen erstmal alle vernünftig initial laden wie Benny schon geschrieben hat...

Dir fehlen sämtliche Grundlagen zu dem was du da in Betrieb genommen hast, das zeigen schon deine Einstellungen im BMS.

Start Balance Volt. (V):3.00 (vieeel zu früh... frühestens ab 3,4xV)

Max Balance Cur.(A):0.6 (warum nicht die maximal möglichen 2 Ampere die das JK schafft?)

Und lass auf jeden Fall erstmal diesen Serialbattery Treiber und DVCC weg (deaktivieren).

Du bist bei deinem Wissensstand noch weit entfernt davon um damit rumzuspielen (ich meins nur gut)😉.

Achtung, einige meiner Angaben stammen von nicht kalibrierten oder geeichten Geräten. Bei Risiken und Nebenwürgungen schreiben sie die Packungsbeilage und vertrauen sie nicht meinen Angaben oder denen ihres Spirituellen Führers! Denn für jede Lösung haben wir ein Problem. Vertrauen sie auf ihren Fehler und genießen sie die Reise. Alle Angaben ohne Gewehr!


   
voltmeter reacted
AntwortZitat
(@autoschrauberix)
Heroischer Stromgenerator
Beigetreten: Vor 2 Jahren
Beiträge: 1070
 

Veröffentlicht von: @u-f-o

Max Balance Cur.(A):0.6 (warum nicht die maximal möglichen 2 Ampere die das JK schafft?)

Es gibt viele verschiedene BMS von JK, ich nehme mal an das ist ein kleineres mit max. 0,6A balancing.

 @nicoc83 Du hast kein Multimeter und baust einen Akku, sorry aber das ist im wahrsten Sinne des Wortes brandgefährlich.

Mindestausstattung bei Eigenbau:

  • Multimeter
  • Amperemeter
  • IR Thermometer besser IR Kamera

Wie willst Du prüfen ob alles in Ordnung ist ?

 


   
voltmeter and U-F-O reacted
AntwortZitat
U-F-O
(@u-f-o)
Autarkiekönig
Beigetreten: Vor 2 Jahren
Beiträge: 792
 

@autoschrauberix 

Hast du natürlich Recht hatte ich nicht bedacht 😉.

Achtung, einige meiner Angaben stammen von nicht kalibrierten oder geeichten Geräten. Bei Risiken und Nebenwürgungen schreiben sie die Packungsbeilage und vertrauen sie nicht meinen Angaben oder denen ihres Spirituellen Führers! Denn für jede Lösung haben wir ein Problem. Vertrauen sie auf ihren Fehler und genießen sie die Reise. Alle Angaben ohne Gewehr!


   
AntwortZitat
(@berndm)
Vorsichtiger Stromfühler
Beigetreten: Vor 2 Jahren
Beiträge: 17
 

Hast du auch daran gedacht, immer schön den Raspi zu rebooten, wenn du änderungen in der utils.py vorgenommen hast?

Ich hab manchmal des rebooten nämlich vergessen und dann werden die Änderungen nicht wirksam.

Und mit einem JK BMS würde ich die SOC Steuerung ohnehin dauerhaft disablen, da die SOC Werte einfach nie stimmen (so +- 20-30% falsch)

Man kann übrigens den SOC neu berechnen lassen, indem man (bei laut Zellenspannungen vollem Akku (also im Leerlauf 3.400V)) im BT Interface des BMS änderungen an der Kapazität des Packs vonimmt. Also zB. der Wert 245Ah auf 250Ah ändert. dann sollte das BMS wieder 100% SOC anzeigen.


   
AntwortZitat
Teilen: