CAN and RS485 BMS Emulated Protocols for DIY Battery to work with LV and HV Invertors - JK BMS JBD Daly 123Smart - OEM Battery


ALL NEW - Battery Finder Search for 12/24/36/48v or by capacity www.batteryfinder.net
New & used Batteries, Solar, accessories, LifePo4 cells & more 5% Coupon "Powerwalls" www.batteryhookup.com
That is what the project solutionized as far as i also understand - they allow for both Battery units to be configured as Master / Slave - Battery -1 as Master to CAN port , Slave of second battery unit to MAster Battery RS485 (tx/rx) of ESP....
I'm hoping that this is what can occur (having 11 JK BMS's in parallel in my case).

I know you can set individual addresses for the 'newer' JK BMS's (not the so-called inverter compatible series), however it's a bit ambiguous if that means for RS485(ttl), BT....or what...(?)
 
Hi @mrconstantin84,
This looks like an awesome tool! Looking forward to getting it set up.

So far I've got the fw flashed to an ESP32 and its saying I have the wrong APP key.

Looking through the thread you need my chip ID to send me a key?
The chip ID is e81f9c9c

I'm looking to get it working with a JKBMS BD4A23S4P to start with and if this goes well I will probably get some higher current JKBMS. I specifically would like to be able to graph the individual cell voltage in emoncms.

Do you have the sourcecode on github/GoogleDrive anywhere or is it "proprietory" code you are unable to share? Hence the use of the App key?

Reason I as is that I'd like to add code to send the data to emoncms via a http request.

I already have a framework I built for data collection/translation originally based on tzapu WifiManager but now taken from khoih-prog ESPAsync_WifiManager using ASYNCWebServer. I took the best bits from both, thinned out what I didn't need, improved setup/config parameters and fixed it to compile for both ESP32-S2/C3 and ESP8266.

I use it for collecting data from Deepsea Gensets and Carlo Gavazzi EM21s using modbus over RS485 among other things.

My code pushes data to EMONCMS using http get and I was hoping to be able to add it to your project to also push JKBMS data to emoncms and compile for my existing ESP8266 modules.

Thanks!

Andy.
 
For HV protocols , i upload new DIYB4I v1 with more easy debug function . For testing the protocol just use fake battery data.

Log 1.jpg

Also all ports can be tested for trafic / also the can msg comms

Log.jpg
 
Lool...you made me laugh when I read this line....don't worry at all I completely understand that you guys are busy
I count myself lucky when I get a reply from anyone of you project leaders.

I was just informed of the solution you have already in place where one can have 2 CAN ports - I was just about to start searching for that information and develop on it.


1 - Battery Hardare Setup - Solis inverter connected to 2 batteries (solution is supposed to look like the below diagram, but i didn't know how to get the 2 JKBMS.s to talk so i have omitted the RS485 communication for now of which its working but i don't trust it)

2 - Invertor protocol u need - i am using Pylontech protocol, i do not mind other protocols as long as its one that is listed in the Solis inverter options

3 - status of ur project - I would say 95 % completed , - not sure if the GPIO will change if i find your solution which would mean reflashing of the ESP32 chips

4 - we talk on whatup / viber / telegram before - i don't mind if we can talk on WhatsApp or Discord that would be great

My objective

View attachment 31606
I all ready answare to u on other topic, but put it again,

u have only 2 bateries

just conect one on rs485 and one on serial on same interface with lv fremwere.
use pylon or seplos protocol will work directly on solis lv is already tested.
 
That is what the project solutionized as far as i also understand - they allow for both Battery units to be configured as Master / Slave - Battery -1 as Master to CAN port , Slave of second battery unit to MAster Battery RS485 (tx/rx) of ESP....
i am not shure if i understand how u want to connect.

in interface u can put id for each battery, and can make one device master and rest are slave to combine the data.
but u cant connect on same rs485 to jkbms directly from ther uart port because they will answerer to same commands

to jk balancer can assign addresses for can and for rs485 port
 
Hi @mrconstantin84,
This looks like an awesome tool! Looking forward to getting it set up.

So far I've got the fw flashed to an ESP32 and its saying I have the wrong APP key.

Looking through the thread you need my chip ID to send me a key?
The chip ID is e81f9c9c

I'm looking to get it working with a JKBMS BD4A23S4P to start with and if this goes well I will probably get some higher current JKBMS. I specifically would like to be able to graph the individual cell voltage in emoncms.

Do you have the sourcecode on github/GoogleDrive anywhere or is it "proprietory" code you are unable to share? Hence the use of the App key?

Reason I as is that I'd like to add code to send the data to emoncms via a http request.

I already have a framework I built for data collection/translation originally based on tzapu WifiManager but now taken from khoih-prog ESPAsync_WifiManager using ASYNCWebServer. I took the best bits from both, thinned out what I didn't need, improved setup/config parameters and fixed it to compile for both ESP32-S2/C3 and ESP8266.

I use it for collecting data from Deepsea Gensets and Carlo Gavazzi EM21s using modbus over RS485 among other things.

My code pushes data to EMONCMS using http get and I was hoping to be able to add it to your project to also push JKBMS data to emoncms and compile for my existing ESP8266 modules.

Thanks!

Andy.
54f24c2e3cf51515887095a8ac0e00a9

for what protocol do u need can regs?
 
I'm hoping that this is what can occur (having 11 JK BMS's in parallel in my case).

I know you can set individual addresses for the 'newer' JK BMS's (not the so-called inverter compatible series), however it's a bit ambiguous if that means for RS485(ttl), BT....or what...(?)
for u the solution is like that:

connect to each interface 2 jkmbs with rs485 , put different battery id on settings of interface.
and will need one interface will the master to combine of the data.
for example for reg 0x305
first will be 0x1305 , second will be 0x2305 ....etc this is extended frame usually the lv invertors not read extended regs so in same can network u will have the master with reg 0x305 and salve with extended regs.

so u can connect 11 jkbms with 5 interfaces to send data to invertor
 
Heeeeelp Mrconstabtin84,
I have a quick question,
I have 3 Sonnen server rack batteries 2.5 kWhr each. I am using them with a
very un-smart inverter, a 48 volt inverter (no canbus). The batteries have a Pylontech BMS. I can get
information from them through the RS232 port but I can't control them meaning I turn them on and 10
minutes later they turn off. I went and learned all I can about canbus, found my old Raspberry pi and got a mcp2515
learned a lot of python programming. Listening on the canbus from a battery I get data for 7 Canbus Id's 4201-4207
have you ran across those Canbus Id's anywhere? I have the Pylontech Protocol 5 page hand out and it seems that Sonnen took
a Pylontech battery and did there own thing with it.

(2024-03-11 20:52:53.790888) can0 00004201 [4] 03 53 EF 65
(2024-03-11 20:52:53.791139) can0 00004202 [7] 1D 14 03 00 FA 00 01
(2024-03-11 20:52:53.792016) can0 00004203 [8] 64 63 6F 13 6F 13 55 00
(2024-03-11 20:52:53.792310) can0 00004204 [7] 00 00 00 00 00 02 00
(2024-03-11 20:52:53.793120) can0 00004205 [8] CD 14 00 00 5C 12 88 13
(2024-03-11 20:52:53.793418) can0 00004206 [8] 03 00 03 00 1D 14 1D 14
(2024-03-11 20:52:53.794232) can0 00004207 [8] 6B 0D 64 0D DC 00 DC 00
 
Heeeeelp Mrconstabtin84,
I have a quick question,
I have 3 Sonnen server rack batteries 2.5 kWhr each. I am using them with a
very un-smart inverter, a 48 volt inverter (no canbus). The batteries have a Pylontech BMS. I can get
information from them through the RS232 port but I can't control them meaning I turn them on and 10
minutes later they turn off. I went and learned all I can about canbus, found my old Raspberry pi and got a mcp2515
learned a lot of python programming. Listening on the canbus from a battery I get data for 7 Canbus Id's 4201-4207
have you ran across those Canbus Id's anywhere? I have the Pylontech Protocol 5 page hand out and it seems that Sonnen took
a Pylontech battery and did there own thing with it.

(2024-03-11 20:52:53.790888) can0 00004201 [4] 03 53 EF 65
(2024-03-11 20:52:53.791139) can0 00004202 [7] 1D 14 03 00 FA 00 01
(2024-03-11 20:52:53.792016) can0 00004203 [8] 64 63 6F 13 6F 13 55 00
(2024-03-11 20:52:53.792310) can0 00004204 [7] 00 00 00 00 00 02 00
(2024-03-11 20:52:53.793120) can0 00004205 [8] CD 14 00 00 5C 12 88 13
(2024-03-11 20:52:53.793418) can0 00004206 [8] 03 00 03 00 1D 14 1D 14
(2024-03-11 20:52:53.794232) can0 00004207 [8] 6B 0D 64 0D DC 00 DC 00

Let me undestand ur situation.

ur bms stop working (cut power) after 10 minutes after u power up because dont communicate with invertor?

i think u need to simulate the invertor, and send the announcement regs to battery, just try to send 04200 to the battery
 
Hey @mrconstantin84!

Many thanks for the App Key.

for what protocol do u need can regs?

I am not using can or modbus for this.

I'm connecting the ESP32 direct to the JKBMS using serial (to the RS485 JST connector).

I want to be able to send cell voltage data from the JKBMS to emoncms which uses a http POST to send json data like this:

C++:
  #ifndef pgEMONCMS_H
  #define pgEMONCMS_H

  #include <Arduino.h>
  #include "Ecms_Struct.h"

  #if defined(ARDUINO_ARCH_ESP8266)
    #include <ESP8266HTTPClient.h>
  #elif defined(ESP32)
    #include <HTTPClient.h>
  #else
    #error Architecture unrecognized by this code.   
  #endif

#ifdef SECURE_ENABLED 
  #include <WiFiClientSecure.h>
#endif

  extern float psuVolts;
  extern String ecms_LastResult;

  namespace emoncms {
    
    bool send2emoncms(emoncmsParams ecmsParam, const char * const ecmsDataNames[], float * ecmsResults, int arraySize);
    bool send2emoncms(emoncmsParams ecmsParam, const String &strJsonData);
 
  } // end namespace

  String strJsonData = new char[1024];  // Global. Keep our place on the heap.
  bool emoncms::send2emoncms(emoncmsParams ecmsParam, const char * const ecmsDataNames[], float * ecmsResults, int arraySize){
    // Make a name:value pair JSON out of the two arrays names and results. Eg: "n1:v1","n2:v2",...,"n99:v99"
    strJsonData = "";
    int maxIndex = arraySize; // sizeof(mbResults)/sizeof(*mbResults);
    char bufr[20];
    for (int i=0; i < maxIndex; i++){
      if (i!=0) strJsonData += ",";
      memcpy_P(bufr, ecmsDataNames[i],20);
      strJsonData += "\"" + (String)bufr + ":" + ecmsResults[i] + "\"";
    }
    return send2emoncms(ecmsParam, strJsonData);
  }
 
  WiFiClient ecms_client;
#ifdef SECURE_ENABLED
    WiFiClientSecure ecms_secureClient;
#endif
  HTTPClient ecms_http;
  bool emoncms::send2emoncms(emoncmsParams ecmsParam, const String &strJsonData ){
    // The uri looks like "/emoncms/input/post".

#ifdef SECURE_ENABLED     
    bool useHttps = false; if (ecmsParam.Port == 443) useHttps = true;

    if (useHttps){
      CONSOLE(F("EMONCMS using https: ")); CONSOLELN((String)ecmsParam.server + ":" + String(ecmsParam.Port) + ecmsParam.uri);
      CONSOLE(F("Connecting..."));
      ecms_secureClient.setInsecure(); // unfortunately necessary, ESP8266 does not support SSL without hard coding certificates
      if (!ecms_secureClient.connect(ecmsParam.server, 443)){
        CONSOLE(F("secureClient.connect failed... ")); CONSOLELN(ecmsParam.server);
        return false;
      }
      CONSOLE(F("secureClient connected... "));
      ecms_http.begin(ecms_secureClient, (String)ecmsParam.server, (int)ecmsParam.Port, (String)ecmsParam.uri, true);
      CONSOLE(F("http.begin connected... "));

    } else {
#endif
      // Insecure, no SSL. Need to do the POST way so we can accomodate a different port.
      CONSOLE(F("EMONCMS using http: ")); CONSOLELN((String)ecmsParam.server + ":" + String(ecmsParam.Port) + ecmsParam.uri);
      CONSOLE(F("Connecting..."));
      ecms_http.begin(ecms_client, (String)ecmsParam.server, (int)ecmsParam.Port, (String)ecmsParam.uri);
      CONSOLE(F("http.begin connected... "));
#ifdef ESCURE_ENABLED 
    }
#endif

    ecms_http.addHeader(F("User-Agent"), F("PwrGenieV1"));
    ecms_http.addHeader(F("Connection"), F("close"));
    ecms_http.addHeader(F("Content-Type"), F("application/x-www-form-urlencoded"));
    
    // The POST data msg looks like "node=<channel>&data={"key1:value1","key2:value2","key3:value3"}&apikey=<apikey>"
    // Add the psuVolts to the data string
    String psuV;
    if (strJsonData.length() != 0) psuV =",";
    psuV += "\"psuVolts:" + String(psuVolts,2) + "\"";
    
    String msg;
    msg =  "node="    + (String)ecmsParam.node;
    msg += "&data="   + (String)"{" + strJsonData + psuV + (String)"}";
    msg += "&apikey=" + (String)ecmsParam.apikey;

    psuV.~String();

    //CONSOLELN(msg);
    CONSOLE(F("calling http.POST()... "));
    int httpCode;
    httpCode = ecms_http.POST(msg);    //Make the call.

    // httpCode will be 200 or 202 on success
    CONSOLE(String("EMONCMS Result: ") + httpCode + String(", "));
    ecms_LastResult = "Last EMONCMS: " + String(httpCode) + ", ";
    if (httpCode == 200 || httpCode == 202){
      CONSOLELN(ecms_http.getString());
      ecms_LastResult += ecms_http.getString();
    } else {
      CONSOLELN(ecms_http.getString());
      CONSOLELN(ecms_http.errorToString(httpCode));
      CONSOLELN(String("EMONCMS POST data: ") + msg);
      ecms_LastResult += ecms_http.getString() + ", " + ecms_http.errorToString(httpCode) + ", JSON: " + msg;
    }
    ecms_http.end();
#ifdef SECURE_ENABLED
    if (useHttps) ecms_secureClient.stop();
#endif
    delay(100);
    return true;
  }

#endif


And the Ecms_Struct.h include:
C++:
#ifndef ECMS_STRUCT_H
   #define ECMS_STRUCT_H

   #define EMONCMS_ANDYJBM_APIKEY  "AA48de47c022-blahblahblah-secretcode"

   //These are defaults for parameters that can be changed in the Device Setup page in WmManager
   #define EMONCMS_FACTORY_NODE "99"
   #define EMONCMS_DEFAULT_URI     "/emoncms/input/post"
   #define EMONCMS_DEFAULT_URL     "my-emoncms-server.co.uk"
   #define EMONCMS_DEFAULT_APIKEY EMONCMS_ANDYJBM_APIKEY
   #include "defs.h"

   // Emoncms Default Reset Parameters
   struct emoncmsParams {
      int Port                = 443;
      char uri[URISIZE]       = EMONCMS_DEFAULT_URI;
      char server[URLSIZE]    = EMONCMS_DEFAULT_URL;
      char node[NODESIZE]     = EMONCMS_FACTORY_NODE;
      char apikey[APIKEYSIZE] = EMONCMS_DEFAULT_APIKEY;
   };
#endif


The magic happens in:
C++:
bool emoncms::send2emoncms(emoncmsParams ecmsParam, const char * const ecmsDataNames[], float * ecmsResults, int arraySize){}

Where ecmsDataNames[] contains an array of the names of the data eg cellV1,cellV2,cellV3 etc and ecmsResults[] contains a float array of the values.

emoncmsParams contains parameters like the server address, port, apikey and node.


Thanks!

Andy.
 
Hi @mrconstantin84,

Forgot to say, I haven't got SSL to work on an ESP8266 because there's not enough memory so don't define
SECURE_ENABLED and it will compile for http instead of https.

I understand that this may take up a lot of time to add. I'm happy to put the work in if you'd like me to help compile & debug with you.

Thanks,

Andy.
 
@AndiusPandius
As a workaround you could use an MQTT broker and have JkBMSCan firmware publish the values and subscribe to it in emoncms.
(I did not test yet what exactly is being published via MQTT)
 
@Sven77PV Yeah, that thought has occurred to me also.

Emoncms is capable of mqtt but in the past I've never got it to work. I've recently had a server refactor and moved all the service components into docker containers so now might be the time to have another go at mqtt.

Now I've got an app key I can have a play with @mrconstantin84's handiwork! I need to get the ESP32 hooked up to the JKBMS and get that working and then have a look at MQTT. If his code pushes out all the cell volts then maybe that's the solution.

My immediate term objective is to use the BMS to graph individual cell discharge on a complete charge/discharge cycle test just to determine how balanced the capacities of all these cells are.

It's gonna take me a day or two to get all that together.

A.
 
Code:
      CONSOLE(F("http.begin connected... "));
#ifdef ESCURE_ENABLED
    }
#endif

Spot the deliberate mistake... Well that explains a lot. :rolleyes: How come I only just noticed that now? At least I noticed b4 any one commented!

Possibly explains why SSL never worked at all!

For those that are not coders it should be "SECURE_ENABLED" not ESCURE, whatever coolaid I'd been drinking when I typed that.

A.
 
Let me undestand ur situation.

ur bms stop working (cut power) after 10 minutes after u power up because dont communicate with invertor?

i think u need to simulate the invertor, and send the announcement regs to battery, just try to send 04200 to the battery
Thanks, I will try that.
 
Let me undestand ur situation.

ur bms stop working (cut power) after 10 minutes after u power up because dont communicate with invertor?

i think u need to simulate the invertor, and send the announcement regs to battery, just try to send 04200 to the battery
Thanks, I will try that.
 
I already have a framework I built for data collection/translation originally based on tzapu WifiManager but now taken from khoih-prog ESPAsync_WifiManager using ASYNCWebServer. I took the best bits from both, thinned out what I didn't need, improved setup/config parameters and fixed it to compile for both ESP32-S2/C3 and ESP8266.
As you do not seem to have noticed my private message yet, I'll repeat my question here (although off-topic):

I would be interested in your framework - do you publish the source on Github?
And is there any reason you prefer the Async over the normal/original WifiManager?
 
@Sven77PV, Sorry, missed the PM. WIll take a look.

No source is not on github (yet) purely because it has secret passwords in that I need to strip out. This could be the motivation I need!

I'll have a look maybe Thursday (on site tomorrow) and see if I can get the whole thing uploaded. Warning ZERO documentation at present!

So I initially was using WmManager on ESP8266 but i needed it to work on ESP32-C3 as well.

Loooong story the goal: one framework for ESP8266, ESP32-C3 to be able to take data from various sources to push to emoncms. (Also to act as a gateway between lora devices to emoncms but that still a dream....) The sync version was timing out missing data and randomly rebooting (some heap issue I think) and in the process I came across the ASync version. I worked on the two side by side combining the best of each for a bit - sync version on 8266 and ASync on ESP32 and the 1st I got to work on both platforms was the ASync version.

And yes, ASync is MUCH more responsive - noticable on esp8266.

So now one platformio project which compiles for ESP8266, ESP32-S3 and now I can add ESP32 devkit to the list!
 
@Sven77PV
As a workaround you could use an MQTT broker
Had a look at mqtt in emoncms and its not a complete implementation - so I'll need some other mqtt to http relay to get it to work...

This is my 1st mqtt ride believe it or not...

A.
 
Let me undestand ur situation.

ur bms stop working (cut power) after 10 minutes after u power up because dont communicate with invertor?

i think u need to simulate the invertor, and send the announcement regs to battery, just try to send 04200 to th
Let me undestand ur situation.

ur bms stop working (cut power) after 10 minutes after u power up because dont communicate with invertor?

i think u need to simulate the invertor, and send the announcement regs to battery, just try to send 04200 to the battery
MRCONSTANTIN84 YOU ARE THE MAN! Yes I'm shouting it for all to hear. I'm slamming the battery with zero's to Canbus ID 0x4200 like you said
and vaboom! damn thing stays on. My $800 investment for a 7.5kWh server rack battery did not go in vain. Now it's time to hit ebay, people
selling these 2.5 kWh Sonnen modules for $300 brand new in the box.

My silly Python progam that works:
import RPi.GPIO as GPIO
import can
import time
import os

led = 22
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led,GPIO.OUT)
GPIo_Output(led,True)

print('\n\rCAN Rx test')
print('Bring up CAN0....')

# Bring up can0 interface at 500kbps
os.system('sudo /sbin/ip link set can0 up type can bitrate 500000')
time.sleep(0.2)
print('Press CTL-C to exit')

try:
bus = can.interface.Bus(channel='can0', bustype='socketcan')
except OSError:
print('Cannot find PiCAN board.')
GPIo_Output(led,False)
exit()

# Main loop
try:
while True:
GPIo_Output(led,True)
msg = can.Message(arbitration_id=0x4200,data=[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],is_extended_id=True)
bus.send(msg)
time.sleep(.5)
message = bus.recv()
print(message)
time.sleep(.4)
GPIo_Output(led,False)
time.sleep(.1)

except KeyboardInterrupt:
#Catch keyboard interrupt
GPIo_Output(led,False)
os.system('sudo /sbin/ip link set can0 down')
print('\n\rKeyboard interrtupt')
 

Attachments

  • sonnen.jpg
    sonnen.jpg
    378.9 KB · Views: 364
  • pi.jpg
    pi.jpg
    465.6 KB · Views: 312
Back
Top