Hoe ik een Big-ASS Battery ombouwde voor gebruik met Victron

Onlangs kreeg ik een aantal industriële Big-ASS Battery modules uit een faillissement in handen. Deze accupakketten zijn oorspronkelijk ontworpen voor professioneel gebruik en bevatten cilindrische LiFePO4-cellen (Lithium Iron Phosphate). Er zit echter één belangrijk nadeel aan de originele configuratie: er is géén echte BMS aanwezig.

In deze blog laat ik zien hoe ik deze accu’s heb omgebouwd voor gebruik met een JK-BMS v19, zodat ze veilig gebruikt kunnen worden met een Victron MultiPlus II, maar uiteraard ook met andere omvormers en energiesystemen.

De accu

Volgens het typeplaatje betreft het een:
  • Nominale spanning: 25,6 V
  • Capaciteit: 7 kWh
  • Chemie: LiFePO4
  • Maximale stroom: 250 A

Na het openen van de module blijkt de accu opgebouwd te zijn uit 42 cellen parallel en 8 groepen in serie. Dus in totaal 336 cellen per module.

De capaciteit komt uit rond de 250-280 Ah, wat goed overeenkomt met de specificaties van de module.

Het originele systeem: géén BMS maar een LMU

De geïnstalleerde printplaat is een Lithium Balance LMU – Local Monitoring Unit. De LMU meet:

  • individuele celspanningen
  • totale accuspanning
  • temperatuur (1 of 2 sensoren afhankelijk van revisie)

Maar kan niet zelfstandig laden of ontladen uitschakelen. Er zitten geen vermogens-MOSFETs in de module om de accu te beschermen.

De originele toepassing gebruikte meerdere LMU’s die gekoppeld waren aan een centrale controller. Pas die centrale controller nam beslissingen over overvoltage, undervoltage, overtemperature en stroombegrenzing.

Zonder die centrale controller is de accu dus feitelijk onbeveiligd.

Daarom heb ik ervoor gekozen de originele elektronica te verwijderen en een moderne JK-BMS te plaatsen.

Waarom een Jikong JK-BMS v19?

Voor deze ombouw heb ik gekozen voor een JK-BMS v19.

  • Actieve balancing
  • Bluetooth
  • CAN-bus ondersteuning
  • RS485
  • Geschikt voor Victron
  • Hoge stroomcapaciteit
  • Goede app

De JK-BMS wordt breed gebruikt binnen de DIY-accu- en Victron-community. Ook Off-Grid Garage, een van de bekendste YouTube-kanalen op het gebied van thuisaccu’s en off-grid energiesystemen, heeft in diverse projecten goede resultaten laten zien met deze BMS.

Demontage

Eerst heb ik het frontje verwijderd en de originele LMU verwijderd. Daarna worden de twee originele connectoren zichtbaar.

Deze blijken Molex Mini-Fit Jr. 4,2 mm connectoren te zijn. Dat zijn dezelfde connectoren die je veel tegenkomt in pc-voedingen.

Benodigd gereedschap

Voor het demonteren van de bestaande connectoren en het krimpen van een nieuwe, heb ik deze set van Amazon gebruikt: https://www.amazon.nl/dp/B0DTJFCV6S

De set bevat:

  • krimptang
  • Mini-Fit Jr contacten
  • connectoren
  • removal tool

Die removal tool blijkt handig om de bestaande connectoren te hergebruiken. Soms wil een contact niet loskomen. In dat geval kun je een kleine inbussleutel gebruiken of eventueel een kleine schroevendraaier.

Bestaande busbar hergebruiken

Om de BMS aan te sluiten, heb ik de originele koperen busbar uit de rev 1.0 accu hergebruikt. (De rev1.1 bevat een flexibele busbar).

Hiervoor heb ik een stuk van 5 cm afgezaagd, een extra gat geboord en de busbar licht gebogen. Daardoor komt de JK-BMS iets schuin naar beneden te hangen, wat precies voldoende ruimte geeft.

Op de foto’s is goed te zien hoe de originele busbar nu de verbinding vormt tussen B- van de JK-BMS en de accu.

 

Aan de positieve zijde heb ik direct een 200A Mega Fuse gemonteerd.

Revisie 1.0 versus 1.1

Tijdens de ombouw kwam ik erachter dat ik twee verschillende uitvoeringen had.

Rev 1.0

  • Geen revisieaanduiding op het label
  • Eén temperatuursensor
  • Min-aansluiting ontbreekt in de 8-polige Molex connector

Rev 1.1

  • Label vermeldt Rev 1.1
  • Twee temperatuursensoren
  • Connectoren zijn 180 graden gedraaid
  • Min-aansluiting wel aanwezig in de 8-polige connector

Bij de rev 1.0 heb ik een extra draad toegevoegd zodat de ontbrekende min-aansluiting alsnog beschikbaar is op pin 1.

Nieuwe balanceerkabel maken

De bedrading die met de BMS meegeleverd is, heeft dikte AWG22 (0,34 mm²). De bestaande pinnen heb ik uit de Molex connectoren van de accu gehaald en vervangen door nieuwe contacten. Vervolgens de rode draden en zwarte draad van de JK-BMS aangesloten.

Bij een 8S JK-BMS gaan de laatste twee draden naar de pluszijde van het accupakket. Dat is normaal en volgt exact het schema van JK.

Controle vóór aansluiten

Voordat de balanceerkabel op de BMS wordt aangesloten, sluit de kabel aan op de accu en meet alle aansluitingen door. Meet steeds met de zwarte meetpen op B- en de rode meetpen één positie verder.

Ook de temperatuursensoren zijn aangesloten op de JK-BMS.

Je zou ongeveer moeten zien:

Meetpunt Spanning
1 3,2 V
2 6,4 V
3 9,6 V
4 12,8 V
5 16,0 V
6 19,2 V
7 22,4 V
8 25,6 V

Als dit klopt, mag de connector op de BMS worden aangesloten.

JK-BMS configureren

Na het aansluiten kan de BMS worden ingeschakeld. Dat kan met de meegeleverde knop of met de knop op een aangesloten display.

Installeer vervolgens de JK-BMS app en maak verbinding via Bluetooth. Het Bluetooth-ID staat op de BMS vermeld. Stel daarna minimaal in:

Screenshot
  • Batterijtype: LiFePO4
  • Capaciteit: 250 Ah

Het standaard wachtwoord is 123456.

Screenshot
Screenshot

Klaar voor Victron

Na deze ombouw beschikt de Big-ASS Battery over een volwaardige BMS. De accu kan nu veilig worden gebruikt en worden opgeladen.

In mijn geval draait de accu inmiddels probleemloos samen met een Victron MultiPlus II.


Aansluitschema balanceerkabel

Voor het aansluiten van de JK-BMS heb ik de originele Mini-Fit Jr. connectoren hergebruikt.

Bedrading Rev 1.1

Let op: bij revisie 1.1 zijn de connectoren 180 graden gedraaid ten opzichte van rev 1.0.

8-polige connector

Pin Functie
1 26,2 V → JK draad 8
2 19,7 V → JK draad 6
3 13,1 V → JK draad 4
4 6,5 V → JK draad 2
5 NTC
6 NTC
7 NC
8 0 V → JK draad 0 (zwarte draad)

6-polige connector

Pin Functie
1 9,8 V → JK draad 3
2 16,4 V → JK draad 5
3 22,9 V → JK draad 7
4 3,2 V → JK draad 1
5 NTC
6 NTC

Bedrading Rev 1.0

Bij revisie 1.0 ontbreekt de min-aansluiting in de originele bekabeling. Hiervoor heb ik een extra zwart draadje toegevoegd zodat B− alsnog beschikbaar is voor de JK-BMS.

8-polige connector

Pin Functie
1 0 V → JK draad 0 (zwarte draad)
2 NC
3 NTC
4 NTC
5 6,5 V → JK draad 2
6 13,1 V → JK draad 4
7 19,7 V → JK draad 6
8 26,2 V → JK draad 8

6-polige connector

Pin Functie
1 NC
2 NC
3 3,2 V → JK draad 1
4 22,9 V → JK draad 7
5 16,4 V → JK draad 5
6 9,8 V → JK draad 3

SolarEdge SE7K Modbus TCP

Ik wilde mijn oudere SolarEdge SE7K omvormer uit 2017 (de variant met LCD display) lokaal kunnen uitlezen en netjes softwarematig kunnen beperken bij negatieve stroomprijzen. De SolarEdge cloud/API werkt prima, maar ik wilde:

  • geen afhankelijkheid van internet/cloud
  • realtime lokale data
  • integratie met Node-RED
  • de omvormer automatisch kunnen curtailen bij negatieve prijzen

In eerste instantie ging ik er vanuit dat ik hiervoor de seriële RS485-poort moest aansluiten. Na wat verder onderzoek bleek echter dat deze oudere SE7K gewoon Modbus TCP ondersteunt via Ethernet. De netwerkkabel zat al aangesloten. Modbus TCP hoefde alleen nog aangezet te worden in het menu van de omvormer.

Modbus TCP kort uitgelegd

Modbus TCP is een simpel industrieel protocol waarbij registers gelezen en geschreven worden via TCP/IP.

De SolarEdge exposed intern een SunSpec registermap via Ethernet.

Dus:

  • uitlezen van actuele productie
  • temperatuur
  • lifetime opbrengst
  • netspanning
  • status
  • en zelfs active power limiting

Navigeren op de oude LCD SolarEdge

Deze oudere generatie heeft slechts één knop onder het display. De bediening werkt als volgt:

  • korte druk = door menuopties bladeren
  • lange druk = bevestigen / enter

Modbus TCP aanzetten

Via het LCD-menu:

Daarna rebooten (belangrijk, anders draait de Modbus service nog niet!):
  1. DC switch uit
  2. 1 minuut wachten
  3. AC uit
  4. AC aan
  5. DC aan

Daarna staat poort 502 open. Controleer dit met het onderstaande bash commando:

nc -vz 192.168.1.72 502

Python setup

Installeren:

pip3 install pymodbus

Actueel vermogen uitlezen

Bij mijn SE7K zit het actuele AC-vermogen op:

Address 83

Script:

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient("192.168.1.72", port=502)

rr = client.read_holding_registers(
    address=83,
    count=2,
    device_id=1
)

power = rr.registers[0]
scale = rr.registers[1]

if scale > 32767:
    scale -= 65536

print(power * (10 ** scale), "W")

client.close()

Voorbeeld output:

1838.0 W

Interessante registers voor de SE7K

Functie Address
AC vermogen 83
Lifetime energy 93
Temperatuur 95
Netfrequentie 96
AC voltage 76
DC voltage 71
Status 107

Statuscodes:

Waarde Betekenis
1 Off
2 Sleeping
4 Producing
5 Production limited
7 Fault

Curtailment / Active Power Limit

Curtailment betekent het bewust beperken van de zonneproductie.

Dus:

  • panelen kunnen meer leveren
  • maar de omvormer wordt softwarematig begrensd

Bijvoorbeeld:

  • 100% = normaal
  • 50% = halve productie
  • 0% = praktisch uit

Handig bij negatieve stroomprijzen.

SolarEdge registers voor power limiting

Bij mijn SE7K werken deze registers:

Register Functie
61762 Advanced Power Control enable
61441 Active Power Limit (%)
61696 Commit/apply settings

Omvormer op 0W zetten

Dit script zet de omvormer netjes softwarematig op 0% productie:

from pymodbus.client import ModbusTcpClient
import time

HOST = "192.168.1.72"
PORT = 502
DEVICE_ID = 1

# 0 = uit
# 50 = halve productie
# 100 = normaal
LIMIT_PERCENT = 0

client = ModbusTcpClient(HOST, port=PORT, timeout=5)

try:
    print("Connect:", client.connect())

    # Advanced Power Control enable
    client.write_registers(
        address=61762,
        values=[0, 1],
        device_id=DEVICE_ID
    )

    time.sleep(1)

    # Active Power Limit
    client.write_register(
        address=61441,
        value=LIMIT_PERCENT,
        device_id=DEVICE_ID
    )

    time.sleep(1)

    # Commit/apply
    client.write_register(
        address=61696,
        value=1,
        device_id=DEVICE_ID
    )

    time.sleep(10)

    # Actueel vermogen uitlezen
    rr = client.read_holding_registers(
        address=83,
        count=2,
        device_id=DEVICE_ID
    )

    power = rr.registers[0]
    scale = rr.registers[1]

    if scale > 32767:
        scale -= 65536

    print("Limit set to:", LIMIT_PERCENT, "%")
    print("Current AC power:", power * (10 ** scale), "W")

finally:
    client.close()

Bij LIMIT_PERCENT = 0 ging mijn SE7K daadwerkelijk naar:

0 W

zonder harde uitschakeling van de omvormer.

Referenties

Vue 3 TypeScript edition

The biggest notable new features for Vue 3 are the Composition API  and full support for TypeScript. Overall Vue 3 is mostly backwards compatible. The only change I’ve found rewriting the Bitcoin Converter is that in 3.x, filters are removed and no longer supported. Instead, they can be replaced by a method call.

And there’s a new build tool in the Vue ecosystem called Vite. Its dev server is 10-100x faster than Vue CLI’s. We used Vite instead of Vue-CLI this time to scaffold the project and to start the dev server.

Composition API

To read in detail about the Composition API, see the original Vue documentation about the Composition API: An introduction to the Composition API.

Basically everything for the component is now initialised in the new setup function. This function is executed before the component is created, once the props are resolved, and serves as the entry point for composition API’s.

Reactive variables need to be wrapped in ref() functions.

A components setup function might look like this:

import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch, toRefs } from 'vue'
 
setup (props) {
  
  const { user } = toRefs(props)
  const repositories = ref([])
  const getUserRepositories = async () => {    
    repositories.value = await fetchUserRepositories(user.value)
  }
 
  onMounted(getUserRepositories)
  watch(user, getUserRepositories)
 
  return {
    repositories,
    getUserRepositories
  }
}

TypeScript

TypeScript enables us to use types and have those types checked during the compile phase.

setup(props: Readonly<IProps>) {
    const loadingStatus = ref<String>(LOADING_STATUS.NOT_LOADING);
    const loadingError = ref<String>();
    const tickerPrice = ref<TickerPrice>();
}

“Vite” Build Tooling

Similar to Vue CLI, Vite is also a build tool providing basic project scaffolding and a dev server.

However, Vite is not based on Webpack and has its own dev server which utilizes native ES modules in the browser. This architecture allows is to be orders of magnitude faster than Webpack’s dev server.

Vite is currently in beta and it appears that the aim of the Vite project is not to be an all-in-one tool like Vue CLI, but to focus on providing a fast dev server and basic build tool.

Demo

Live demo Vue 3 – Bitcoin Converter

https://sandbox.juurlink.org/vue3/

Resources

 

All variants of the Bitcoin Converter Application

  • 2021 – Vue 3 TypeScript Bitcoin converter application blog src demo
  • 2020 – Vue.js Bitcoin converter application – part 2 blog src demo
  • 2019 – Vue.js Bitcoin converter application – part 1 blog src demo
  • 2017 – Angular Bitcoin converter application [blog] src demo
  • 2013 – AngularJS Bitcoin converter application blog src demo
  • 2013 – Backbone Bitcoin converter application blog src demo

Mutual Exclusion in Javascript

According to Wikipedia Mutual Exclusion means:

Mutual exclusion is a property of concurrency control, which is instituted for the purpose of preventing race conditions. It is the requirement that one thread of execution never enters its critical section at the same time that another concurrent thread of execution enters its own critical section.

Well in short it means execute only a part of the code by one thread at the same time.

Back in my Java days™️, Java had a nice simple keyword to make a method synchronized, which means mutually exclusive. Javascript doesn’t have something similar, that’s the reason I came up with this Javascript mutex implementation. It’s probably not perfect, but hey, it does the job!

This example shows how to create a function that returns a promise in which the work executes synchronized:

See Github for full source code


const data = {
    counter: 0
}

/**
 * Some heavy calculations in a promise.
 *
 * @param {number} executionSequence The index number of execution
 * @param {{counter:number}} data Wrapper object with counter
 * @return {Promise<number>} Promise that resolves on success or rejects otherwise
 */
function execute(executionSequence, data) {
    const promise = new Promise(resolve => {
        synchronized(release => {

            // Release the lock when the promise is done.
            promise.finally(release);

            // Wait a random time between 0 and 2 seconds.
            setTimeout(() => {

                data.counter++;
                console.log('Execute promise: ' + executionSequence);
                console.log('Counter: ' + data.counter);
                resolve(data.counter);

            }, Math.random() * 2 * 1000);
        });
    });
    return promise;
}

for (let i = 1; i <= 10; i++) { console.log(`==== Create promise: ${i}`); execute(i, data).then(result => {
        console.log(`Promise success: ${i}, result: ${result}`);
    })
}

 

The title image is shamefully stolen from this article:
Mollie: How to use Mutex locks responsibly

Template Literals Templating

What are Template Literals?

Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them. Template Literals are part of the ES6 specification.

Actually they even contain the basic requirements to use it as a templating language!

Continue reading “Template Literals Templating”

Vue.js; AngularJS done right! – part 2

Just started with Vue? Please read part 1 first. It’s a small introduction into the Vue framework.

In part one we have created our first application using Vue. Functionally that application is complete but it is lacking a nice architecture, it is not translated, it did not have any unit tests and we did not leverage the complete power of single file components and CLI tooling to scaffold the project.

Continue reading “Vue.js; AngularJS done right! – part 2”

Vue.js; AngularJS done right!

This post describes briefly my first impressions of working with the Vue frontend framework.

I have been using Vue for only a couple of days now and during these days I have created an example application (a bitcoin converter).

Before, I have created the same application using other frameworks like AngularJS and Backbone, so this makes a comparison between the use of different frameworks possible.

Continue reading “Vue.js; AngularJS done right!”

Run Jenkins Automation Server as Docker Image

Introduction

Even for my side projects it is convenient to have my personal automation server run. As far as I know, this type of server is also known as Continues Integration CI environment and I use those terms interchangeable. Beside being convenient, it is also fun and I might even learn something from it!

The most popular open source CI at this moment is Jenkins. So that is the one I am going to install.

Continue reading “Run Jenkins Automation Server as Docker Image”