Einige Inhalte dieses Webauftrtitts wurden unter Zuhilfenahme von AI erstellt und/oder optimiert.
Teilnehmermodus
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:
Aktivierung über App > "Netzwerk" > "CAN Teilnehmermodus" > "Hinzufügen".
LIN
Der LIN-Bus ist an Pin 8 der SaftkistePRO anzuschließen:
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 zuTime_To_Go. Bei gesetzter Grenze kannTime_To_Godaher 0 erreichen, währendDischargeable_Capacitynoch 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_ActiveundCritical_AlertFlags - 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
- Überprüfung, dass alle Nachrichten-IDs übertragen werden
- Prüfung der Timing-Anforderungen
- Validierung der Datenbereiche und Skalierung
- Test der Fehler-Flag-Funktionalität
Integrations-Checkliste
Versions-Historie
| Version | Datum | Änderungen |
|---|---|---|
| 1.4 | 23.04.2026 |
|
| 1.3 | 17.03.2026 |
|
| 1.2 | 20.02.2026 |
|
| 1.1 | 28.11.2025 |
|
| 1.0 | 01.11.2025 | Erstveröffentlichung |
Kontakt: Für technischen Support und Protokoll-Updates wenden Sie sich an das Entwicklungsteam.