Aus meinem LIN-Sniffer Projekt (Beitrag "TJA1020 mit ESP32 betreiben") habe ich nun zwei Logs erzeugt (CANDUMP Format, lesbar mit SavvyCAN), jeweils ohne besondere Aktionen durchzuführen, außer "Zündung an". Am Bus hängen bekanntermaßen folgende Teilnehmer:
Master: BCM
Slave:
Regensensor ("BV6T-17D547-AD")
Batteriesensor ("AG9N-10C679-DE")
Scheibenwischermotor
Ein Diff-Vergleich der IDs beider Logs ergab (nicht beantwortete IDs sind nicht aufgeführt):
no-batsensor_no-action.log
0x05
0x06
0x10
0x20
0x35
0x3C
Also nutzt der Batteriesensor vermutlich diese IDs
0x0D
0x0E
0x0F
0x17
0x26
0x2B
Die mit dem Multimeter gemessene Batteriespannung lag zwischen und 12,3 und 12,5V (stieg im laufe der Messung). Es waren keine besonderen Verbrauchen zugeschaltet (Licht Aus, Heizungen aus).
Die Teilenummer auf 0x2B ist unstrittig und das einzig wirklich belastbare im Moment.
1
> 0x0D Spannung
2
3
0x0E Strom 16‑Bit‑Wert
4
0x0F Temperatur
Geraten? KI-Analyse? Erfahrung?
Ich habs auch mit KI versucht, aber die Ergebnisse sind mir nicht plausibel. Laut Claude.ai ist in 0x0D Spannung, Strom und Temperatur und eine Prüfsumme enthalten.
Der Sensor ist vermutlich von HELLA (IBS?), müsste was sein was es bereits Anfang 2007/2009 rum gab. Der Sensor selbst ist sicher in etlichen anderen Ford-Modellen verbaut, sicher auch in Fahrzeugen anderer Hersteller.
Die Spannung im (letzten) Log lag so bei 12,2 - 12,5 V rum, laut Multimeter. Der Wagen lief nicht, nur Zündung an, ohne besondere Verbraucher würde ich eine Stromabgabe von 2-4 A schätzen. Anfänglich kommen die Glühkerzen (Diesel) dazu, die könnten durchaus 25 - 50 A ziehen für eine Sekunde oder zwei.
Der Wagen steht in der Garage, bei aktuellen 2°C Außentemperatur ist es da drin auch kaum wärmer. Der Sensor gibt natürlich seine Sensortemperatur wieder, die kann schon steigen bei Stromfluß. Claude.ai meinte die Temperatur mit einem Offset -20 zu belegen, was ich für totalen Quatsch halte. Wenn dann -40.
Beim HELLA IBS Sensor ist die Batteriespannung im Payload als 2-Byte Wert im Little-Endian Format / 1000 enthalten.
In 0x0D wären das Werte wie .. CC 56 bis .. C6 55, also 0x56C6 = 22.214 / 1000 = 22,214 V. Das kommt nicht hin. Auch ist gut erkennbar das Byte 4 der Nachricht immer nur 0x55 oder 0x56 ist und keine anderen Werte annimmt.
Beim HELLA IBS Sensor ist die Batteriespannung im Payload als 2-Byte
Wert im Little-Endian Format / 1000 enthalten.
Beim Hella IBS 200X wird die Batteriespannung mit 16 Bits, der Strom mit 24 Bits und die Temperatur mit 9 Bits dargestellt.
Das sagt aber nichts darüber aus wie es die Fahrzeughersteller machen. Bei VW wird z.B. mit der fast identischen Sensorhardware von Hella die Batteriespannung mit 14 Bits, der Strom mit 16 Bits und einem Skalierungsfaktor (1, 10 oder 100) und die Temperatur mit 8 Bits dargestellt. Das Ganze natürlich auch mit einer anderen ID als beim Hella IBS 200X.
Ich wuerde erst mal probieren mit Taschenlampe und Giesskanne eine
bessere Zuordnung zu treffen....
Bei der Batterie? Besser nicht... ;-)
Den Regensensor habe ich schon, der ist einfach. Der Wischermotor hat eigentlich kein LIN, sondern nur popelige Kontakte und Windungen. Hier ist es wohl so das er am BCM elektrisch angeschlossen ist und das BCM einen LIN-Slave auf dem Bus emuliert. Das macht eigentlich nur Sinn wenn der Regensensor erwartet den Motor direkt ansteuern zu können, oder?
Das wiederum bedeutet das der Regensensor auch einen Motorstatus ermitteln können muss. Auch das die Position und Einstellung des Wischerhebels am Lenkrad für den Sensor wichtig ist. Ich hätte anfangs gedacht das es sich nur um einen dummen Sensor handelt und das BCM die gesamte Steuerung übernimmt... ich wüsste aber keinen Grund warum das sonst so gebaut sein sollte?
dargestellt. Das Ganze natürlich auch mit einer anderen ID als beim
Hella IBS 200X.
Vermutlich gibt der Autohersteller ein LDF vor nachdem es Hella dann programmiert, das falls der Autobauer seinen Lieferanten wechselt (was sie ja gern mal tun wenn es einen Mikrocent zu sparen gibt) alles so funktioniert wie zuvor...
Das heißt aber auch das mir die eigentlich sehr umfangreichen Infos im Netz bezüglich des HELLA IBS nichts nutzen.
Vermutlich gibt der Autohersteller ein LDF vor nachdem es Hella dann
programmiert, das falls der Autobauer seinen Lieferanten wechselt (was
sie ja gern mal tun wenn es einen Mikrocent zu sparen gibt) alles so
funktioniert wie zuvor...
Genau so ist es. Der RLS und der Batteriesensor sind Katalogteile, die kundenspezifisch angepasst werden. Also Schrauben- oder Klipspositionen, Kommunikationsschnittstelle und Kommunikationsmatrix.
Was mir noch so auffällt ist, das jedes Log mit diesem Frame endet:
03C#0000000000000000
Enden bedeutet, das ich die Zündung ausgeschaltet habe und der LIN-Datenstrom wenige Sekunden danach verödet. PID 0x3C entsprich ja der ID 0x12. Das sieht doch verdächtig nach einem vom Master (BCM) gesendeten Ruhebefehl aus?
Was mir noch so auffällt ist, das jedes Log mit diesem Frame endet:
03C#0000000000000000
Das ist der normale LIN Sleep-Befehl für Busruhe. Eigentlich nach Spec 0x00 FF FF FF FF FF FF FF, aber der hintere Teil wird ignoriert. Also Master Request (PID 0x3C) mit dem ersten Byte Null.
Zum Wecken gibt man einen Low-Puls von mindestens 150 µs auf den Bus. Kannst Du auch selber machen. Einmal kurz gegen Masse ziehen, dann wachen alle Steuergeräte auf.
Miss doch bitte mal am Lichtschalter Richtung BCM;) Bei meinem Ford (Mondeo MK4 VFl) waren die Lampen arg duster, niemand wollte oder konnte mir die etwas heller stellen. Wurden aber nachweislich mit nur 82%PWM betrieben, sobald der Motor lief. (Bin da mal imt'm Oszi dran gewesen, um das zu zeigen)
Aber auch egal; nur wenn Zeit ist.
Wurden aber nachweislich mit nur 82%PWM betrieben,
Was meinst du mit "nur 82%PWM"?
Soll das heißen, dass die Lampe 82% der Zeit aus war?
Sonst wirst du die Helligkeit durch Änderung des Tastverhältnisses nicht wirklich merkbar erhöhen können. Eine Leistungserhöhung von 0.9 dB siehst du nicht, solange man die beiden Lichtquellen nicht direkt nebeneinander hält.
Soll das heißen, dass die Lampe 82% der Zeit aus war?
ne - an, mit eben "etwas Luft nach oben". Beim Start 100% und dann, wenn die Spannung hoch geht, werden die Lampen runtergeregelt.
Ich kann mal suchen, ob ich den Thread noch finde. Hab dann die PWM-Lücken mit Elkos aufgefangen. Ging ganz gut.
Das ist der normale LIN Sleep-Befehl für Busruhe. Eigentlich nach Spec
0x00 FF FF FF FF FF FF FF, aber der hintere Teil wird ignoriert. Also
Master Request (PID 0x3C) mit dem ersten Byte Null.
Perfekt, das erklärt es natürlich!
Theoretisch müssten die Slaves dann ja noch mit 0x3D antworten.
Zum Wecken gibt man einen Low-Puls von mindestens 150 µs auf den Bus.
Das passiert bei mir nicht, zumindest kommt keine Kommunikation zustande. Aber ich denke das liegt evtl. daran das eben das BCM das Master ist und es für sich keinen Grund sieht aufzuwachen nur weil der Regensensor was zu maulen hat ;-)
Inzwischen habe ich meinem Sniffer auch eine Sendefunktion spendiert. Aktuell nur ganz simpel mit "HEADER <PID>". Damit kann ich aber immerhin eine Antwort provozieren, auch wenn der Bus durch 0x3C schlafen gelegt wurde.
Hier habe ich mir das Multibyte-Frame der PID 0x2B zum testen genommen. Das ist der Batteriesensor, dort liefert er seinen Teilecode. Dabei scheint es eine interne Statemachine mit Timeout zu geben, denn nur wenn man die Requests innerhalb eines bestimmten Zeitfensters hintereinander abfeuert, erhöht er das FF/CF Byte (1. Byte) im Frame. Ansonsten fängt er einfach wieder von vorn an.
Interessant finde ich das er mit dem Zähler 0x02 startet, erwartet hätte ich eigentlich 0x01, oder ein Bit 7 gesetzt/nicht gesetzt, wie bei CAN.
ID 0x04 sehe ich in keinem der anderen Logs, aber irgendwas antwortet da.
ID 0x2A wird bei allen Logs immer UNANSWERED, frage ich das direkt, kommt all-FF.
ID 0x17, 0x26 und 0x27 haben sichtbar andere Werte als im Betrieb.
ID 0x17
Ich habe das jetzt mal mit Messwerten (Fluke) am Fahrzeug verglichen. Dort messe ich 12,60V mit diesen Daten, die mutmaßlich dem Batteriesensor gehören:
1
HEADER 0D
2
HEADER sent for ID 0x0D - watch for RX response
3
(5823.025788) lin0 00D#0020C954 # RX Classic
4
5
HEADER 0E
6
HEADER sent for ID 0x0E - watch for RX response
7
(5827.942076) lin0 00E#00B22AFF # RX Classic
8
9
HEADER 0F
10
HEADER sent for ID 0x0F - watch for RX response
11
(5832.341869) lin0 00F#CA87AFFF # RX Classic
Es ist auch so, das manchmal keine Antwort kommt und wenn man nochmal fragt, kommt eine. Also z.B.
1
HEADER 0E
2
HEADER sent for ID 0x0E - watch for RX response
3
(5825.066894) lin0 00E# # UNANSWERED
4
5
HEADER 0E
6
HEADER sent for ID 0x0E - watch for RX response
7
(5827.942076) lin0 00E#00B22AFF # RX Classic
Könnte an meiner LIN-Implementation liegen, oder einem unpräzisen, zu knappen Break, oder der Sensor schläft beim ersten Request noch und ich warte nicht lange genug auf das Antwortbyte?
Meine aktuelle LIN-BREAK Methode schaut so aus:
1
// sende ein 0x00 mit halber Baudrate (4800 baud)
2
uart_set_baudrate(uart_num,lin_baudrate/2);
3
uart_write_bytes(uart_num,"\x00",1);
4
uart_wait_tx_done(uart_num,...);
5
uart_set_baudrate(uart_num,lin_baudrate);// zurück auf 9600
6
esp_rom_delay_us(LIN_BREAK_DELIMITER_US);
Bei 9.600 Baud dauert ein Byte = 1,042 ms. Bei halber Baudrate (4.800) = 2,083 ms.
Das BREAK-Signal muss nach LIN-Spezifikation mindestens 13 Bit-Zeiten lang sein, also 1,354 ms bei 9.600 Baud.Problem: uart_set_baudrate() und uart_wait_tx_done() haben Overhead durch FreeRTOS und könnten um einige 100 µs variieren.
Ich überlege ob es sinnvoller ist die Methode mittels GPIO umzusetzen:
00D#0020C954 sieht irgendwie leer aus
0020
8192
Zufall oder
Ne, sicher kein Zufall. Ich glaube 0x0D ist der Stromfluss. Der kann ja positiv oder negativ sein.
Die Daten im Payload dürften immer Little-Endian sein.
Nehmen wir an 8192 wäre der Nullpunkt ("0 A" Stromfluß), wenn also alles aus ist. Das sieht man immer am Anfang und am Ende der Logs. Von dort geht es dann nach oben bis 0xFFFF (= +57344) und nach unten bis 0x0000 (= -8192).
Schau mal ob Du damit was anfangen kannst - nur das dritte Byte aus 0x0D als Batteriespannung. Macht Deine LiMa beim Start mehr als 15V und regelt dann ein?
Mit Bitschubserei hab ich noch nicht angefangen, konnte nicht so recht was erkennen.
Also bei 0x0F komm ich auf keinen grünen Zweig. Bei 0x0E ist es mindestens ein 16-Bit Wert, das kann man gut am Bitmuster sehen. Könnte Temperatur sein, Wert / 1024 - 40 kommt auf 4,50 °C
1
FF B1 11 FF 1 1 1 1 1 1 1 1 1 0 1 1 0 0 0 1 ...
2
00 B2 11 FF 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 0 ...
0x0D als 24-Bit Wert / 1024 ergibt wohl mV (hatte vorher mit 1000 gerechnet) da passt das gut zum Startvorgang
Ich habe jetzt mal den Batteriesensor vom Bus abgezogen, der ist gut zugänglich, und dort direkt meinen Sniffer angehangen. Nun spreche ich also direkt und ausschließlich mit dem Sensor.
Damit sollte dann ja eindeutig geklärt sein welche IDs zum Sensor gehören, bzw. von ihm beantwortet werden. Unklar ist noch welche er selbst konsumiert?
Ich habe nun mal den Batteriesensor "zurückgesetzt". Dafür gibt es im Fahrzeug eine Prozedur an dessen Ende das Batteriesymbol im Kombiinstrument einige male zur Bestätigung blinkt. Dabei sollen die Anlernwerte zurückgesetzt werden. Ich glaube aber nicht das hier etwas in den Sensor programmiert wird, sondern das das BMS seine Werte neu einstellt um eine neue Batterie wieder optimal zu laden. In dem Log sehe ich zumindest nichts, was ich nicht auch in anderen Logs gesehen hätte...
0x0D als 24-Bit Wert / 1024 ergibt wohl mV (hatte vorher mit 1000
gerechnet) da passt das gut zum Startvorgang
00D#B81FC42B -> 00 C4 1F B8 -> 12853176 -> 12,6 V
Durch 1024 ist ja gleich mit >>10 (Bitshift um 10 Stellen nach rechts). Das ist definitiv logischer als ein teilen durch 1.000 dezimal.
Das 4. Byte ändert sich definitiv auch, die Frage ist halt was das wäre?
Für mich hätte das ja irgendwie besser zum Stromfluß gepasst...
Durch 1024 ist ja gleich mit >>10 (Bitshift um 10 Stellen nach rechts)
Hm stimmt. Da bleiben 14 Bits für den Wert. Das deckt sich ja mit der Info von Dieter. Dann ist es so schlimm wie befürchtet, die Bits sind nicht byte-aligned. Also doch Bitschubserei.
Ich habe mir ja ganz bewußt einen eigenen Sniffer gebaut, weil ich möglichst offen für Tools sein will. Zunächst hatte ich SavvyCAN im Blick, das kann eine große Zahl von Log-Dateiformaten laden, ist aber natürlich für CAN Frames gedacht. Damit habe ich obige Grahpen gemacht (Flow view). SavvyCAN ist OpenSource und läuft auf PC, Linux, Mac.
Mein Sniffer ist einfach ein ESP32 (hab nen S3 und nen C6 getestet) und ein TJA1020 als Transceiver. Etwas Komfort habe ich inzwischen einprogrammiert, vor allem weil ich bequem vom warmen Arbeitszimmer arbeiten wollte und nicht ständig mit dem Laptop im Schnee am Auto stehen, bzw. in der eiskalten Garage. Daher kann mein Sniffer sich mit einem WLAN verbinden und akzeptiert einen Telnet-Client der verschiedene Befehle kann und eben Frames im candump Format ausgibt. Dann habe ich noch einen Webserver drüber gelegt, der eben per http ein solches Terminal emuliert und auch einen Firmware-Upload für OTA bietet. So muss ich fast nicht mehr raus in die Kälte ;-)
Ein spezialisiertes LIN-Debug Tool wäre jetzt sicher hilfreicher, auch um bereits bekannte Parameter zu hinterlegen (Stichwort LDF).
Wie ich grad gelesen hab CAN ist von rechts nach links, während LIN von links nach rechts ist. Man müsste also von MSB nach LSB konvertieren, vielleicht sehen die Daten dann im SavvyCAN sinnvoller aus.
Ich habe jetzt meinen LIN-Sniffer mit einer POLL-Funktion erweitert:
1
POLL <ID> <periode_ms> -> endlos
2
POLL <ID> <periode_ms> <N> -> N Wiederholungen (reine Zahl)
3
POLL <ID> <periode_ms> <N>s -> N Sekunden (Zahl + 's')
4
STOP -> sofort stoppen
So kann ich periodisch als Master eine ID auf den Bus legen (um z.B. "offline" direkt mit nur einem Slave zu sprechen) welche ich in einem Intervall automatisch wiederholen lasse. Das ganze dann optional mit N Wiederholungen oder über eine Dauer in Sekunden.
Stoppen lässt es sich vorher mittels STOP Befehl oder durch einen neuen POLL.
Damit werde ich jetzt mal zyklisch 0x0D ausgeben lassen und verschiedene Aktionen durchführen die den Stromfluß der Batterie signifikant ändern müssten, z.B.
Ladegerät/Starterpack anschließen (+2 A bis 3 A)
Motor starten (-600 A bis -800 A)
Licht einschalten (35W Xenon = -2 A)
Motor laufen lassen (Einpegelphase) und dann Front- und Heckscheibenheizung einschalten. FSH hat ca. 600 W, also gute 50 A, das sollte erkennbar sein. HSH dürfte bei ca. 200 W liegen, also abermals runde 15 A.
Ideal wäre natürlich den echten Stromfluß zu messen und mit den Werten des Sensors zu vergleichen. Leider habe ich kein DC Zangenamperemeter. Aber vielleicht könnte ich einfach den Spannungsabfall über dem Batteriesensor messen? Das ist ja im Grunde nichts anderes als ein Shunt im Milliohm-Bereich.
Wie ich grad gelesen hab CAN ist von rechts nach links, während LIN von
links nach rechts ist. Man müsste also von MSB nach LSB konvertieren,
vielleicht sehen die Daten dann im SavvyCAN sinnvoller aus.
Das mag stimmen, ist für unsere Betrachtung aber egal, da SavvyCAN keine Kombinationen durchführt, es stellt jedes Byte einzeln dar. Leider...
Im Ruhezustand ist der mutmaßliche Stromverbrauchswert ja praktisch immer 00 20 = 0x2000 (8192) = 0A. Das Auto zieht im absoluten Ruhezustand ja wirklich nur wenige Milliampere. Dennoch hätte ich gedacht das der Sensor so empfindlich ist das zu erkennen, wozu sonst eine Auflösung von 1 mA?
Anbei mal ein Log mit dem POLL auf 0x0D während einer Sequenz.
Extrem beeindruckend was Claude.ai da in meinem Auftrag als Statistik ausgespuckt hat (HTML).
Er ist der Meinung der Payload wäre: [cur_lo][cur_hi][volt][chk]
Strom-Berechnungsformel: I = (raw16 − 0x2000) × 0.02441
Wobei negative Werte = Entladung, positive = Ladung seien.
Die Spannung meint er wäre: U = volt × 0.060
Ja, den und andere hatte ich mir schon angeschaut. Aber wie ganz oben schonmal erwähnt kann das in meinem, fahrzeugspezifischen Sensor alles ganz anders sein...
Gut, die ID lassen wir mal weg und schauen nur auf die Formeln. Ibatt sind da drei Bytes und ein ganz anderer offset und Teiler. Auch scheint in diesem Modell der Frame 5 Bytes zu liefern und nicht nur 4.
Wenn wir davon ausgehen dass Strom mit im Frame drin steckt, dann können das unter der Annahme dass Spannung passt nur die ersten 10 Bits sein. Da die negativ werden kann ist es wohl ein Signed Int. Die nächsten 14 Bits sind dann Spannung, und die letzten 8 Bits Temperatur. Kannst Du das mal testen?
Hier mal ein POLL (60s Interval) von 0x0D während nur das Ladegerät dran hängt. Die Claude-Auswertung ist zwar schick, aber unplausibel. Ich glaube der rechnet hier falsch. Die Ladespannung ist garantiert keine 16,5V und der Ladestrom sicher höher als 70mA.
Seine Formeln lauten aktuell:
I [mA] = (b[1]<<8 | b[0]) − 8192 → Nullpunkt bei 0x2000, 1 mA/Einheit
V = b[2] / 16
T [°C] = b[3] / 3.4
Wenigstens die Temperatur ist sicher falsch berechnet, denn da muss irgendwo ein "-40" drin stecken, da bin ich mir sicher.
UPDATE #1:
Ich habe die Log-Datei nochmal aktualisiert und auch mal am Fahrzeug die Spannung mit einem Multimeter gemessen. Diese war zum Zeitpunkt 9157.466032 exakt 14,02V. Die Grafik "15-02-2026_13-55-13.png" sieht jetzt sehr stimmig aus, auch was die Spannung angeht.
Bei einem 8-Bit Wert durch 16 (>>4) erhält man eine winzige Mantisse von 4 Bits nach dem Komma und 4 Bits davor. Mit den oberen 4 Bits wären also maximal 16 V darstellbar, was für den KFZ-Bereich grundsätzlich ok wäre, denn mehr würden die Steuergeräte auch nicht verkraften. Und eine Nachkommastelle mit 4 Bit Auflösung wäre aus meiner Sicht auch ok.
UPDATE #2:
Was er als Temperatur sieht ist für mein Empfinden eher ein Zähler. Dafür ist die Steigung und der Abstand zu konstant. Das könnte irgendein Epoch-Zähler sein, intern im Sensor?
Aktuell wären für den Strom Werte von -82A (Entladung) und +573A (Ladung) darstellbar, aber unplausibel. Genau umgekehrt wäre es eigentlich korrekt, denn selbst 80A Ladestrom wären schon mehr als doppelt so viel wie die stärkste Batterie verkraften würde, wohingegen 600A Stromentnahme beim starten durchaus normal wären.
Wenn ich aber einfach das Vorzeichen umdrehe, würde meine Ladekurve vom Batterieladegerät irgendwie seltsam aussehen, nicht wahr? Evtl. ist doch der Nullpunkt einfach ein anderer? Oder Du hast Recht und da fehlen noch ein paar Bits? Möglicherweise sind die 4 Byte von 0x0D nicht gleichmäßig aufgeteilt, sondern von Byte 3 gehören noch ein paar Bits zum Strom und der Rest zur Spannung? Irgendwie doch noch nicht 100% sicher.
Ich lese ja aktuell im 60s-Takt die ID. Aus der Änderung des 4. Bytes hat claude ermittelt das sich der Wert alle 11 Minuten erhöht. Hm, krummer Wert, vielleicht weil Karneval ist?
Du hast ein Abfrageintervall von 60 Sekunden d.h. nur aller 60 Sekunden ein Wert, oder alle Werte innerhalb von 60 Sekunden? Dachte Du hattest einen kompletten Motorstart aufgezeichnet...
Falls jemand Interesse an meinem Sniffer-Tool haben sollte, das wäre hier zu haben: https://github.com/igittigitt/esp32_lin_sniffer
Enthalten ist auch ein prebuild image zum direkten Flashen eines ESP32-C6 mittels Commandline, Windows, oder Web-Flasher von Espressif.
So, keine Lust mehr auf KI. Hab hier mal ein Script was ich zum Bitschubsen genutzt hab. Damit kannst Du einzelne Bits rauspicken und dir den Wert als unsigned / signed anzeigen lassen. Man könnte noch ein zweites Bruteforce Wrapper Script drumherum bauen das mit den Offsets spielt und nur Treffer ausgibt die in einem bestimmten vorgegebenen Range liegen. Hilft vielleicht bei der Suche. Ich lösche es jetzt.
Ich kann mich erinnern dass es selbst mit bekannten Offsets schwierig war die Werte plausibel zu kriegen, insbesondere krumme Bitfelder die mehr als 8 Bit hatten und über Byte Grenzen hinweg gingen. Ich glaube der Trick war Highbyte und Lowbyte getrennt zu maskieren und nach der Extraktion ein zweites Mal zu vertauschen.
Ich frage mich warum Ford es sich hierbei unnötig schwer machen sollte? IDs sind genug da. Auch frage ich mich was so die restlichen IDs angeht wozu die noch dienen...
Ich könnte mir vorstellen dass es zu einem Shunt auch eine Shunt-Spannung und eine Shunt-Temperatur braucht um eine präzise Strommessung hinzubekommmen. Ergo dienen die Daten einer einzeln PID möglicherweise nur einer einzigen Kenngröße.
Jedenfalls sollte man da mit NI ran, KI ist verführerisch aber oft falsch.
Ich könnte mir vorstellen dass es zu einem Shunt auch eine
Shunt-Spannung und eine Shunt-Temperatur braucht um eine präzise
? Ein Shunt ist ein kleiner, präziser Widerstand und über ihm fällt eine Spannung analog zum Stromfluss ab. Natürlich ist jedes Material temperaturanfällig, was vermutlich auch der Grund ist das es einen Sensor gibt zur Kompensation, nicht nur für die Batterieberechnungen?
Was mir aber auffällt ist das das 2. Byte, welches ja mutmaßlich das MSB des Stroms ist, nie unter 0x0A fällt, selbst beim Motorstart und ich habe mit einer Auflösung von 100ms gescannt. Mir will einfach nicht einleuchten warum man den Messbereich für Entladung auf 80A und für Ladung auf fast 600A dimensionieren sollte, das kann doch nur falsch sein? Dreht man aber einfach das Vorzeichen um, dann passt es auch nicht.
Jedenfalls sollte man da mit NI ran, KI ist verführerisch aber oft
falsch.
Ja, die lügt oft wie gedruckt, verkauft es aber als Wahrheit... was das angeht hat sie von der NI schon gut gelernt.
Was mir aber auffällt ist das das 2. Byte, welches ja mutmaßlich das MSB
des Stroms ist, nie unter 0x0A fällt,
Dann zerteile es bis es passt. Notfalls auch mal umdrehen auf LSB-first. Ein ADC mit 10 Bit Auflösung muss nicht zwangsläufig als 16 Bit Integer liefern.
Ideal wäre natürlich den echten Stromfluß zu messen und mit den Werten
des Sensors zu vergleichen. Leider habe ich kein DC Zangenamperemeter.
Normales Multimeter reicht aus. Kann man ohne Unterbrechung zwischenklemmen. Musst halt irgendwo mit Masse verbinden, die andere Messspitze direkt auf den Batteriepol (Masse) drücken, das Massekabel von der Batterie lösen und drüber fädeln.
Aber vielleicht könnte ich einfach den Spannungsabfall über dem
Batteriesensor messen? Das ist ja im Grunde nichts anderes als ein Shunt
im Milliohm-Bereich.
Dann müsstest Du Dir wohl noch einen OPV dazu löten und den Spannungsabfall ausreichend verstärken damit er messbar wird.
Zwischendurch habe ich mir mal den Regensensor angeschaut. Der hat im Mondeo eine eigene Sicherung (beim MK4 Facelift ist das "F6" im BCM welches auch als zentraler Sicherungskasten für den Innenraum dient). Die habe ich einfach mal gezogen, Zündung an und den Log mit einem verglichen wo die Sicherung drin war.
Dabei war wunderbar zu erkennen das auf ID 0x05 und 0x35 keine Antworten mehr kamen, das ist also ganz klar der "BV6T-17D547-AD" Regensensor. Dieser Sensor ist übrigens aufgrund eines Scheibentauschs nicht mehr der Originale, der war ein "6G9N-17D547-AD" (BOSCH 1 397 212 103, bzw. VOLVO 312 14 359).
Die 0x05 wird alle 100 ms (10 Hz) bzw. 200 ms abgefragt (5 Hz), das hängt wohl mit dem Schedule-Slot zusammen den das BCM dafür reserviert.
Interessant ist das immer am Anfang (also immer nach Zündung an) eines Logs diese Sequenz zu sehen ist: "40 09" -> "40 08", danach folgt nur noch "40 02" dauerhaft. Das sieht doch stark nach einem Wakeup/Init aus?
09 = Aufwachen
08 = Initialisierung
02 = normaler Betrieb
Ich werde mal ein paar Messungen mit der Sprühfalsche auf den Sensor machen und schauen wie sich seine Werte ändern?
Neben der Regenerkennung auf der Scheibe dient der Sensor auch zur Erfassung der Helligkeit für die Lichtautomatik. Es sollte also auch einen Unterschied anzeigen wenn es hell oder dunkel ist.
Noch eine andere Idee für reproduzierbare Testbedingungen: Den Batteriesensor ausbauen (ist nur eine Schraube am Massekabel, oder?) und am Labornetzteil betreiben. Da kann man dann die Spannung zwischen 8 und 15V mal testen. Und definierte Ströme in beide Richtungen.
Wie funktioniert ein Regensensor? Was liefert der? Eine Spannung? Einen
Status? Ist da ein ADC drin? Wenn ja welche Auflösung?
Er bekommt den Schalterstatus von Wischer und Wascher, die Wischerposition, die Helligkeit (sofern er sie nicht als Regen/Licht-Sensor selber misst ;-), den Schalterstatus des Fahrlichtes und die Fahrzeuggeschwindigkeit. Dafür liefert er ein wiper speed request. Also langsam wischen, schnell wischen, aus.
Im Sensor sitzen mehrere Fototransistoren, die über den internen ADC des Controllers ausgewertet werden. Der Controller treibt auch die LEDs und die Heizung (gegen Beschlagen) und macht die Auswertung und Bus-Kommunikation.
Vielleicht macht es Sinn sich erstmal die Lichtmaschine vorzuknöpfen. Wenn ich den Text richtig verstanden habe sind die in verschiedenen Fahrzeugen verbaut und die Bitfields einheitlich. Wenn man das nachvollziehen kann und das passt, versteht man auch besser wie andere LIN Frames aufgebaut sind.
Noch eine andere Idee für reproduzierbare Testbedingungen: Den
Batteriesensor ausbauen (ist nur eine Schraube am Massekabel, oder?) und
Ja, so mache ich das auch für Gewöhnlich, solange die Probanten solo zu betreiben sind. Ich habe auch noch den alten Regensensor hier (meiner wurde mit der Scheibe mal getauscht), den würde ich mal auf dem Labortisch testen können. Ein Batteriesensor kostet aus nem Schlachterfahrzeug auch nicht die Welt (20-40€), ausbauen will ich meinen nicht, da er fest in das Massekabel integriert ist, welches ich dann austauschen müsste. Die Batterie auszubauen ist leider etwas Aufwand bei mir (Luftfilter raus, etc.).
Wie funktioniert ein Regensensor? Was liefert der? Eine Spannung? Einen
Status? Ist da ein ADC drin? Wenn ja welche Auflösung?
Der arbeitet optisch, mit Reflektion von IR-Licht auf der Scheibe, ein bisschen so wie ein PIR-Sensor. Hier ist das Funktionsprinzip ganz gut erklärt https://www.kfztech.de/kfztechnik/sicherheit/regensensor.htm
Dabei soll er den Grad der Nässe übermitteln, damit die Wischersteuerung entsprechend gegensteuert.
Dann hat er eben noch einen zusätzlichen Lichtsensor für die Umgebungsbeleuchtung. Bei manchen wird damit auch das automatisch abblendende Fernlicht gesteuert (in modernen Autos eher nicht mehr, da übernehmen Kameras).
Um einen Strom in 1 mA darstellen zu können braucht es für 500A schon 19
Bit.
Oder wir interpretieren die Kommaposition des Wertes falsch und in einem anderen Byte kommen links noch Bits dazu?
Vielleicht macht es Sinn sich erstmal die Lichtmaschine vorzuknöpfen.
Die hängt leider an einem anderen LIN-Bus direkt am PCM (Motorsteuergerät). Im Motorraum müsste ich aber da irgendwo dran kommen, muss ich bei Licht und schönerem Wetter mal suchen...
Ich habe nun weitere Versuche mit dem Regensensor unternommen und mit die ID 0x05 genauer angesehen. Dabei ist mir aufgefallen das die Werte statisch (b[0] b[1]) "40 02" blieben wenn der Wischerhebel nicht auf AUTO steht. Stellt man ihn auf die Automatik, dann ändert sich der Wert zu "00 02". Wenn der Wischer dann angesteuert wird (Wasser auf die Scheibe) dann geht der Wert auf "01 02".
Bei der Log-Aufzeichnung hat der Wischer nach Zündung an zwei/dreimal selbst eine Intervallwischung durchgeführt. Danach stand er bis ich Wasser auf die Scheibe gegeben habe. Erst wenig, dann lief er langsam, dann mehr, dann lief er schneller, bis er über Intervallwischen wieder auf Ruhestellung zurück ging.
Damit dürfte 0x05 b[0] so kodiert sein:
0x40 = Automatik aus
0x00 = Automatik an, kein Regen erkannt
0x01 = Automatik an, Regen auf Scheibe erkannt
Eine Intensität sieht man hierin nicht.
Daher habe ich dann mal eine Statistik erstellen lassen die mir jede im Log vorhandene ID als Graphen darstellt. Die Ausschlaghöhe ist dann einfach die Addition aller Bytes der ID Payload, jeweils auf gleiche Y-Höhe scaliert. So kann man auf einen Blick erkennen wann sich welche Werte wie geändert haben und das mit der ausgelösten Aktion in Verbindung setzen.
Ich denke ID 0x06 ist ganz klar die Intensität? Komisch nur das mein Offline-Scan die 0x06 auch angezeigt hat, als der Regensensor keinen Strom hatte. Oder ich übersehe hier noch was, das 0x06 nur die Wischerfunktion abbildet?
Der Regensensor reagiert übrigens nicht auf einfache Helligkeit, denn selbst eine 2000 lm LED Lampe lies das Fahrtlicht an. Der wird also auf IR-Anteil prüfen, was ja evtl. im Tunnel oder nachts auf beleuchteten Straßen mit Kunstlicht auch Sinn macht.
Macht Spaß das Python auf dem Handy. Die Spalten stimmen nur nicht wenn man 2 Byte und 4 Byte Payload zusammen darstellt. Und man muss aufpassen von rechts nach links zu zählen um die Position zu ermitteln. Das Script hat Verbesserungspotential.
Ich habe in meinem Code-Repo jetzt noch ein Analyzer-Tool hinterlegt, welches einfach im Browser läuft. Es kann die candump Logs lesen und deren Inhalte auf verschiedene Arten filtern und darstellen. Nicht so mächtig die SavvyCAN, aber besser als nix und quasi immer verfügbar :-)
Die Stellung des Wischerhebels wird über ID 0x06 ausgesandt (AUTO-Modus oder nicht, und Empfindlichkeit). Das dient dem Regensensor als Parameterierung.
Der Regensensor selbst scheint ja, neben der Teilenummer auf ID 0x35 als Status nur die ID 0x05 zu beantworten/senden. Diese habe ich nun entschlüsselt.
Zunächst folgt immer eine Sequenz aus: 40 09 -> 40 08 das könnte eine Initialisierung sein. Möglicherweise sind "40 09" und "40 08" auch Quittierungen für Parameter die das BCM auf ID 0x06 für den Sensor aufgelegt hat (Stellung des Wischerhebels und eingestellte Empfindlichkeit)?
Die Helligkeit ist im zweiten Byte (b[1]) kodiert. Nach der Initialisierung spring der Wert von ID 0x05 nämlich auf "40 02" bei Dunkelheit bzw. "40 00" bei Tageslicht. Damit ist klar das das zweite LSB Bit Dunkelheit signalisiert:
b[1] = 0x02 = 0000 0010 (Bit 1 = 1) -> Dunkel
b[1] = 0x00 = 0000 0000 (Bit 1 = 0) -> Hell
Erkannter Regen wird im ersten Byte (b[0]) kodiert:
b[0] = 0x40 = 0100 0000 (Bit 6 = 1) -> Wischerstellung auf Manuell oder Aus
b[0] = 0x00 → 0000 0000 (Bit 6 = 0) -> Wischerstellung AUTO und Scheibe trocken
b[0] = 0x01 → 0000 0001 (Bit 0 = 1) -> Wischerstellung AUTO und Regen erkannt (=Wischer auslösen)
Also Gibt Bit 6 die grundsätzliche Automatikfunktion wieder und Bit 0 ist der Auslöser für den Wischer.
Was jetzt noch fehlt ist die Regenstärke, denn abhängig davon schaltet das BCM den Wischer ja zwischen den Intervall- und Dauerstufen um. Im beigefügten Log habe ich mal mehr mal weniger Wasser auf den Sensor gesprüht, es sollten sich also wenigstens Intervall und Stufe I und II darin nachweisen lassen. Auf ID 0x05 im ersten Byte sieht man das jedoch nicht, man sieht nur das Flag.
Meine Vermutung ist das das BCM, welches diese ID ja mit einer sehr hohen Frequenz abfragt (~2,7 kHz) sich aus Zeit und Zustand ein PWM-Signal erzeugt und daraus die Intensität ableitet.
Ich habe das Tool "CaLiGraph" genannt da ich vor habe es auch für CAN Dumps einzusetzen. Es kann schon eine ganze Menge. Integriert habe ich einen Rekorder mit Replay und Live Funktion. Die Daten kommen über einen Websocket vom Sniffer oder aus einer Logdatei und werden in einer IndexedDB zwischengespeichert (Ringbuffer) und teilweise ins RAM geladen. Damit kann man auch lange Logs aufzeichnen. Es gibt einen Export aus der DB in eine LOG-Datei, so eignet sich dieses Tool hervorragend als Frontend zu meinem Sniffer.
Sobald die Arbeit am MONITOR Mode beendet sind begebe ich mit an den Simulator im DASHBOARD um dort Daten optisch mit Aktionen zu verknüpfen, z.B. Fahrtlicht an, oder Scheibenwischer, etc. Das wird nochmal etwas mehr Arbeit...
Sieht nach ner One-Man-Show aus. Das entwickelt sich in eine Richtung wo Du mehr Aufwand in die Entwicklung eines Analysetools setzt als in Deinen LIN-Bus. Ich hoffe sehr für Dich damit kann noch jemand außer Dir etwas mit anfangen ;)
Ich habe zwischenzeitlich zwei Alarm-Sensoren (Ultraschall Innenraumüberwachung) die am LIN hängen "offline" getestet. Keiner davon reagiert auf den IDSCAN. D.h. diese Module reden nicht mit jedem. Von der Stromaufnahme her gehen sie rasch nach dem einschalten in den sleep und wollen vermutlich sowas wie ein Keepalive/Ping vom BCM (LIN-Master) sehen bevor sie auf eine ID-Abfrage reagieren?
Einen wakeup-Puls (200 µs low) hast Du vor der Abfrage gesendet? Die Dinger sind darauf trainiert, sich energiesparend zu verhalten. Daher kann es gut sein, dass sie jeden anderen Traffic auf dem Bus erstmal ignorieren.
Ja, ich sende beim ID-SCAN für jede ID ein "BREAK, Delimiter, SYNC, PID". Ich versuche das mal ins Auto einzubauen bzw. mir anzusehen was das BCM macht. Ich könnte mir vorstellen das das Modul erst die Existenz vom Master sehen will bevor es auf etwas antwortet, oder es benötigt einfach eine INIT-Sequenz um sich z.B. scharf zu schalten.
So, also ich habe einen der Sensoren im Auto verbaut (+12V, GND und LIN an die dafür vorgesehenen Pins vom Dachhimmelkabelbaum) und meinen Sniffer dazu geklemmt. Zunächst sah ich nichts, keinerlei Aktivität. Am "LIN 2" an dem dieser Sensor laut Schaltplan hängt sonst nur noch die Akku-Sirene bei der erweiterten Alarmanlage.
Aktiviere ich das Alarmsystem in der Fahrzeugkonfiguration ("kodieren") dann erscheint aber was.
Natürlich habe ich gleich meinen Analyzer dran gehangen :-) Da sehe ich auf ID 0x12 die Teilenummer ("6G9N-15K607-CG").
0x01 - statisch 20 02 (90 ms)
0x08 - statisch 01 00 (70 ms)
0x12 - enthält die Teilenummer im multiframe-stil
0x23 - ist statisch 01 00 00 00
0x3D - kommt einmal vor mit 00 00 00 00 00 00 00 00. 3C kenne ich als SLEEP.
Wenn ich über meinen LIN-Sniffer periodischauf ID 0x01 die Payload "20 02" sende
SEND 01 20 02 EVERY 100
und dann mit HEADER 0x08 bzw. periodisch mit
POLL 0x08 500
Abfrage erhalte ich, meist den erwateten Payload
1
2304.952|01|2002|CLA|.|
2
2305.050|01|2002|CLA|.|
3
2305.060|01|2002|CLA|.|
4
2305.158|01|2002|CLA|.|
5
2305.168|01|2002|CLA|.|
6
2305.232|08|0100|CLA|..|
7
2305.266|01|2002|CLA|.|
8
2305.276|01|2002|CLA|.|
9
2305.374|01|2002|CLA|.|
10
2305.384|01|2002|CLA|.|
11
2305.482|01|2002|CLA|.|
12
2305.492|01|2002|CLA|.|
13
2305.590|01|2002|CLA|.|
14
2305.600|01|2002|CLA|.|
15
2305.698|01|2002|CLA|.|
16
2305.708|01|2002|CLA|.|
17
2305.736|08|0100|CLA|..|
18
2305.806|01|2002|CLA|.|
19
2305.816|01|2002|CLA|.|
20
2305.914|01|2002|CLA|.|
21
2305.924|01|2002|CLA|.|
22
2306.022|01|2002|CLA|.|
23
2306.032|01|2002|CLA|.|
24
2306.130|01|2002|CLA|.|
25
2306.140|01|2002|CLA|.|
26
2306.238|01|2002|CLA|.|
27
2306.248|08|UNANSWERED|---||
28
2306.248|01|2002|CLA|.|
29
2306.346|01|2002|CLA|.|
30
2306.356|01|2002|CLA|.|
31
2306.454|01|2002|CLA|.|
Wenn ich das Sendeintervall auf 200 ms erhöhe klappt es nicht mehr. Ich vermute das dem 01 20 02 innerhalb einer kurzen Zeit die Abfrage auf 0x08 folgen muss um beantwortet zu werden.
Jab, genauso scheint es zu sein. Ich habe meinen Sniffer um die Möglichkeit erweitert LIN-Master zu spielen und eine eigene ID zu senden und gleich im Anschluß eine abzufragen.
Das mit der Kombi "Sende auf ID 0x01 Payload 20 02" und "Empfange ID 0x08" ergibt nachvollziehbar den gewünschten Effekt:
1
> SEND 01 20 02 HEADER 08
2
3
15.008 | 01 | 20 02 | CLA | . |
4
15.008 | 08 | 01 00 | CLA | .. |
5
# OK
6
> SEND 01 20 02 HEADER 08
7
8
18.489 | 01 | 20 02 | CLA | . |
9
18.489 | 08 | 01 00 | CLA | .. |
10
# OK
11
> SEND 01 20 02 HEADER 08
12
13
20.537 | 01 | 20 02 | CLA | . |
14
20.537 | 08 | 01 00 | CLA | .. |
15
# OK
D.H. der 0x08 wird nur mit einem vorausgesendeten 0x01 beantwortet. Es scheint dabei sogar noch völlig egal zu sein wie die Payload von 0x01 ist, das 0x08 antwortet aktuell immer gleich.
Was jetzt nochmal spannend wird ist die Frage was 0x23 ist und wer es sendet? Und wie das im Falle der Aktivierung der Alarmanlage aussieht? Dann müsste das Alarmmodul ja regelmäßig gepollt werden, weil senden kann es ja nicht von selbst. Und dazu müsste es vorher sicher auch irgendwie "scharf" gemacht werden.
Ich habe mir auch die ID 0x12 mit der Teilenummer nochmal so angesehen und konnte dabei feststellen das es auch ein TP Index-1 Frame gibt, welches ich in den Scans nicht gefunden hatte. Dieses enthält mir noch unbekannte Werte, die nicht zu Teilenummer gehören: