JKBMS - welche Version kaufen?

Ach so und dann möchte ich Hoffnung machen. RS485 Kommunikation funktioniert mit meinem Victron MP2 einwandfrei. Angesteckt, Serialbattery installiert. Läuft. Und das alles ohne EM24.
Hallo ton,
kannst du das etwas näher ausführen? Also die ganze RS485 Signalkette. Was nutzt du statt EM24?

Klar. Gerne.

Für die RS485 Kommunikation:
1. JK BMS RS485 Adapter: https://de.aliexpress.com/item/1005003451100409.html
2. RS485 auf USB Adapter: https://www.waveshare.com/usb-to-rs485.htm
3. DBUS Serialbattery installieren: https://github.com/Louisvdw/dbus-serialbattery
Fertig.

Für die EVU Daten habe ich mein Modbus Solaredge Smartmeter. Da gäbe es jetzt verschiedene Varianten dieses in Venus OS zu bekommen. Ich habe noch eine openWB Wallbox und die Daten des Smartmeters liegen dort sowieso vor, weil sie per Modbus abgefragt werden. Gleichzeitig läuft auf der OpenWB ein MQTT Broker, der diese Daten aufbereitet und andern zur Verfügung stellt. Dazu habe ich folgende "Treiber" auf dem Venus OS installiert und auf mein Setting angepasst:

Wechselrichter (also PV Leistung):
#!/usr/bin/env python
try:
import gobject # Python 2.x
except:
from gi.repository import GLib as gobject # Python 3.x
import platform
import logging
import time
import sys
import json
import os
import paho.mqtt.client as mqtt
try:
import thread # for daemon = True / Python 2.x
except:
import _thread as thread # for daemon = True / Python 3.x

our own packages

sys.path.insert(1, os.path.join(os.path.dirname(file), '/opt/victronenergy/dbus-systemcalc-py/ext/velib_python'))
from vedbus import VeDbusService
path_UpdateIndex = '/UpdateIndex'

MQTT Setup

broker_address = "192.168.XXX"
port = 1883
MQTTNAME = "PVInverter"
username="XXXX"
password="XXX!"

Variblen setzen

verbunden = 0
durchlauf = 0
volt_ges = 0
volt_p1 = 0
volt_p2 = 0
volt_p3 = 0
amp_p1 = 0
amp_p2 = 0
amp_p3 = 0
pow_ges =0

MQTT Abfragen:

def on_disconnect(client, userdata, rc):
global verbunden
print("Client Got Disconnected")
if rc != 0:
print('Unexpected MQTT disconnection. Will auto-reconnect')
else:
print('rc value:' + str(rc))
try:
print("Trying to Reconnect")
client.connect(broker_address)
verbunden = 1
except Exception as e:
logging.exception("Fehler beim reconnecten mit Broker")
print("Error in Retrying to Connect with Broker")
verbunden = 0
print(e)
def on_connect(client, userdata, flags, rc):
print("Verbunden mit IoBroker: " + broker_address)
client.subscribe("openWB/pv/W")
def on_message(client, userdata, message):
global volt_ges,volt_p1, volt_p2, volt_p3, amp_p1, amp_p2, amp_p3, pow_ges
msg = str(message.payload.decode("utf-8"))
print("message received: ", msg)
print("message topic: ", message.topic)
if message.topic == "openWB/pv/W":
pow_ges = float(msg)
class DbusDummyService2:
def init(self, servicename, deviceinstance, paths, productname='Solaredge', connection='MQTT'):
self._dbusservice = VeDbusService(servicename)
self._paths = paths
logging.debug("%s /DeviceInstance = %d" % (servicename, deviceinstance))

Create the management objects, as specified in the ccgx dbus-api document

self._dbusservice.add_path('/Mgmt/ProcessName', file)
self._dbusservice.add_path('/Mgmt/ProcessVersion', 'Unkown version, and running on Python ' + platform.python_version())
self._dbusservice.add_path('/Mgmt/Connection', connection)

Create the mandatory objects

self._dbusservice.add_path('/DeviceInstance', deviceinstance)
self._dbusservice.add_path('/ProductId', 0xFFFF) # value used in ac_sensor_bridge.cpp of dbus-cgwacs
self._dbusservice.add_path('/ProductName', productname)
self._dbusservice.add_path('/Position', 0)
self._dbusservice.add_path('/FirmwareVersion', 0.1)
self._dbusservice.add_path('/HardwareVersion', 0)
self._dbusservice.add_path('/Connected', 1)
for path, settings in self._paths.items():
self._dbusservice.add_path(
path, settings['initial'], writeable=True, onchangecallback=self._handlechangedvalue)
gobject.timeout_add(1000, self._update) # pause 1000ms before the next request
def _update(self):
self._dbusservice['/Ac/Energy/Forward'] = pow_ges
self._dbusservice['/Ac/L1/Voltage'] = 230
self._dbusservice['/Ac/L2/Voltage'] = 230
self._dbusservice['/Ac/L3/Voltage'] = 230

self._dbusservice['/Ac/L1/Current'] = round(230*-3/pow_ges, 2)

self._dbusservice['/Ac/L2/Current'] = round(230*-3/pow_ges, 2)

self._dbusservice['/Ac/L3/Current'] = round(230*-3/pow_ges, 2)

self._dbusservice['/Ac/L1/Power'] = round(pow_ges/-3, 2)
self._dbusservice['/Ac/L2/Power'] = round(pow_ges/-3, 2)
self._dbusservice['/Ac/L3/Power'] = round(pow_ges/-3, 2)
self._dbusservice['/Ac/Power'] = pow_ges
logging.info("House Consumption: {:.0f}".format(pow_ges))

increment UpdateIndex - to show that new data is available

index = self._dbusservice[path_UpdateIndex] + 1 # increment index
if index > 255: # maximum value of the index
index = 0 # overflow from 255 to 0
self._dbusservice[path_UpdateIndex] = index
return True
def _handlechangedvalue(self, path, value):
logging.debug("someone else updated %s to %s" % (path, value))
return True # accept the change
def main():
logging.basicConfig(level=logging.DEBUG) # use .INFO for less logging
thread.daemon = True # allow the program to quit
from dbus.mainloop.glib import DBusGMainLoop

Have a mainloop, so we can send/receive asynchronous calls to and from dbus

DBusGMainLoop(set_as_default=True)
pvac_output = DbusDummyService2(
servicename='com.victronenergy.pvinverter.pv0',
deviceinstance=41,
paths={
'/Ac/Power': {'initial': 0},
'/Ac/L1/Voltage': {'initial': 0},
'/Ac/L2/Voltage': {'initial': 0},
'/Ac/L3/Voltage': {'initial': 0},
'/Ac/L1/Current': {'initial': 0},
'/Ac/L2/Current': {'initial': 0},
'/Ac/L3/Current': {'initial': 0},
'/Ac/L1/Power': {'initial': 0},
'/Ac/L2/Power': {'initial': 0},
'/Ac/L3/Power': {'initial': 0},
'/Ac/Energy/Forward': {'initial': 0},
path_UpdateIndex: {'initial': 0},
})
logging.info('Connected to dbus, and switching over to gobject.MainLoop() (= event based)')
mainloop = gobject.MainLoop()
mainloop.run()

Konfiguration MQTT

client = mqtt.Client(MQTTNAME) # create new instance
client.on_disconnect = on_disconnect
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username=username, password=password)
client.connect(broker_address, port) # connect to broker
client.loop_start()
if name == "main":
main()
(Ursprung: https://github.com/RalfZim/venus.dbus-fronius-smartmeter)

Smartmeter:
#!/usr/bin/env python
try:
import gobject # Python 2.x
except:
from gi.repository import GLib as gobject # Python 3.x
import platform
import logging
import time
import sys
import json
import os
import paho.mqtt.client as mqtt
try:
import thread # for daemon = True / Python 2.x
except:
import _thread as thread # for daemon = True / Python 3.x

our own packages

sys.path.insert(1, os.path.join(os.path.dirname(file), '../ext/velib_python'))
from vedbus import VeDbusService
path_UpdateIndex = '/UpdateIndex'

MQTT Setup

broker_address = "192.168.XXX"
port = 1883
MQTTNAME = "XXX"
username="XXX"
password="XXX"

Variblen setzen

verbunden = 0
durchlauf = 0
maxcellvoltage = 3.0
powercurr = 0
totalin = 0
totalout = 0

MQTT Abfragen:

def on_disconnect(client, userdata, rc):
global verbunden
print("Client Got Disconnected")
if rc != 0:
print('Unexpected MQTT disconnection. Will auto-reconnect')
else:
print('rc value:' + str(rc))
try:
print("Trying to Reconnect")
client.connect(broker_address)
verbunden = 1
except Exception as e:
logging.exception("Fehler beim reconnecten mit Broker")
print("Error in Retrying to Connect with Broker")
verbunden = 0
print(e)
def on_connect(client, userdata, flags, rc):
print("Verbunden mit IoBroker: " + broker_address)
client.subscribe("openWB/evu/W")
client.subscribe("openWB/evu/WPhase1")
client.subscribe("openWB/evu/WPhase2")
client.subscribe("openWB/evu/WPhase3")
client.subscribe("openWB/evu/WhImported")
client.subscribe("openWB/evu/WhExported")
def on_message(client, userdata, message):
global powercurr,power_p1, power_p2, power_p3, totalin, totalout
msg = str(message.payload.decode("utf-8"))
print("message received: ", msg)
print("message topic: ", message.topic)
if message.topic == "openWB/evu/W":
powercurr = float(msg)
if message.topic == "openWB/evu/WPhase1":
power_p1 = float(msg)
if message.topic == "openWB/evu/WPhase2":
power_p2 = float(msg)
if message.topic == "openWB/evu/WPhase3":
power_p3 = float(msg)
if message.topic == "openWB/evu/DailyYieldImportKwh":
totalin = float(msg)
if message.topic == "openWB/evu/DailyYieldExportKwh":
totalout = float(msg)
class DbusDummyService:
def init(self, servicename, deviceinstance, paths, productname='Smart Meter', connection='MQTT'):
self._dbusservice = VeDbusService(servicename)
self._paths = paths
logging.debug("%s /DeviceInstance = %d" % (servicename, deviceinstance))

Create the management objects, as specified in the ccgx dbus-api document

self._dbusservice.add_path('/Mgmt/ProcessName', file)
self._dbusservice.add_path('/Mgmt/ProcessVersion', 'Unkown version, and running on Python ' + platform.python_version())
self._dbusservice.add_path('/Mgmt/Connection', connection)

Create the mandatory objects

self._dbusservice.add_path('/DeviceInstance', deviceinstance)
self._dbusservice.add_path('/ProductId', 45069) # value used in ac_sensor_bridge.cpp of dbus-cgwacs
self._dbusservice.add_path('/ProductName', productname)
self._dbusservice.add_path('/FirmwareVersion', 0.1)
self._dbusservice.add_path('/HardwareVersion', 0)
self._dbusservice.add_path('/Connected', 1)
for path, settings in self._paths.items():
self._dbusservice.add_path(
path, settings['initial'], writeable=True, onchangecallback=self._handlechangedvalue)
gobject.timeout_add(1000, self._update) # pause 1000ms before the next request
def _update(self):
self._dbusservice['/Ac/Power'] = powercurr # positive: consumption, negative: feed into grid
self._dbusservice['/Ac/L1/Voltage'] = 230
self._dbusservice['/Ac/L2/Voltage'] = 230
self._dbusservice['/Ac/L3/Voltage'] = 230
self._dbusservice['/Ac/L1/Current'] = round(power_p1/230 ,2)
self._dbusservice['/Ac/L2/Current'] = round(power_p2/230 ,2)
self._dbusservice['/Ac/L3/Current'] = round(power_p3/230 ,2)
self._dbusservice['/Ac/L1/Power'] = round(power_p1, 2)
self._dbusservice['/Ac/L2/Power'] = round(power_p2, 2)
self._dbusservice['/Ac/L3/Power'] = round(power_p3, 2)
self._dbusservice['/Ac/Energy/Forward'] = totalin
self._dbusservice['/Ac/Energy/Reverse'] = totalout
logging.info("House Consumption: {:.0f}".format(powercurr))

increment UpdateIndex - to show that new data is available

index = self._dbusservice[path_UpdateIndex] + 1 # increment index
if index > 255: # maximum value of the index
index = 0 # overflow from 255 to 0
self._dbusservice[path_UpdateIndex] = index
return True
def _handlechangedvalue(self, path, value):
logging.debug("someone else updated %s to %s" % (path, value))
return True # accept the change
def main():
logging.basicConfig(level=logging.DEBUG) # use .INFO for less logging
thread.daemon = True # allow the program to quit
from dbus.mainloop.glib import DBusGMainLoop

Have a mainloop, so we can send/receive asynchronous calls to and from dbus

DBusGMainLoop(set_as_default=True)
pvac_output = DbusDummyService(
servicename='com.victronenergy.grid.cgwacs_ttyUSB0_mb1',
deviceinstance=0,
paths={
'/Ac/Power': {'initial': 0},
'/Ac/L1/Voltage': {'initial': 0},
'/Ac/L2/Voltage': {'initial': 0},
'/Ac/L3/Voltage': {'initial': 0},
'/Ac/L1/Current': {'initial': 0},
'/Ac/L2/Current': {'initial': 0},
'/Ac/L3/Current': {'initial': 0},
'/Ac/L1/Power': {'initial': 0},
'/Ac/L2/Power': {'initial': 0},
'/Ac/L3/Power': {'initial': 0},
'/Ac/Energy/Forward': {'initial': 0}, # energy bought from the grid
'/Ac/Energy/Reverse': {'initial': 0}, # energy sold to the grid
path_UpdateIndex: {'initial': 0},
})
logging.info('Connected to dbus, and switching over to gobject.MainLoop() (= event based)')
mainloop = gobject.MainLoop()
mainloop.run()

Konfiguration MQTT

client = mqtt.Client(MQTTNAME) # create new instance
client.on_disconnect = on_disconnect
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(username=username, password=password)
client.connect(broker_address, port) # connect to broker
client.loop_start()
if name == "main":
main()

Das war es schon. Sieht komplizierter aus, als es ist. Hab jetzt den zweiten Akku fertig. Da hat mich das ganze vielleicht 5 Minuten gedauert zu konfigurieren. Wichtig: Die anderen Dateien die hier (https://github.com/RalfZim/venus.dbus-fronius-smartmeter) zur Verfügung gestellt werden brauchst Du auch im Venus OS. Und dann bitte an die dortige Installationsanleitung halten. Der hier gepostete Anleitung ist nur meine persönliche Anpassung.

Hallo zusammen,

noch Mal eine kurze Frage die irgendwie nie so richtig beantwortet wurde.... für mich!:smile:
Den Typ habe ich schon Mal, ein JK mit 2A Balancer und 150A!
Meine Frage:
-Die RS485 Schnittstelle läuft über einen Adapter den ich zusätzlich kaufen muss. Muss ich auf irgendwas achten oder geht der immer dran?
- Can Bus muß man mit bestellen! Wofür benötige ich Ihn. RS 485 reicht doch dür die Kommunikation? Würde es schaden/irgendetwas anderes ausschließen wenn man es gleich mit bestellt?
Möchte am Ende nicht noch eines kaufen da die Kommunikation zum Venus OS oder IObroker nicht klappt.

Danke Olli

Nimm den oben verlinkten USB zu RS485 Adapter. Dann noch den JK RS485 Adapter. Fertig. Ist oben alles verlinkt. Canbus brauchst du dann nicht.

Hi,
habe gestern den JK an Raspi4 angebunden.
OHNE den JK Adapter. (ich frage mich für was der wirklich gut ist... )
RS485/USB Kabel direkt am BMS angeschlossen. (ohne +)
-> Geht :thumbup:

RS485/USB
Stecker

jarek

Noch besser! Welche RS485 Adapter hast Du? Ist wahrscheinlich einer der auch TTL kann, richtig?

Edit: Sehe gerade, dass Du den Adapter verlinkt hast. Ja, das ist ein TTL Adapter. Habe auch davon gelesen, dass das klappt, aber selbst noch nicht getestet. Schön zu hören, dass das so einfach klappt.

Habe vor 2 Wochen beim HankzorBMS Store nun auch über Aliexpress ein JK-B2A24S20P samt Zubehör bestellt, und hängt jetzt wohl im Zoll fest:
"Import clearance exception" bei Cainiao Tracking und "Status Offen" am IPZ Frankfurt bei DHL

War das bei euch auch? Hab schon lange nix mehr bei Aliexpress bestellt und kenne da die Zollabläuft nicht mehr :roll:

Eigentlich geht das mit durch... Aber Feind haben sie wohl raus gesucht, durch das BT Modul kannst Pech haben... Aber erst mal warten, dann bekommst Post

Eigentlich geht das mit durch... Aber Feind haben sie wohl raus gesucht, durch das BT Modul kannst Pech haben... Aber erst mal warten, dann bekommst Post
oh man... ich bin gespannt... da ist mein endlich fast fertig mit Kapazitätstest der Zellen und bereit zum Akku Bau... dann kommt der Zoll in die quere :cry: :cry:

Habe auch alles bestellt, ich hoffe es klappt.

Juhu, heute hat die Post geklingelt und mir gegen 33€ das Päckchen übergeben :smiley: Im Tracking war davor übrigens dann nur bei DHL seit gestern Abend was zu sehen... falls sich mal jemand die gleichen Sorgen macht, das dem Zoll das BT nicht gefällt :lol:

Nun zum Anschluss... habe die "RS485" Version bestellt, bei welcher schon der RS485 Adapter dabei ist aber wo muss ich den jetzt einstecken?
Am "CAN/RS485" Port passt der Stecker nicht rein sondern num am "GPS" Port, ist das korrekt? Und könnte ich da jetzt auch direkt mit nem TTL/USB Wandler dran so wie @jarek ?

Klar,
Aber nur um an den Stecker zu kommen hättest du nicht den RS485 Adapter mit kaufen müssen. Die gibt es auch einzeln, oder mit ein Stück Kabel dran.

Ja das weiß ich mittlerweile auch :wink:
Hatte bei der Bestellung aber nicht gemerkt das da ein Adapter dabei ist sondern dachte das wird dann direkt auf dem Board aktiviert...
Außerdem wusste ich damals noch nicht das ein USB-TTL Wandler reicht, kann ich mit dem hier direkt auf den GPS Port gehen? Der liegt noch rum:
USB-TTL Adapter

Das steht die Steckerbelegung:
https://github.com/syssi/esphome-jk-bms
und da auch:
https://de.aliexpress.com/item/1005003104573871.html

Rotes kabel abschneiden.

Hi!
Falls jemand den USB-TTL direkt am JK-BMS angeschlossen hat: könntest du mal ein Foto davon hochladen, bitte?
Ich würde das gerne mit dbus-serialbattery und Venus OS nutzen...

Bei mir klappte der Direktanschluss am RS485/GPS Port bis jetzt nicht. Der Raspi sieht das JKBMS nicht.

Habe es mit einem standard TTL usb Adapter sowie mit dem von Waveshare (welcher den gleichen Chipset verwendet wie das original Victronkabel) versucht.
Entweder habe ich irgendwo nen Fehler drin oder ich brauche doch den RS485 Adapter von JK.

Werde es aber weiterprobieren weil bei anderen hat es ja funktioniert....

Ich dokumentiere das jetzt mal hier:
Da es mir keine Ruhe gelassen hat, hab ich das nochmal nachgestellt. Das JK-BMS hat eine serielle (RS232) Schnittstelle. Der Adapter, den man mitbestellen kann, wandelt von RS232 in RS485, deshalb braucht man dann auch den USB-to-RS485 Adapter.
Man kann aber auch einfach mit einem USB-to-serial oder USB-to-RS232 Adapter direkt an das BMS gehen. Ich habe das gerade getestet und es funktioniert mit dbus-serialbattery und Venus OS.
Steinigt mich bitte nicht wegen der Verkabelung der seriellen Verbindung - das wird noch "schön" gemacht und vor allem mit einem anderen Adapter realisiert - diesen hatte ich noch in meiner Bastelkiste rumfliegen :slight_smile:

Ist das Protokoll bzw. der genaue Datenverkehr irgendwo dokumentiert? Ich möchte versuchen, die Daten in eine Steuerung einzulesen.

...hab da was bei mir - ob das stimmt? :?: :angel: :think:

40874=7070-BMS.485.instruction.pdf|attachment (700 KB)

40874=7069-BMS.CAN_.instruction.pdf|attachment (150 KB)

Danke schön, na das ist doch schonmal was :slight_smile:
CAN kann das JK aber nicht, oder? Steckverbinder ist zwar vorhanden, aber ich glaube mal gelesen zu haben, dass das nicht funktioniert.