Hallo zusammen, Ich versuche aktuell über einen STM32F4 mit mehreren, per Daisy Chain verbundenen Batterie-Management(BMS)-Chips zu kommunizieren. Direkt kommunizieren muss ich dabei nur mit einem der Chips über SPI, dieser ist wiederum mit den anderen über eine Daisy Chain verbunden (Der Daisy-Chain-Standard ist ein proprietärer Standard). Die Teilnehmer sind also: STM32-Host-uC: SPI Master BMS-Master-Chip: SPI Slave Weitere BMS-Chips: Per Daisy-Chain mit BMS-Master-Chip verbunden Die SPI-Kommunikation erfolgt über 5 Leitungen: MISO, MOSI, SCK und Chip Select, sowie ein /DATA READY (GPIO IN am STM32-Host-uC), welches dem Host-STM32 mit fallender Flanke anzeigt, dass ein Byte vom BMS-Master-Chip empfangen werden kann (Dieses kann vom BMS-Master-Chip selbst, oder von einem der Weiteren BMS-Chips sein) Ich muss dabei immer Befehle mit 4 Bytes bzw. 3 Bytes Länge senden und empfange in der Regel dann 4 Bytes als Antwort. Die 4 Bytes bestehen immer aus einer Adresse und Daten. Zusätzlich gibt es Sonderfälle: 1. Auf bestimmte Kommandos kommt erst eine 4 Byte Antwort, direkt danach allerdings noch eine definierte Anzahl weiterer 3 Byte Antworten. 2. Bei Fehlern wird automatisch eine 4 Byte Antwort gesendet durch den Batterie-Management-Chip. Bei den empfangenen Daten gibt es keine Start-/Stopbytes, Anzahl noch zu empfangener Bytes im Frame oder ähnliches. Erschwerend kommt noch hinzu, dass ich nach den Befehlen unterschiedliche Zeiten warten muss, bis ich den nächsten Befehl senden kann, und das relativ zügig empfangen werden muss, da der BMS-Master-Chip nur einen 4-Byte Buffer hat. Zusätzlich muss das Chip Select zwischen jedem Byte "gestrobed" werden (Direktes Auslesen von 4-bytes per DMA ist also beispielsweise auch nicht möglich). Ich habe mittlerweile eine Lösung, die halbwegs stabil läuft, mit der ich aber nicht wirklich zufrieden bin. Jetzt würde mich interessieren, ob jemand Literatur/Code/Best practises kennt für Protokolle, die ähnlich aufgebaut sind, so dass man sich hier Anregungen holen kann. Oder natürlich direkt Vorschläge, wie man das realisieren könnte, oder meine Lösung verbessern könnte. Eine Beschreibung meiner bisherigen Lösung habe ich angehängt. Bitte beachtet auch noch meinen Kommentar weiter unten.
:
Bearbeitet durch User
>und das relativ zügig empfangen >werden muss, da der Master-Chip nur einen 4-Byte Buffer hat. Wie bitte? Der Master gibt den Takt vor. Da muss gar nichts zügig gehen. Ich glaube du machst da irgendwas falsch. Deine Prosa oben kannst du dir übrigends an die Tapete kleben. Damit kann niemand was anfangen.
Danke schnelle Antwort. 1. Nein, ich mache da nichts falsch, es war aber zu knapp beschrieben: Die Teilnehmer sind: STM32 Host-uC: SPI-Master Master-Battery-Management(BMS)-Chip: SPI-Slave (Im ursprünglichen Text versehentlich nur als "Master-Chip" bezeichnet. Weitere BMS-Chips: Per Daisy-Chain mit dem Master-BMS-Chip verbunden Der STM32 Host-uC (SPI-Master) gibt den Takt vor, in meinem Fall 2MHz. Dieser ist mit dem BMS-Master-Chip per SPI verbunden. Dieser BMS-Chip ist über die Daisy-Chain mit allen anderen BMS-Chips verbunden und sendet neben seinen eignenen Daten auch die aller anderen BMS-Chips (Die er selbst über die Daisy-Chain empfängt) per SPI an den STM32 Host-Microcontroller. Der Master BMS-Chip hat für diese Daten einen 4-byte buffer. Die Daten kommen über die Daisy-Chain mit 500kHz. Natürlich gebe ich mit dem STM32 Host-Microcontroller den Takt vor, aber wenn ich die Daten nicht schnell genug aus dem Buffer des Master-BMS-Chip lese, werden sie dort überschrieben (Mit neuen Daten von der Daisy-Chain). Ich werde das oben im Text nochmal editieren, damit es klarer wird. 2. Ich hätte das Ganze gerne besser beschrieben, Auszüge aus dem Datenblatt gepostet etc. Leider ist das Datenblatt komplett als "Confidential" markiert und ich kann das nicht machen. Mir geht es aber auch nicht darum, dass mir hier jemand Code postet. Das Coden schaffe ich dann selbst. Mir geht es darum, ob jemand ähnliche Protokolle und dafür frei verfügbare Lösungen kennt, Literatur wie man solche Probleme lösen kann, etc. Oder eben sich meine Lösung in Prosa mal durchlesen will, um mir zu sagen ob das scheisse/verbesserungswürdig/was auch immer ist. Wenn du mir sagst, was genau an der Prosa unverständlich ist, kann ich mir gerne sehr viel Mühe geben, dass noch besser zu beschreiben. Ich habe hier leider keinen Drucker, kann es somit auch nicht "an die Tapete kleben".
>aber wenn ich die Daten >nicht schnell genug aus dem Buffer des Master-BMS-Chip lese, werden sie >dort überschrieben (Mit neuen Daten von der Daisy-Chain). In die Tonne treten diesen Schrott. Nicht vorhersehbare Timings führen eigentlich zwangsläufig zu einem instabilen Programm. Was ist wenn da mal ein Interrupt dazwischen funkt? >Leider ist das Datenblatt komplett als >"Confidential" markiert Noch ein Grund mehr diesen Schrott in die Tonne zu treten.
Diese Wahl habe ich nicht. Unvorhersehbar ist das Timing auch nicht. Der /Data Ready Pin zeigt an, wann ein Byte zur Verfügung steht. Die Daten kommen über die Daisy-Chain mit 500KHz, per SPI empfange ich mit 2 MHz. Somit ist es grundsätzlich kein Problem, alle Daten zuverlässig zu empfangen. Alle Timings werden im Datenblatt exakt beschrieben und von mir so auch eingehalten. IRQs funken da zwangsläufig dazwischen (CAN, Timer, ADC-DMA, USART), das führt jedoch zu keinen relevanten Verzögerungen (Dem GPIO IRQ um die fallende Flanke an /DATA READY zu erkennen weise ich die höchste Priorität zu, per SPI empfangen kann ich dann unabhängig vom Prozessor per DMA, dem DMA IRQ kann ich wiederum eine hohe Priorität zuweisen).
Wenn eines mit Sicherheit nicht supergeheim ist, ist es wohl die Information, um welchen Chip es sich hier handelt. Kann ja dann jeder selbst im chinesischen Internet auf die Suche nach einem Datenblatt gehen... ;-) SPI dasy chaining stelle ich mir ganz anders vor, als du es beschreibst. Üblicherweise bilden alle ge-dasy-chainten ICs ein entsprechend langes Schieberegister, das mit der vom Host kommenden Clock ausgelesen wird. "Timing" spielt dabei überhaupt keine Rolle.
Joe F. schrieb: > SPI dasy chaining stelle ich mir ganz anders vor, als du es beschreibst. Ich auch. Bei SPI dasy chaining wird das MOSI des nächsten mit MISO des Vorgängers verbunden. Will man z.B. aus 4 Chips mit dem 3. sprechen, schickt man an die anderen NOP-Befehle. NOP heißt, leite alle Bytes nur durch und mache nichts.
Peter D. schrieb: > NOP heißt, leite alle Bytes nur durch und mache nichts. Alle vom Master kommenden Bits werden sowieso durchgeleitet.
Joe F. schrieb: > Wenn eines mit Sicherheit nicht supergeheim ist, ist es wohl die > Information, um welchen Chip es sich hier handelt. > Kann ja dann jeder selbst im chinesischen Internet auf die Suche nach > einem Datenblatt gehen... ;-) Ich habe selbst nochmal nach Datenblättern geschaut. Zu meinem Chip wird man wohl nichts finden. Glücklicherweise gibt es einen sehr ähnlichen Chip, der, was die Daisy-Chain-Kommunikation betrifft, praktisch genauso funktioniert, den Intersil ISL94212. Hier das Datenblatt: http://www.intersil.com/content/dam/Intersil/documents/isl9/isl94212.pdf Ich benutze SPI in "Half-Duplex-Operation" (Datenblatt Seite 32 für Daisy-Chain), die Daisy-Chain-Funktionalität inkl. Beispiel-Daten wird ab Seite 34 beschrieben. > SPI dasy chaining stelle ich mir ganz anders vor, als du es beschreibst. > Üblicherweise bilden alle ge-dasy-chainten ICs ein entsprechend langes > Schieberegister, das mit der vom Host kommenden Clock ausgelesen wird. > "Timing" spielt dabei überhaupt keine Rolle. Dass die ge-dasy-chainten ICs ein entsprechend langes Schieberegister bilden ist grundsätzlich richtig. Wie bereits geschrieben handelt es sich bei dem Daisy-Chain-Protokoll um ein Proprietäres Protokoll, was exakt passiert lässt sich also nicht nachvollziehen. Jedenfalls ist diese Daisy-Chain gewissermaßen entkoppelt von der Host-uC/BMS-Master SPI Verbindung. Konkret: Ich sende einen entsprechenden 4-byte Befehl an den BMS-Master. Dieser sendet ihn weiter auf die Daisy-Chain wo der Befehl bis zum entsprechenden BMS-Chip wandert. Am BMS-Master kommen daraufhin 40 Byte an Daten über die Daisy-Chain zurück und werden in einem 4-byte buffer gespeichert. Jedes mal wenn ein Byte ankommt gibt es eine fallende Flanke an /DATA READY und ich muss dieses Byte per Host-uC aus diesem Buffer "raustakten". Das dies schnell genug passieren muss wird im Datenblatt auf Seite 32 auch beschrieben: "A 4 byte data buffer is provided for SPI communications. This accommodates all single transaction responses. Multiple responses, such as those that may be produced by a device detecting an error would overflow this buffer. It is important therefore that the host microcontroller reads the first byte of data before a 5th byte arrives on the Master device’s daisy chain port so as not to risk losing data."
Peter M. schrieb: > den Intersil ISL94212. Achso, das ist ja gar keine SPI-Chain, sondern ein separater Erweiterungsbus. Da hilft wohl nur, sich in das Protokoll gründlich einzulesen.
Tja, also einfach wird das nicht werden, den Ansprüchen dieses Chips gerecht zu werden. a) dieses bi-direktionale SPI interface ist nicht wirklich Standard. b) Zu verhindern, das der 4-byte Buffer überläuft ist eine Herausforderung. Wie viele von diesen Battery-Managern hast du denn? Ich denke mal, wenn die örtlich nicht besonders weit voneinander entfernt sind, wäre es einfacher, alle Battery-Mangager im Standalone-Mode zu betreiben. Du würdest dafür alle an einen ganz normalen SPI Bus hängen (CLK, MOSI, MISO + entsprechend viele CS_N). Alle timingkritischen Punkte, die mit diesem eigentümlichen Dasy-Chain Interface zusammen hängen, entfallen dann.
:
Bearbeitet durch User
Joe F. schrieb: > Ich denke mal, wenn die örtlich nicht besonders weit voneinander > entfernt sind, wäre es einfacher, alle Battery-Mangager im > Standalone-Mode zu betreiben. > > Du würdest dafür alle an einen ganz normalen SPI Bus hängen (CLK, MOSI, > MISO + entsprechend viele CS_N). > > Alle timingkritischen Punkte, die mit diesem eigentümlichen Dasy-Chain > Interface zusammen hängen, entfallen dann. Noch viel sinnvoller wäre, einfach selbst die daysy chain zu betreiben, denn dann blieben alle Vorteile der daysy chain Architektur erhalten. Nur die Nachteile des Konstrukts mit dem zusätzlichen BMS master würden ausgemerzt. Und damit eindeutig nachgewiesen, dass der nicht nur völlig "über" ist, sondern sogar kontraproduktiv... Ich frage mich ernsthaft, wie man überhaupt auf die Idee kommen kann, das Ding einsetzen zu wollen...
c-hater schrieb: > Joe F. schrieb: > >> Ich denke mal, wenn die örtlich nicht besonders weit voneinander >> entfernt sind, wäre es einfacher, alle Battery-Mangager im >> Standalone-Mode zu betreiben. >> >> Du würdest dafür alle an einen ganz normalen SPI Bus hängen (CLK, MOSI, >> MISO + entsprechend viele CS_N). >> >> Alle timingkritischen Punkte, die mit diesem eigentümlichen Dasy-Chain >> Interface zusammen hängen, entfallen dann. > > Noch viel sinnvoller wäre, einfach selbst die daysy chain zu betreiben, > denn dann blieben alle Vorteile der daysy chain Architektur erhalten. > > Nur die Nachteile des Konstrukts mit dem zusätzlichen BMS master würden > ausgemerzt. Und damit eindeutig nachgewiesen, dass der nicht nur völlig > "über" ist, sondern sogar kontraproduktiv... > > Ich frage mich ernsthaft, wie man überhaupt auf die Idee kommen kann, > das Ding einsetzen zu wollen... Die Platinen sind bereits beim Fertiger, dies sind also keine Optionen. Ich glaube auch nicht, dass einer von beiden Vorschlägen funktionieren würde: Der Stack besteht aus 288 LiPo-Zellen (144s2p, 12 BMS-Chips, Pead-Entladestrom ca. 180 A, Peak-Ladestrom 80 A). Zusätzlich zu erheblichen EMV-Störungen ist auch eine gewisse räumliche Distanz zwischen den einzelnen Platinen zu überbrücken. Die Daisy-Chain-Leitung dagegen ist eine differentielle Zweidraht-Leitung. Zusätzlich ist, wie im Datenblatt zu sehen, an jedem Frame eine CRC4-Checksum, um die Integrität der Daten festzustellen, und Kommunikations-Fehler werden von den BMS-Chips erkannt. All dies würde bei einer eigenen SPI-Daisy-Chain entfallen, und ich bezweifle dass diese EMV-resistent genug wäre (Getestet habe ich es nicht). Der BMS-Master-Chip ist übrigens auch kein zusätzliches Konstrukt sondern überwacht seinerseite 12 Zellen. Siehe Datenblatt Seite 1.
Peter M. schrieb: > Die Platinen sind bereits beim Fertiger, dies sind also keine Optionen. Keine Option? Statt des BMS-Master bestückt man einfach ein paar Drahtbrücken zwischen dessen Pads. Das kriegt jeder Fertiger recht problemlos hin... > Die Daisy-Chain-Leitung dagegen ist eine differentielle > Zweidraht-Leitung. Aha. Dieses Detail hättest du vielleicht im allerersten Posting erwähnen sollen? OK, ich gebe zu, dass da auch nirgendwo stand, dass es sich um eine SPI-daysy chain handelt, sondern nur, dass sie irgendwie proprietär wäre. Aber OK. Dann sind's eben nicht nur ein paar Drahtbrücken, sondern ein Sub-PCB mit Diff-Treibern und Empfängern... > Zusätzlich ist, wie im Datenblatt zu sehen, an jedem > Frame eine CRC4-Checksum, um die Integrität der Daten festzustellen, und > Kommunikations-Fehler werden von den BMS-Chips erkannt. All dies würde > bei einer eigenen SPI-Daisy-Chain entfallen Wieso? Seit wann kann ein ARM keine CRC's mehr berechnen? Ich meine: das können sogar die kleinen AVRs, mit denen ich normalerweise meist auskomme, völlig problemlos. Und bei CRC4 spielt die "Proprietärität" nicht mal mehr eine nennenswerte Rolle, die paar möglichen Varianten für das Generator-Polynom und Startwert hat man beim reverse engineering schneller ausgeklingelt, als dein Fertiger ein PCB-Exemplar herstellen kann... > Der BMS-Master-Chip ist übrigens auch kein zusätzliches Konstrukt > sondern überwacht seinerseite 12 Zellen. So what? Einfach einen Slave mehr nehmen und alles ist gut. Ohne jede Änderung des Layouts der hochwichtigen und praktisch ja wohl bereits in 100.000er Stückzahlen gelieferten Platine. Denn wären es wesentlich weniger, würde man das offensichtliche Fehldesign einfach abschreiben und von vorn beginnen...
Peter M. schrieb: > Der BMS-Master-Chip ist übrigens auch kein zusätzliches Konstrukt > sondern überwacht seinerseite 12 Zellen. Siehe Datenblatt Seite 1. c-hater schrieb: > Statt des BMS-Master bestückt man einfach ein paar > Drahtbrücken zwischen dessen Pads. ;-) c-haters Vorschlag macht die Sache nur wesentlich komplizierter. Das Protokoll der Dasy-Chain ist ja komplett undokumentiert. Das wird ebenfalls bidirektional sein, und die Clock muss im Protokoll auch noch eincodiert sein. Das möchte man nicht reverse-engineeren. Die Aufgabe besteht jetzt halt darin, das zwar etwas ungewöhnliche, jedoch gut dokumentierte bidirektionale SPI Protokoll des BMS-Masters zu implementieren.
:
Bearbeitet durch User
Joe F. schrieb: > Die Aufgabe besteht jetzt halt darin, das zwar etwas ungewöhnliche, > jedoch gut dokumentierte bidirektionale SPI Protokoll des BMS-Masters zu > implementieren. Exakt. Danke für die vielen Vorschläge, aber das hardwaretechnisch zu ändern wird nicht funktionieren. Vielleicht hätte ich des von Anfan an ausführlicher schildern müssen, ich bin gar nicht auf die Idee gekommen, dass jemand die Hardware ändern will: Die SPI-Verbindung vom Host-uC zum BMS-Master ist galvanisch getrennt. Das ist nötig, da die ISLs selbst von den Zellen versorgt werden, der Mikrocontoller hingegen vom galvanisch getrennten LV-System. Sollte, wie von euch vorgeschlagen, der Mikrocontroller jetzt mit den anderen ISL Slaves direkt kommunizieren, bedarf es dazu einer gemeinsamen Masse. Direkte Verbindung der negativsten Spannungen eines 12s Stack in einem 144s (also 12x12s) System ist eher weniger zielführend. Man müsste daher also die galvanische Trennung des SPIs weitere 11x ausführen. Hinzu kommen die Probleme mit EMV bei einer reinen SPI-Daisy-Chain über mehrere Platinen und gewisse räumliche Abstände hinweg. Und dass es zeitlich für uns gar nicht möglich ist. Meiner Meinung nach ist das auch kein Fehldesign sondern sind hier die Vorgaben des Herstellers hardware-technisch umgesetzt und müssen jetzt eben noch in Software implementiert werden. Grundsätzlich läuft es ja schon halbwegs. Aktuell betreibe ich den SPI noch nicht Interrupt-gesteuert/über den DMA. Ich denke über DMA macht auch nicht viel Sinn, ich könnte ja immer nur ein Byte auf einmal senden, da ich beim Befehle senden das Chip Select Signal "stroben" muss (High->Low nach jedem gesendeten Byte) und beim Empfangen mit /Data Ready synchronisieren muss? Die Daten schreibe ich einfach in ein globales Array, welches dabei immer inkrementiert wird, bis die Anzahl der erwarteten Daten empfangen ist. Ist dies der Fall, wird der Index wieder auf 0 gesetzt und die Daten werden ausgewertet. Die ankommenden Daten takte ich aktuell noch direkt im GPIO Interrupt des /Data Ready Pins raus (immer ein Byte), der auf die fallende Flanke konfiguriert ist. Wenn es hilft, könnte ich versuchen ein paar Code-Abschnitte zu posten, ist ziemlich viel, aber vllt. kriege ich es aufs Wesentliche reduziert? Hat sonst noch jemand Vorschläge, softwaretechnisch?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.