Teilnehmermodus Protokoll Spezifikation v1.4 - BMS CAN LIN Kommunikation

⚠️ Wichtige Versionsanforderungen

Damit dieser Modus über die App erfolgreich aktiviert werden kann, muss mindestens die App Version v1.60 und mindestens die BMS Version 1.0.7 installiert sein. Falls eine ältere Version installiert ist, schauen Sie bitte auf ältere Versionen dieser Dokumentation.

→ Zur Version 1.3 der Dokumentation

Überblick - BMS Kommunikationsprotokoll für Entwickler

Das Teilnehmermodus Protokoll ist ein standardisiertes BMS Kommunikationsprotokoll für die Kommunikation mit SaftkistePRO Batteriemanagementsystemen mit Unterstützung für CAN-Bus und LIN-Bus Schnittstellen. Die SaftkistePRO kann als passiver Teilnehmer in bestehende Bus-Netzwerke integriert werden und ihre Batteriedaten über das Protokoll an andere Systeme im Fahrzeug senden. Diese Funktion ermöglicht es, Ladezustand, Spannung, Strom und weitere wichtige Batterieparameter direkt an Bordcomputer, Anzeigegeräte oder andere Komponenten zu übertragen, ohne dass zusätzliche Verkabelung erforderlich ist. Diese technische Spezifikation definiert die Nachrichtenstruktur, Signaldefinitionen und Implementierungsanforderungen für Entwickler, die Teilnehmermodus-kompatible BMS-Geräte integrieren möchten.

Downloads

Protokoll-Dateien für Entwickler:

Anschluss und Aktivierung

CAN

Die Pins für CAN-High und CAN-Low sind an den Pins 6 bzw. 16 der SaftkistePRO anzuschließen:

SaftkistePRO CAN-Bus Anschluss Pin 6 und 16 Teilnehmermodus

Aktivierung über App > "Netzwerk" > "CAN Teilnehmermodus" > "Hinzufügen".

LIN

Der LIN-Bus ist an Pin 8 der SaftkistePRO anzuschließen:

SaftkistePRO LIN-Bus Anschluss Pin 8 Teilnehmermodus

Aktivierung über App > "Netzwerk" > "LIN Teilnehmermodus" > "Hinzufügen".

BMS Protokoll Features - CAN und LIN Bus

  • Dual-Bus-Unterstützung: CAN 2.0B und LIN 2.1
  • Umfassende BMS-Daten: Batteriestatus, Zellspannungen, Schutzfunktionen und Diagnose
  • Standardisiertes Nachrichtenformat: Konsistent über alle Teilnehmermodus-Geräte
  • Echtzeit-Überwachung: Kritische Daten mit 100ms Aktualisierungsraten
  • Fehlererkennung: Integrierte Fehlerberichterstattung und Schutzmechanismen

CAN LIN Nachrichten-Übersicht - BMS Datenstruktur

Nachricht CAN ID LIN ID Länge CAN Länge LIN Update-Rate Beschreibung
States 0x770 0x10 8 Bytes 8 Bytes 100ms Alle Boolean-Status-Flags + Temperatur
Parameters 0x771 0x11 8 Bytes 4 Bytes 1000ms Software-/Hardware-Versionen
Serial_Number_1 0x772 0x12 8 Bytes 8 Bytes 5000ms Geräte-Seriennummer (Teil 1)
Serial_Number_2 0x773 0x13 8 Bytes 8 Bytes 5000ms Geräte-Seriennummer (Teil 2)
General_Readings 0x774 0x14 8 Bytes 8 Bytes 100ms Spannung, Strom
Cell_Voltages 0x775 0x15 8 Bytes 8 Bytes 100ms Einzelne Zellspannungen
Capacity 0x776 0x16 8 Bytes 7 Bytes 1000ms SOC, SOH, Kapazitätsdaten
Cumulativ_Ah 0x777 0x17 8 Bytes 8 Bytes 1000ms Kumulierte Lade-/Entladung
Uptime 0x778 0x18 8 Bytes 4 Bytes 10000ms System-Laufzeitzähler
Time_To_Go 0x779 0x19 8 Bytes 8 Bytes 1000ms Geschätzte Restlaufzeit und Zeit bis Vollladung

Frame-Längen unterscheiden sich je Bus. Auf CAN sind alle Nachrichten 8 Byte lang, nicht belegte Bytes werden mit 0x00 gesendet. Auf LIN entspricht die Länge exakt den belegten Bytes, wie im LDF definiert: Parameters hat dort 4 Byte, Capacity 7 Byte und Uptime 4 Byte. Die Byte-Layouts in den folgenden Abschnitten beschreiben jeweils den CAN-Frame; die als reserviert markierten Bytes am Ende entfallen auf LIN.

Nachrichten-Definitionen

States (0x770 / 0x10)

Zweck: Konsolidierte Boolean-Status-Flags für alle BMS-Zustände, Schutzfunktionen, Fehler und Temperatur.

Bit-Layout:

Byte Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 Any_Fault_Active Any_Protection_Active Force_Off_Pin_State User_Main_Switch_State Is_Heating Is_Balancing Is_Discharging Is_Charging
1 High_Current_Charge_Prot High_Cell_Voltage_Prot Low_Cell_Voltage_Prot Pre_Warning_Charge_Shutdown Pre_Warning_Discharge_Shutdown Low_SoC Allowed_To_Discharge Allowed_To_Charge
2 Temperature_Fault Voltage_Fault Switch_Fault Low_Temperature_Discharge_Prot Low_Temperature_Charge_Prot High_Temperature_Discharge_Prot High_Temperature_Charge_Prot High_Current_Discharge_Prot
3 Reserviert Reserviert Reserviert Reserviert Critical_Alert Switch_Forced_Off Shunt_Delta_Fault Voltage_Delta_Fault
4-5 Temperature (16-bit signed, little-endian)
6-7 Reserviert (0x00)

Signal-Definitionen:

Die Spalte Bit ist der Bit-Index über den gesamten Frame, so wie ihn die .dbc und die .ldf verwenden. Die Spalte Byte.Bit nennt dieselbe Position als Byte und Bit innerhalb des Bytes, passend zur Tabelle oben.

Bit Byte.Bit Signal Bedeutung
0 0.0 Is_Charging Es fließt Ladestrom in die Batterie. Das Bit wird direkt aus dem Momentanstrom abgeleitet und hat kein Totband, bei Strömen nahe 0 A kann es daher wechseln.
1 0.1 Is_Discharging Es fließt Entladestrom aus der Batterie. Gleiche Einschränkung wie bei Is_Charging.
2 0.2 Is_Balancing Der Zellausgleich läuft, mindestens eine Zelle wird gerade abgeglichen. Normaler Betriebszustand, überwiegend gegen Ende der Ladung, und kein Fehler.
3 0.3 Is_Heating Die Zellheizung ist eingeschaltet. Nur bei Modellen mit Heizung, sonst dauerhaft 0.
4 0.4 User_Main_Switch_State Stellung des Hauptschalters, so wie ihn der Nutzer gesetzt hat, per App oder Taster. 1 = eingeschaltet. Das Bit sagt nur, was gewünscht ist. Ob tatsächlich Strom fließen kann, steht in Allowed_To_Charge und Allowed_To_Discharge.
5 0.5 Force_Off_Pin_State Zustand des Force-Off-Eingangs. 0 = Normal, 1 = Forced_Off.
6 0.6 Any_Protection_Active Beliebiger Schutzmechanismus ist ausgelöst. Sammelmeldung.
7 0.7 Any_Fault_Active Beliebige Fehlerbedingung liegt vor. Sammelmeldung.
8 1.0 Allowed_To_Charge Der Ladepfad ist durchgeschaltet, die Batterie kann Strom aufnehmen. 0 bedeutet, dass gerade nicht geladen werden kann, etwa wegen Zellüberspannung oder zu niedriger Temperatur.
9 1.1 Allowed_To_Discharge Der Entladepfad ist durchgeschaltet, die Batterie kann Verbraucher versorgen. 0 bedeutet, dass gerade kein Strom entnommen werden kann.
10 1.2 Low_SoC Der Ladezustand liegt unter 20%. Feste Schwelle, unabhängig von einer in der App eingestellten Entladeschutz-Grenze. Gedacht als Anzeige- und Hinweisschwelle, nicht als Abschaltwarnung.
11 1.3 Pre_Warning_Discharge_Shutdown Der Ladezustand liegt unter 1% und es wird nicht nennenswert geladen. Die Abschaltung wegen Entladung steht unmittelbar bevor, dies ist keine Vorwarnung mit mehreren Minuten Vorlauf. Solange geladen wird, bleibt das Bit 0.
12 1.4 Pre_Warning_Charge_Shutdown Die Batterie ist in weniger als einer Minute voll, die Ladung endet also gleich regulär. Trotz des Namens keine Fehler- oder Schutzmeldung.
13 1.5 Low_Cell_Voltage_Prot Mindestens eine Zelle hat die untere Spannungsgrenze erreicht. Entladen ist gesperrt, bis sich die Zelle erholt oder geladen wird.
14 1.6 High_Cell_Voltage_Prot Mindestens eine Zelle hat die obere Spannungsgrenze erreicht. Laden ist gesperrt.
15 1.7 High_Current_Charge_Prot Überstrom oder Kurzschluss im Ladepfad erkannt. Laden ist gesperrt.
16 2.0 High_Current_Discharge_Prot Überstrom oder Kurzschluss im Entladepfad erkannt. Entladen ist gesperrt. Typisch bei einem defekten Verbraucher oder einem Kurzschluss in der Bordnetzverkabelung.
17 2.1 High_Temperature_Charge_Prot Zu warm zum Laden. Laden ist gesperrt, Entladen bleibt möglich.
18 2.2 High_Temperature_Discharge_Prot Zu warm zum Entladen. Entladen ist gesperrt.
19 2.3 Low_Temperature_Charge_Prot Zu kalt zum Laden. Laden ist gesperrt. Bei Modellen mit Heizung ist das der Zustand, in dem üblicherweise Is_Heating anläuft; die Ladung wird wieder freigegeben, sobald die Zellen warm genug sind.
20 2.4 Low_Temperature_Discharge_Prot Zu kalt zum Entladen. Entladen ist gesperrt. Diese Grenze liegt deutlich tiefer als die zum Laden, im Winter tritt daher meist nur Low_Temperature_Charge_Prot auf.
21 2.5 Switch_Fault Es fließt weiterhin Strom, obwohl der Hauptschalter ausgeschaltet ist. Deutet auf durchlegierte Leistungsschalter hin und ist ein Wartungsfall.
22 2.6 Voltage_Fault Die Gesamtspannung des Zellstapels liegt über dem zulässigen Wert und bleibt dort. Vorwarnstufe, siehe Hinweis unter der Tabelle.
23 2.7 Temperature_Fault Die gemessene Temperatur liegt über dem zulässigen Wert und bleibt dort. Anders als bei High_Temperature_Charge_Prot und High_Temperature_Discharge_Prot geht es hier nicht um das Sperren eines einzelnen Pfades, sondern um eine drohende Sicherheitsabschaltung der ganzen Batterie.
24 3.0 Voltage_Delta_Fault Die Spannungen der vier Zellen laufen zu weit auseinander. Hinweis auf eine schwächelnde Zelle oder einen Übergangswiderstand an einem Zellverbinder.
25 3.1 Shunt_Delta_Fault Die beiden Strommessungen der Batterie weichen zu stark voneinander ab. Solange das Bit steht, sind Strom, Ladezustand und Restlaufzeit weniger genau.
26 3.2 Switch_Forced_Off Die Batterie hat sich wegen einer anhaltenden Sicherheitsverletzung selbst abgeschaltet. Im Unterschied zu Switch_Fault meldet dieses Bit den Zustand, nicht den Defekt.
27 3.3 Critical_Alert Kritischer Systemfehler erfordert sofortige Aufmerksamkeit.
32-47 4.0-5.7 Temperature Batterietemperatur in 0.01°C (16-bit signed, Bereich: -327.68°C bis 327.67°C). Übertragen wird der arithmetische Mittelwert der vier Zelltemperatursensoren, nicht der wärmste Einzelsensor. Für eine Übertemperatur-Überwachung im Fahrzeug sind daher die Flags Temperature_Fault, High_Temperature_Charge_Prot und High_Temperature_Discharge_Prot maßgeblich, nicht dieser Messwert.

Die acht *_Prot-Flags sind kein Defekt. Sie melden, dass ein Pfad im Moment gesperrt ist, weil eine Betriebsgrenze erreicht wurde. Eine Batterie, die im Winter Low_Temperature_Charge_Prot meldet oder am Ende der Ladung High_Cell_Voltage_Prot, arbeitet bestimmungsgemäß. Für eine Anzeige im Fahrzeug eignen sie sich als Erklärung dafür, warum gerade nicht geladen oder entladen wird, nicht als Störungsmeldung.

Die fünf *_Fault-Flags sind Vorwarnungen. Switch_Fault, Voltage_Fault, Temperature_Fault, Voltage_Delta_Fault und Shunt_Delta_Fault werden gesetzt, sobald eine Sicherheitsbedingung etwa ein Drittel der jeweils zulässigen Toleranzzeit lang verletzt ist. Verschwindet die Ursache vorher, verschwinden auch die Bits, ohne dass die Batterie abschaltet. Hält die Verletzung über die volle Toleranzzeit an, schaltet die Batterie ab und meldet das über Switch_Forced_Off (Bit 26). Für ein Anzeigegerät sind diese fünf Bits also der richtige Zeitpunkt für einen Hinweis an den Nutzer, nicht erst die Abschaltung selbst.

Parameters (0x771 / 0x11)

Zweck: Software- und Hardware-Versionsinformationen.

Byte-Layout:

Byte Feld Typ Bereich
0 Software_Version_Major 8-bit unsigned 0-255
1 Software_Version_Minor 8-bit unsigned 0-255
2 Software_Version_Patch 8-bit unsigned 0-255
3 Hardware_Version 8-bit unsigned 0-255
4-7 Reserviert (nur CAN, 0x00) - -

Auf LIN ist der Frame 4 Byte lang und endet nach Hardware_Version. Auf CAN werden die Bytes 4 bis 7 als 0x00 aufgefüllt.

Serial_Number_1 & Serial_Number_2 (0x772-0x773 / 0x12-0x13)

Zweck: 16-stellige ASCII-Seriennummer-Identifikation.

Format: ASCII-Zeichen, null-terminiert wenn kürzer als 16 Zeichen.

General_Readings (0x774 / 0x14)

Zweck: Primäre Batteriemessungen.

Byte-Layout:

Bytes Feld Typ Einheit
0-3 Voltage 32-bit unsigned, little-endian mV
4-7 Current 32-bit signed, little-endian mA

Berechnungen:

  • Spannung: Rohwert * 1 mV
  • Strom: Rohwert * 1 mA (negativ = Entladung, positiv = Ladung)

Cell_Voltages (0x775 / 0x15)

Zweck: Überwachung einzelner Zellspannungen. Übertragen werden die vier physischen Zellen in Reihenfolge der Reihenschaltung. Die Differenz zwischen der höchsten und der niedrigsten Zellspannung ist das aussagekräftigste Maß für den Zustand des Zellverbunds; läuft sie dauerhaft auseinander, meldet die Batterie Voltage_Delta_Fault.

Byte-Layout:

Bytes Feld Typ Einheit
0-1 Cell1_Voltage 16-bit unsigned, little-endian mV
2-3 Cell2_Voltage 16-bit unsigned, little-endian mV
4-5 Cell3_Voltage 16-bit unsigned, little-endian mV
6-7 Cell4_Voltage 16-bit unsigned, little-endian mV

Capacity (0x776 / 0x16)

Zweck: Batteriekapazität und Zustandsinformationen.

Byte-Layout:

Bytes Feld Typ Einheit
0-1 State_Of_Charge 16-bit unsigned, little-endian 0,01%
2-3 State_Of_Health 16-bit unsigned, little-endian 0,01%
4-5 Dischargeable_Capacity 16-bit unsigned, little-endian 0,1Ah
6 Nominal_Capacity 8-bit unsigned 2Ah
7 Reserviert (nur CAN, 0x00) - -

Berechnungen:

  • SOC: Rohwert * 0,01% (Bereich: 0-100%). Bezugsgröße ist die aktuelle Ist-Kapazität der Batterie, nicht die Nennkapazität. 100% SOC bedeutet also vollgeladen, unabhängig von der Alterung.
  • SOH: Rohwert * 0,01% (Bereich: 0-100%)
  • Entladbare Kapazität: Rohwert * 0,1 Ah. Dies ist die gesamte noch entnehmbare Kapazität bis 0% SOC. Eine in der App konfigurierte Entladeschutz-Grenze ist hier nicht berücksichtigt, im Gegensatz zu Time_To_Go. Bei gesetzter Grenze kann Time_To_Go daher 0 erreichen, während Dischargeable_Capacity noch einen Restwert anzeigt.
  • Nennkapazität: Rohwert * 2 Ah. Das 8-bit-Feld sättigt bei 255, der maximal darstellbare Wert ist also 510 Ah. Größere Verbünde melden 510 Ah.

Cumulativ_Ah (0x777 / 0x17)

Zweck: Über die Lebensdauer kumulierter Lade- und Entladedurchsatz. Die Werte werden aus dem Zyklenzähler und dem aktuellen Ladezustand hochgerechnet, es sind also Schätzwerte und keine direkt gemessenen Zähler. Geladene und entladene Ah liegen deshalb konstruktionsbedingt dicht beieinander.

Byte-Layout:

Bytes Feld Typ Einheit
0-3 Cumulativ_Discharged_Ah 32-bit unsigned, little-endian Ah
4-7 Cumulativ_Charged_Ah 32-bit unsigned, little-endian Ah

Uptime (0x778 / 0x18)

Zweck: Laufzeit seit dem letzten Neustart des BMS. Der Zähler beginnt bei jedem Hochlauf wieder bei 0 und ist keine Gesamtbetriebsstundenzahl. Ein Rücksprung auf einen kleinen Wert ist damit das zuverlässigste Signal dafür, dass die Batterie zwischenzeitlich neu gestartet ist, etwa nach einem Firmware-Update oder einem Abschaltvorgang.

Byte-Layout:

Bytes Feld Typ Einheit
0-3 Uptime 32-bit unsigned, little-endian Sekunden
4-7 Reserviert (nur CAN, 0x00) - -

Auf LIN ist der Frame 4 Byte lang und endet nach Uptime. Auf CAN werden die Bytes 4 bis 7 als 0x00 aufgefüllt.

Time_To_Go (0x779 / 0x19)

Zweck: Geschätzte Restlaufzeit und Zeit bis Vollladung.

Beide Werte werden aus einem geglätteten Strommittelwert berechnet, nicht aus dem Momentanstrom aus General_Readings. Nach einem Lastwechsel braucht die Schätzung daher rund 10 Sekunden, bis sie den neuen Wert erreicht. Eine eigene Berechnung aus Current liefert deshalb abweichende Werte.

Time_To_Go rechnet bis zum Abschaltpunkt der Batterie, nicht bis 0% SOC: Ist in der App eine Entladeschutz-Grenze gesetzt, ist das die verbleibende Zeit bis zu dieser Grenze. Ohne gesetzte Grenze ist es die Zeit bis 0% SOC. Time_To_Full rechnet bis zur vollen Ist-Kapazität.

Byte-Layout:

Bytes Feld Typ Einheit
0-3 Time_To_Go 32-bit unsigned, little-endian Minuten
4-7 Time_To_Full 32-bit unsigned, little-endian Minuten

Spezialwerte:

  • Time_To_Go = 4294967295: Nicht anwendbar. Gesendet, solange nicht entladen wird, also bei Ladung und im Ruhezustand unterhalb von 100 mA Entladestrom.
  • Time_To_Full = 4294967295: Nicht anwendbar. Gesendet, solange nicht geladen wird, also bei Entladung und im Ruhezustand unterhalb von 100 mA Ladestrom.

BMS Implementierungsanforderungen - CAN LIN Konfiguration

CAN-Bus-Konfiguration

  • Protokoll: CAN 2.0B Standard Frame
  • Baudrate: 500 kbps (empfohlen)
  • Byte-Reihenfolge: Little Endian
  • Knotenname: "Saftkiste"

LIN-Bus-Konfiguration

  • Protokoll: LIN 2.1
  • Baudrate: 19200 bps
  • NAD: 0x01
  • Produkt-ID: 0x1234, 0x5678

Timing-Anforderungen

  • Kritische Nachrichten (States, General_Readings, Cell_Voltages): ≤ 100ms
  • Status-Nachrichten (Capacity, Parameters): ≤ 1000ms
  • Identifikations-Nachrichten (Serial Numbers, Uptime): ≤ 10000ms

Fehlerbehandlung

  • Überwachung der Any_Fault_Active und Critical_Alert Flags
  • Implementierung von Timeout-Erkennung für fehlende Nachrichten
  • Validierung der Datenbereiche gemäß Signaldefinitionen

BMS Code-Beispiele - CAN LIN Implementierung

CAN-Nachrichten-Parsing (C)

Die Signale werden bewusst über Schiebeoperationen statt über Bitfelder und Pointer-Casts ausgelesen: Die Anordnung von C-Bitfeldern ist nicht standardisiert, und ein Cast auf uint16_t* mitten in den Empfangspuffer setzt eine Ausrichtung voraus, die auf kleinen Cortex-M-Kernen nicht gegeben ist. Der folgende Code ist auf jeder Plattform gültig.

#include <stdint.h>
#include <stdio.h>

#define TM_NOT_APPLICABLE 0xFFFFFFFFu

/* Little-Endian-Zugriffe, ausrichtungsfrei */
static uint16_t tm_u16(const uint8_t *d)
{
    return (uint16_t)((uint16_t)d[0] | ((uint16_t)d[1] << 8));
}

static int16_t tm_i16(const uint8_t *d)
{
    return (int16_t)tm_u16(d);
}

static uint32_t tm_u32(const uint8_t *d)
{
    return (uint32_t)d[0] | ((uint32_t)d[1] << 8) |
           ((uint32_t)d[2] << 16) | ((uint32_t)d[3] << 24);
}

static int32_t tm_i32(const uint8_t *d)
{
    return (int32_t)tm_u32(d);
}

/* Bit-Index 0..63 ueber den gesamten Frame, wie in DBC und LDF */
static int tm_bit(const uint8_t *d, uint8_t bit)
{
    return (d[bit / 8] >> (bit % 8)) & 1;
}

/* States (0x770 / 0x10) */
void parse_states_message(const uint8_t *data)
{
    int is_charging    = tm_bit(data, 0);
    int is_discharging = tm_bit(data, 1);
    int any_protection = tm_bit(data, 6);
    int any_fault      = tm_bit(data, 7);
    int low_soc        = tm_bit(data, 10);
    int critical_alert = tm_bit(data, 27);

    /* Mittelwert der vier Zelltemperatursensoren */
    float temperatur_c = tm_i16(&data[4]) * 0.01f;

    if (any_fault) {
        /* Fehlerbedingung behandeln */
    }
    if (any_protection) {
        /* Schutzfunktion behandeln */
    }
    if (critical_alert) {
        /* Kritischer Systemfehler, Batterie muss geprueft werden */
    }

    printf("Laden: %d, Entladen: %d, Low SoC: %d, Temperatur: %.2f C\n",
           is_charging, is_discharging, low_soc, temperatur_c);
}

/* General_Readings (0x774 / 0x14) */
void parse_general_readings(const uint8_t *data)
{
    uint32_t spannung_mv = tm_u32(&data[0]);
    int32_t  strom_ma    = tm_i32(&data[4]);  /* negativ = Entladung */

    printf("Spannung: %lu mV, Strom: %ld mA\n",
           (unsigned long)spannung_mv, (long)strom_ma);
}

/* Capacity (0x776 / 0x16) */
void parse_capacity(const uint8_t *data)
{
    float soc_prozent      = tm_u16(&data[0]) * 0.01f;
    float soh_prozent      = tm_u16(&data[2]) * 0.01f;
    float entladbar_ah     = tm_u16(&data[4]) * 0.1f;
    uint16_t nennkapaz_ah  = (uint16_t)data[6] * 2u;

    printf("SOC: %.2f %%, SOH: %.2f %%, entladbar: %.1f Ah von %u Ah\n",
           soc_prozent, soh_prozent, entladbar_ah, nennkapaz_ah);
}

/* Time_To_Go (0x779 / 0x19) */
void parse_time_to_go(const uint8_t *data)
{
    uint32_t time_to_go_min  = tm_u32(&data[0]);
    uint32_t time_to_full_min = tm_u32(&data[4]);

    if (time_to_go_min == TM_NOT_APPLICABLE) {
        printf("Time to Go: Nicht anwendbar\n");
    } else {
        printf("Time to Go: %lu Minuten\n", (unsigned long)time_to_go_min);
    }

    if (time_to_full_min == TM_NOT_APPLICABLE) {
        printf("Time to Full: Nicht anwendbar\n");
    } else {
        printf("Time to Full: %lu Minuten\n", (unsigned long)time_to_full_min);
    }
}

LIN-Schedule-Implementierung

Die Zahlen sind die Wiederholraten aus der Nachrichten-Übersicht. Beim Aufbau der Schedule-Tabelle im Master ist zu beachten, dass sich die Wiederholrate eines Frames aus der Gesamtlänge des Schedule-Zyklus ergibt und nicht aus dem Slot, in dem er steht. Die schnellen Frames müssen daher mehrfach pro Zyklus eingeplant werden.

// LIN Schedule-Tabelle: Frame-ID und angestrebte Wiederholrate
lin_frame_t schedule[] = {
    {0x10, 100},    // States           - 100ms
    {0x14, 100},    // General_Readings - 100ms
    {0x15, 100},    // Cell_Voltages    - 100ms
    {0x16, 1000},   // Capacity         - 1000ms
    {0x11, 1000},   // Parameters       - 1000ms
    {0x17, 1000},   // Cumulativ_Ah     - 1000ms
    {0x19, 1000},   // Time_To_Go       - 1000ms
    {0x12, 5000},   // Serial_Number_1  - 5000ms
    {0x13, 5000},   // Serial_Number_2  - 5000ms
    {0x18, 10000},  // Uptime           - 10000ms
};

Konformitätstests

Nachrichten-Validierung

  1. Überprüfung, dass alle Nachrichten-IDs übertragen werden
  2. Prüfung der Timing-Anforderungen
  3. Validierung der Datenbereiche und Skalierung
  4. Test der Fehler-Flag-Funktionalität

Integrations-Checkliste

Versions-Historie

Version Datum Änderungen
1.4 23.04.2026
  • Änderung der Einheiten für Time_To_Go und Time_To_Full von Sekunden auf Minuten
1.3 17.03.2026
  • Fehlerbehebung im Signal "Temperature" im States Frame (0x770/0x10) im .dbc - nun anstatt 16 Bit unsigned, 16 Bit signed
1.2 20.02.2026
  • Hinzufügung des Signals "Temperature" im States Frame (0x770/0x10) - 16 Bit unsigned, 0.01°C Auflösung
  • Entfernung des Signals "Temperature" aus dem General_Readings Frame (0x774/0x14)
  • Änderung des Signals "Current" im General_Readings Frame von 16 Bit signed auf 32 Bit signed
  • LIN-Struktur an CAN-Struktur angepasst
1.1 28.11.2025
  • Entfernung des Signals "Uptime_Since_Last_Reset". Stattdessen bleibt diese Adresse frei.
  • Hinzufügung von Time_To_Full bei CAN-ID 0x779 bzw. LIN-ID 0x19
  • Fehlerbehebung bei Time_To_Go Berechnung
1.0 01.11.2025 Erstveröffentlichung

Kontakt: Für technischen Support und Protokoll-Updates wenden Sie sich an das Entwicklungsteam.