Daly BMS mit ESP32 Wroom Modul und Arduino IDE

Versuche das Daly BMS mit ESP32 und Arduino IDE auszulesen.

Zur RX/TX Verbindung habe ich einen Adum-1201 dazwischen geschaltet.
Bekomme bereits eine Antwort die aber leer ist.
Mein Sketsch:


[details="Zusammenfassung"]
Dieser Text wird ausgeblendet
[/details]

#define RX_PIN 16 // Ersetze 16 durch den tatsächlichen RX-Pin des ESP32
#define TX_PIN 17 // Ersetze 17 durch den tatsächlichen TX-Pin des ESP32
#include <HardwareSerial.h>

HardwareSerial mySerial(1); // UART1 verwenden

void setup() {
    Serial.begin(115200); // Debugging
    mySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Daly BMS UART
    Serial.println("Setup abgeschlossen");
}


//byte request[] = {0xA5, 0x80, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E}; // 0x1E = Prüfsumme
//mySerial.write(request, sizeof(request)); // Anfrage senden

// Prüfsumme berechnen
byte calculateChecksum(byte* data, int length) {
    int sum = 0;
    for (int i = 0; i < length - 1; i++) { // Prüfsumme selbst nicht einschließen
        sum += data[i];
    }
    return sum & 0xFF; // Reduktion auf ein Byte
}



void loop() {
    byte request[] = {0xA5, 0x80, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    request[12] = calculateChecksum(request, sizeof(request)); // Prüfsumme hinzufügen

    Serial.println("Anfrage wird gesendet:");
    for (int i = 0; i < sizeof(request); i++) {
        Serial.print(request[i], HEX);
        Serial.print(" ");
    }
    Serial.println();

    // Sende die Anfrage
    mySerial.write(request, sizeof(request));

    delay(2000); // Warte auf eine Antwort
}

Kann mir jemand noch in eine Richtung geben um den SOC, VOLT..... vollenz zu lesen?

Hier ist nirgendwo was drin, wo Du irgendwas ausliest.
Wie bekommst Du denn eine Antwort?

Habe im Serielen Monitor immer A5 80 91 08 0 0 0 0 0 0 0 0 ED
bekommen. Hab natürlich keine Ahnung was das ist.

Gib doch mal den Sketch, mit dem Du auch was raus bekommst.
Ich würde erstmal sehen wollen, wie Du das zusammengebaut hast, damit man eine Grundlage hat.

  1. Das ist das, was Du sendest. Eine Antwort wird in Deinem Programm nicht gelesen.
  2. ESP32 hat Serial2 (RX2=GPIO16; TX2=GPIO17) vorkonfiguriert, mySerial braucht es daher nicht.

Ok jetzt hat mein Programm nichts wo was empfängt?
Glaub ich hab mal wieder richtig in die Scheiße gegriffen.
Danke das ich jetzt auch weiß das da noch was fehlt.

Ich war jetzt auch grad am suchen, wo und wie ich was lesen könnte.

Vielleicht so?


void setup()
{
  Serial.begin(115200); // Debugging
  Serial2.begin(9600); // Daly BMS UART
  Serial.println("Setup abgeschlossen");
}


//byte request[] = {0xA5, 0x80, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E}; // 0x1E = Prüfsumme
//mySerial.write(request, sizeof(request)); // Anfrage senden

// Prüfsumme berechnen
byte calculateChecksum(byte *data, int length)
{
  int sum = 0;
  for (int i = 0; i < length - 1; i++)   // Prüfsumme selbst nicht einschließen
  {
    sum += data[i];
  }
  return sum & 0xFF; // Reduktion auf ein Byte
}

bool antwort = false;

void loop()
{
  byte request[] = {0xA5, 0x80, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  request[12] = calculateChecksum(request, sizeof(request)); // Prüfsumme hinzufügen
  if (!antwort)
  {
    Serial.println(F("Anfrage wird gesendet:"));
    for (int i = 0; i < sizeof(request); i++)
    {
      Serial.print(request[i], HEX);
      Serial2.print(' ');
    }
    Serial.println();
    // Sende die Anfrage
    Serial2.write(request, sizeof(request));
    antwort = true;
  }
  else
  {
    Serial.println(F("Warte auf Antwort"));
    while (Serial2.available())
    {
      Serial.print(Serial2.read(), HEX);
      Serial.print(' ');
      antwort = false;
    }
    delay(2000); // Warte auf eine Antwort
  }
}

So nach dem ich mir gesagt wurde das da was wichtiges fehlt! :face_with_spiral_eyes:
Habe ich wieder mal versucht was zu machen.
Mei neuer Sketsch:


#define RX_PIN 16 // Ersetze 16 durch den tatsächlichen RX-Pin des ESP32
#define TX_PIN 17 // Ersetze 17 durch den tatsächlichen TX-Pin des ESP32
#include <HardwareSerial.h>

HardwareSerial mySerial(1); // UART1 verwenden

void setup() {
    Serial.begin(115200); // Debugging
    mySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Daly BMS UART
    Serial.println("Setup abgeschlossen");
}


//byte request[] = {0xA5, 0x80, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E}; // 0x1E = Prüfsumme
//mySerial.write(request, sizeof(request)); // Anfrage senden

// Prüfsumme berechnen
byte calculateChecksum(byte* data, int length) {
    int sum = 0;
    for (int i = 0; i < length - 1; i++) { // Prüfsumme selbst nicht einschließen
        sum += data[i];
    }
    return sum & 0xFF; // Reduktion auf ein Byte
}

void loop() {
    byte request[] = {0xA5, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E};
    request[12] = calculateChecksum(request, sizeof(request)); // Prüfsumme hinzufügen

    Serial.println("Anfrage wird gesendet:");
    for (int i = 0; i < sizeof(request); i++) {
        Serial.print(request[i], HEX);
        Serial.print(" ");
    }
    Serial.println();

    // Anfrage senden
    mySerial.write(request, sizeof(request));

    // Warte auf Antwort
    delay(2000);

    // Prüfen, ob Daten verfügbar sind
    if (mySerial.available()) {
        Serial.println("Antwort empfangen:");
        while (mySerial.available()) {
            // Lese ein Byte
            byte incomingByte = mySerial.read();
            Serial.print(incomingByte, HEX);
            Serial.print(" ");
        }
        Serial.println();
    } else {
        Serial.println("Keine Antwort empfangen.");
    }

    // Zeit für den nächsten Loop
    delay(5000);
}

O Wunder o wunder der Serielle Monitor gibt folgendes aus:

Anfrage wird gesendet:
A5 40 90 8 0 0 0 0 0 0 0 0 7D

Antwort empfangen:
A5 1 90 8 1 C 0 0 75 52 3 A3 B8

Wobei sich die Werte ab den 2 Nullen immer wieder ändern.
Gibt es dafür einen Übersetzer?

Und danke für den Tip von euch hätte da noch sehr viel Zeit verbraten :heart_eyes:

A

Das Datenblatt zum Kommunikationsprotokoll?

Die Anfrage mußt Du irgendwo her haben, da steht dann auch, was in der Antwort zu erwarten ist.

BMS = Batteriemanagementsystem

Von der Firma gibt es verschiedene, auch mit "aktivem Gleichgewichtsmodul". Welches Du verwendest, weißt derzeit nur Du :wink:

...ist eine Eigenschaft Deines Sketches und zwar verbrätst Du zwei Sekunden nach dem Senden der Anfrage und nochmal fünf nach dem Lesen der Antwort.

Implizit erwartest Du mehrere Sachen von der Antwort:

  • kommt innerhalb der zwei Sekunden
  • ist vollständig
  • passt komplett in den Empfangspuffer der Library für die serielle Schnittstelle

Wenn das so zu dem BMS passt... schweige ich stille.

Eigentlich schade: Rund gerechnet 2x13x1.2ms=31ms werden für die Übertragungen benötigt und 7000ms fürs Nichtstun - das ist nicht mal ein halbes Prozent nützlicher Arbeit für den ESP.
:slight_smile:

Da nicht sichergestellt ist, dass der Empfangspuffer im ersten Byte den Startcode hat, kann ich das schonmal mit Bestimmtheit in Frage stellen :slight_smile:

Hallo Leute nach langem suchen, habe ich folgendes Gefunden für das DalyBms.

2.3 Uart Communication Format
2.3.1 PC send

Start Flag = 0xA5(Fixed)
Denk das ist der Anfang der Communication. 0xA5

PC address = 0x40
Address assignment
Module Address
BMS master 0x01
Bluetooth APP 0x80
GPRS 0x20
Upper computer 0x40
Das wird die Addresse für PC sein 0x40

Data ID
Refer to Section3 = 0x90
SOC of total voltage current 0x90
Maximum & Minimum voltage 0x91
Maximum& Minimum temperature 0x92
usw.
Wenn SOC gelesen werden soll 0x90

Data length
8 Bytes(fixed) 0x08
muß auf 8 stehen für die länge?

Data Content?????
weis nix :face_with_spiral_eyes:

Checksum(1Byte)
Ende des Satzes???

Könnte es so sein?

0xA5, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E
Stehen für die Anfrage das ich den SOC Wert abfragen kann?

Oder ist daß wieder völliger unsinn?

Nö.

Man könnte es auch verlinken (PDF).

Schön das du das kannst :+1:
Bin leider zu doof dazu :sob:

Danke das ihr mir so gut geholfen habt :heart_eyes: :+1: :heart_eyes:

wenn du jetzt das Protokoll gefunden hast (bzw. das PDF von @wno158 , sollte es ja ziemlich übersichtlich werden, an die einzelnen Daten zu kommen.
Oder brauchst du jetzt noch zu einem Punkt Hilfe?

Die Antwort A5 01 90 08 01 0C 00 00 75 52 3 A3 B8 würde ich so verstehen:

hex dez Bedeutung und Einheit Wert Einheit
0x010c 268 pressure (0.1 V) 26,8 V
0x0000 0 acquisition (0.1 V) 0 V
0x7552 30034 current (0.1A Offset 30000) 3,4 A
0x03a3 931 SOC(0.1%) 93,1 %

Ohne Gewähr :slightly_smiling_face:

Wäre das sinnvoll?

Hallo hab mal wieder weiter gebastelt.

#define RX_PIN 16 // Ersetze 16 durch den tatsächlichen RX-Pin des ESP32
#define TX_PIN 17 // Ersetze 17 durch den tatsächlichen TX-Pin des ESP32
#include <HardwareSerial.h>

HardwareSerial mySerial(1); // UART1 verwenden

void setup() {
    Serial.begin(115200); // Debugging
    mySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Daly BMS UART
    Serial.println("Setup abgeschlossen");
}

// Prüfsumme berechnen
byte calculateChecksum(byte* data, int length) {
    int sum = 0;
    for (int i = 0; i < length - 1; i++) { // Prüfsumme selbst nicht einschließen
        sum += data[i];
    }
    return sum & 0xFF; // Reduktion auf ein Byte
}


bool validateChecksum(byte* data, int length) {
    byte checksum = calculateChecksum(data, length - 1);
    return (checksum == data[length - 1]);
}

void loop() {
    byte request[] = {0xA5, 0x40, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    request[12] = calculateChecksum(request, sizeof(request)); // Prüfsumme hinzufügen

    mySerial.write(request, sizeof(request)); // Anfrage senden

  unsigned long bufferFlushStart = millis();
while (mySerial.available() && millis() - bufferFlushStart < 50) {
    mySerial.read();
}


   unsigned long waitStart = millis();
while (!mySerial.available() && millis() - waitStart < 500) {
    // Warte auf Daten oder Timeout nach 200 ms
}
 

    byte response[13]; // Globale Deklaration innerhalb von loop()
    int index = 0;     // Initialisierung

    unsigned long startTime = millis();
    while ((millis() - startTime < 1000) && index < sizeof(response)) {
        if (mySerial.available()) {
            response[index++] = mySerial.read(); // Antwort lesen
        }
    }

    if (index < sizeof(response)) {
        Serial.println("Unvollständige Antwort erhalten.");
        return;
    }

    if (response[0] != 0xA5) {
        Serial.println("Ungültige Antwort: Header fehlt.");
        return;
    }

    Serial.println("Empfangene Antwort:");
    for (int i = 0; i < index; i++) {
        Serial.print("Byte ");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(response[i], HEX);
    }

    int totalVoltageRaw = (response[9] << 8) | response[10];
    float totalVoltage = totalVoltageRaw * 0.1; // Spannung in Volt umrechnen
    Serial.print("Kumulative Gesamtspannung: ");
    Serial.println(totalVoltage, 2);

    delay(5000); // Zeit für den nächsten Loop
} 

Hab nu folgendes Problem:
bekomme kein zuverlässiges Volt vom BMS raus.
Wenn V stimmt und ich Last aufschalte stimmt meine Anzeige nicht mehr zu meinem Voltmeter.
Hat jemand eine Idee dazu?