RS-485 im VM

Beiträge
285
Es geht um die Steuerung der elektrischen Komponenten im Velomobil per RS-485.
Ziel ist es, den störanfälligen und unübersichtlichen Drahtverhau zu lichten, der momentan Standard ist, und durch ein Bussystem zu ersetzen.

Als physikalischer Layer soll RS-485 im Half-Duplex Mode dienen.

Da im Ursprungsthread schon einige gute Ideen und Ansätze dargelegt wurden, wäre es vielleicht ganz gut, wenn, wer mag, seine Gedanken hier noch mal zusammenfasst (oder einfach reinkopiert ;)).
 
Zuletzt bearbeitet:
Dann warten wir mal, welche Vorschläge @nikolauzi hat.
Ja, Wink mit dem Zaunpfahl verstanden;)

Also mal eine kurze Zusammenfassung, was ich bei mir wie umgesetzt habe, als Diskussionsgrundlage:
1. wichtigster Punkt ist der Bus, da habe ich mich des Physical Layers vom RS422/485 bedient.
Gründe: Mit dem MAX487 gibt es einen günstigen, störunanfälligen und sparsamen (120µA) Treiber. Hatte mir eine Stange für ein paar Euro bestellt. CAN braucht 10-50 mal mehr Strom, fällt also flach.
2. Protokoll: Das RS422/485 Protokoll habe ich nicht übernommen, wollte was praktisches und einfaches, ergo vier Byte:
0x80 (Sync), Service, Option, Checksum (=Service+Option+0xea)
0x80 (LSB first) ergibt mit dem Startbit 8 Bits, die mißt ein Timer, teilt das durch 8 und gibt das als Timebase an die UART für die folgenden 3 Byte -> Autosync
3. Controller: ist ziemlich egal, Hauptsache Timer und UART, ich habe einen STM8S103 genommen, gab da mal 10 Platinen für 9€ bei Ebay, Atmel tut's da aber auch locker.
4. Bus Struktur:
Theoretisch Multi Master/Multi Slave machbar, Single Master/Multi Slave ist bei mir aktuell umgesetzt, paßt ganz gut soweit.

5. Services
Service/Bezeichnung/Option (mein Vorschlag):
08 Brake 0x0f
10 Horn 0x0f
18 Blinker lf,lmid,lr,laux, rf,rmid,rr,raux (als Option, falls man später z.B, mal die Blinker rund um VM laufen lassen will, praktischerweise ist der Standart 0xf0, 0x0f oder 0xff (Warnblinker)
20 Light tfl_l,tfl_r,abl,fl,back,back_l,back_r (d.h. z.B. daß beim Blinker RR (rear right) auch das Rücklicht RR ausgehen könnte, das zentrale Rücklicht aber an bleiben würde)
30 light position (servo), 8bit (Leuchtweiteneinstellung/Fernlicht)

Dx 0xXX (aux functions, Steuersignale z.B. für Unterbodenbeleuchtung, Musik, Scheibenwischer & Co)

Diagnose (0xEX ist eine Diagnosenachricht an einen Knoten, d.h. der Rest hält den Mund, 0xFX ist die Antwort des Knotens auf die Diagnosenachricht, z.B. zur zyklischen Abfrage, ob alle Knoten im Bus aktiv sind, ob es draußen dunkel ist, oder vorne die Luft nahe 0°. Anmerkung: das ist nicht schön gelöst, es müßte noch ein Service Kommando rein für solche Infos geben, à là: Weiß jemand, ob es dunkel ist? Ob es kalt ist? Etc.)
E0/F0 Req/Diag steer
E1/F1 Req/Diag back
E2/F2 Req/Diag front
E3/F3 Req/Diag center

E8/F8 Req/Diag aux1 Unterboden Beleuchtung
..
EF/FF Req/Diag Node 15
Aktuell wäre also 16 Knoten möglich.

6. Service Handling:
Die Services werden in einem festen Zeitraster vom Master gesendet, jeder Knoten hält den Service nur so lange aktiv, bis eine gegenteilige Serviceanfrage kommt, oder das Zeitraster um 50% überschritten wird. Dadurch geht z.B. der Blinker im Zweifelsfall automatisch aus. Fehlt die Knotendiagnose (0xdx) für 500ms, geht der Knoten in den Limp Home Modus, d.h. als Fail Safe wird z.B. das Rücklicht eingeschaltet, wenn der Knoten vom Netz getrennt wird.
Bekommt der Knoten am Tiller von einem Knoten keine Antwort auf eine Knotendiagnose, geht dort die MIL Lampe an als Warnung für den Fahrer, daß ein Knoten fehlt.

7. Baudrate: habe da mal einfach 32kbaud genommen, d.h. eine Nachricht (4 Byte) dauert etwa 1.2ms, was soweit ganz ok scheint. Ist aber eh wurscht, das System adaptiert sich ja eh, d.h. man könnte für z.B. Crash Sensor einfach temporär auf bis zu 250kBaud springen.

Soviel mal als grober Überblick, ich guck mal, was mir noch so einfällt oder was ich vergessen habe;)
 
Wow - soviel Gehirnschmalz ist da notwendig - ich kann natürlich nur maximal 10% davon nachvollziehen.
Naja, vieles davon sind Abkürzungen, sonst wäre der Text noch viel länger. Bei den Blinkern dürfte lf, lmid, lr und laux z.B. "links vorn", "links mitte", "links hinten" und "links zusatz" bedeuten.

@nikolauzi: Wo ist denn in Bezug auf Limp-Home der Unterschied zwischen einer ausbleibenden Serviceanfrage und einer ausbleibenden Diagnoseabfrage? Bei Fernlicht oder Hupe sollte man sicher nicht erst die halbe Sekunde bis zur nächsten Diagnoseabfrage warten, bis man abschaltet, beim Blinker dagegen klingt es für mich arg schnell, den schon nach Ausbleiben einer einzigen Serviceanfrage abzuschalten.
 
Hallo @nikolauzi, das Protokoll wirkt gut durchdacht. Ich denke auch, niemand braucht für sowas mehr als vier Bytes (frei nach Bill Gates ..).
Obwohl man das, vielleicht mit ein paar kleineren Anpassungen, direkt so verwenden könnte (und das machst Du ja offensichtlich auch schon erfolgreich), tun sich da bei mir noch Fragen auf.

Z.B. das Auto-Bauding: Läuft das so, dass der Master eine Taktrate vorgibt, und alle Knoten stellen ihre Baudrate darauf ein ?
Was für einen Vorteil hätte man gegenüber einer festen Baudrate, die so gewählt ist, dass sie bei der gewählten Leitungslänge und Topologie zuverlässig arbeitet ?
Was war Deine Überlegung, als Du das implementiert hast ? Obwohl es mit einem Timer sicherlich nicht schwer zu implementieren ist, kostet es Dich immerhin ein Byte (das Sync - Byte).

Die Identität der Knoten, also der Service, den er bedienen soll. Ein Knoten muss in Deinem Protokoll genau wissen, ob er z.B. Blinker lf, lmid, lr, laux, rf, rmid, rr oder raux ist. Es gibt verschiedene Möglichkeiten, das einzustellen:
  1. Für jeden Service eine unterschiedliche Firmware (also mit unterschiedlichen #defines o.ä. kompiliert)
  2. Lötbrücken
  3. Dip Switches
  4. Nachträglich von aussen oder per spezieller Service-Message programmierbar
  5. Unterschiedliche Platinen für elektrisch unterschiedliche Funktionen (Blinker, Hupe, Licht ...) + eine der Massnahmen 1 - 4
Welche Möglichkeit hast Du gewählt ?
 
Ja, Wink mit dem Zaunpfahl verstanden;)

Also mal eine kurze Zusammenfassung, was ich bei mir wie umgesetzt habe, als Diskussionsgrundlage:
;)

Das sieht nach einem spannenden Projekt aus.
Dazu fällt mir ein:
Du kannst erheblich Energie sparen, wenn Du die Busteilnehmer (vermutlich alles Mikrocontroller) periodisch in den Schlafmodus versetzt.
Bei vielen Teilnehmern hast Du mit RS485 das Problem, dass Du Kollisionen auf dem Bus nicht erkennen kannst. Das ist bei CAN einfacher.
Solange es nur einen Busmaster gibt welcher die Kommunikation einleiten darf, ist das aber kein Problem.
CAN Treiber benötigen auch weniger externe Komponenten als RS485 Treiber.
Zum Thema Knotenidentität fällt mir ein:
Für die Kodierung von z.B. 8 verschiedenen Knotentypen (Blinker, Aktuator, Tempsensor, ...) benötigst Du eigentlich 3 digitale IO-Pins.
Solltest Du soviele Pins nicht investieren wollen, so kannst Du auch einen Analogeingang verwenden und vor diesen einen Spannungsteiler setzen.
Die vom Spannungsteiler vorgegebene Analogspannung gibt dann den Knotentyp vor. Zur Festlegung brauchst Du nur zwei feste Widerstände.

Die Telegramme würde ich als C-structs definieren mit einem Typfeld ganz am Anfang.
So dokumentierst Du Dein Protokoll automatisch und erleichterst es anderen, kompatible Sensoren zu entwickeln.

Just my five cents.
 
Bei vielen Teilnehmern hast Du mit RS485 das Problem, dass Du Kollisionen auf dem Bus nicht erkennen kannst. Das ist bei CAN einfacher.
Solange es nur einen Busmaster gibt welcher die Kommunikation einleiten darf, ist das aber kein Problem.
Es ist ohne weiteres möglich, mit einer geeigneten Beschaltung Kollisionen auf dem RS-485 Bus zu erkennen, wenn man das möchte.
Ich habe am Ende ein Beispiel aus der ESP-32 Dokumentation angehängt. Das geht aber natürlich mit jedem uC.
CAN Treiber benötigen auch weniger externe Komponenten als RS485 Treiber.

Man sollte die Versorgungsspannung am Treiberchip mit einem kleinen Kondensator gegen Masse puffern. Sonst braucht man eigentlich keine weiteren Komponenten. Oder habe ich da jetzt was vergessen ? (Den Terminierungswiderstand braucht man nur einmal am Anfang der Leitung (wahrscheinlich beim Master, und am Ende der Leitung.)

Zum Thema Knotenidentität fällt mir ein:
Für die Kodierung von z.B. 8 verschiedenen Knotentypen (Blinker, Aktuator, Tempsensor, ...) benötigst Du eigentlich 3 digitale IO-Pins.
Es genügt nicht, den Typ (Blinker) zu kodieren, der Knoten muß auch wissen, welcher Blinker er ist (links/rechts || vorne/mitte/hinten).
Ich würde mal ein komplettes Byte dafür einplanen (so wie es @nikolauzi ja auch macht.)

Die Telegramme würde ich als C-structs definieren mit einem Typfeld ganz am Anfang.
So dokumentierst Du Dein Protokoll automatisch und erleichterst es anderen, kompatible Sensoren zu entwickeln.

(y)
 

Anhänge

  • esp32-collision-detection.png
    esp32-collision-detection.png
    96,2 KB · Aufrufe: 18
Z.B. das Auto-Bauding: Läuft das so, dass der Master eine Taktrate vorgibt, und alle Knoten stellen ihre Baudrate darauf ein ?
Was für einen Vorteil hätte man gegenüber einer festen Baudrate, die so gewählt ist, dass sie bei der gewählten Leitungslänge und Topologie zuverlässig arbeitet ?
Man braucht nur den Master umzuprogrammieren, wenn man's ändern will. :) Genauigkeit der Taktgeneratoren in den verschiedenen Controllern spielt so auch keine große Rolle mehr.
Die Identität der Knoten, also der Service, den er bedienen soll. Ein Knoten muss in Deinem Protokoll genau wissen, ob er z.B. Blinker lf, lmid, lr, laux, rf, rmid, rr oder raux ist.
Die Diagnose klingt nach einem anderen Konzept, wahrscheinlich ein Knoten im Bug, einer im Heck, und zwei andere noch irgendwo dazwischen.
Da gibt es keinen Knoten, dem man sagen könnte "Du bist der linke vordere Blinker", sondern der im Bug muss auf alle Nachrichten für Fernlicht, Abblendlicht, Tagfahrlicht links/rechts und Blinker links/rechts reagieren und jeweils einen entsprechenden Ausgang schalten, und bei der Leuchtweiteneinstellung schaltet er nicht ein/aus, sondern macht vermutlich eine Analogspannung oder eine Pulsweite für einen Servo.

(Und mir wird gerade die Hälfte der Antwort auf meine obige Frage klar. Diagnose bezieht sich auf den Knoten, also "Bug" oder "Heck", Serviceanfrage bezieht sich auf den einzelnen Verbraucher, also "Blinker links hinten" oder "Rücklicht", was ja beides am Knoten im Heck hängt. Insofern gibt's einen Unterscheid dazwischen, einen einzelnen Verbraucher in einen Default-Zustand zu versetzen oder den ganzen Knoten in den Limp-Home-Modus, in welchem der z.B. wiederum alle seine Verbraucher in ihre Default-Zustände versetzt.)
 
Eine andere Idee: Wie wäre es mit einem Funkmodul wie z.B. dem CC1101?
Dann brauchst Du gar keine Datenleitungen zu verlegen, sondern nur die Versorgungsspannung als Ring oder Baum zu verlegen.
Du musst Dich dann auch nicht auf irgendwelche speziellen Datenstecker festlegen.
Kabelbrüche und Kontaktkorrosion sind dann auch kein Problem mehr.

Die Kommunikation per CC1101 erfolgt Halbduplex (entweder senden oder empfangen). Die Reichweite genügt selbst bei minimaler Leistungseinstellung vollkommen.
Fertig aufgebaute Module gibt es günstig bei verschiedenen Anbietern: https://www.amazon.de/Laqiya-CC1101-Funkübertragung-Antenne-Transceiver/dp/B075PFQ57G/
 
Die Diagnose klingt nach einem anderen Konzept, wahrscheinlich ein Knoten im Bug, einer im Heck, und zwei andere noch irgendwo dazwischen.
Da gibt es keinen Knoten, dem man sagen könnte "Du bist der linke vordere Blinker", sondern der im Bug muss auf alle Nachrichten für Fernlicht, Abblendlicht, Tagfahrlicht links/rechts und Blinker links/rechts reagieren und jeweils einen entsprechenden Ausgang schalten, und bei der Leuchtweiteneinstellung schaltet er nicht ein/aus, sondern macht vermutlich eine Analogspannung oder eine Pulsweite für einen Servo.

(Und mir wird gerade die Hälfte der Antwort auf meine obige Frage klar. Diagnose bezieht sich auf den Knoten, also "Bug" oder "Heck", Serviceanfrage bezieht sich auf den einzelnen Verbraucher, also "Blinker links hinten" oder "Rücklicht", was ja beides am Knoten im Heck hängt. Insofern gibt's einen Unterscheid dazwischen, einen einzelnen Verbraucher in einen Default-Zustand zu versetzen oder den ganzen Knoten in den Limp-Home-Modus, in welchem der z.B. wiederum alle seine Verbraucher in ihre Default-Zustände versetzt.)

Ok, ich war automatisch davon ausgegangen, dass Service == Knoten ist. Aber das muß natürlich nicht so sein.
Wenn ich mir einen Knoten vorstelle, der einen Kellermann steuern soll, dann würde der ja zum Beispiel drei Services beinhalten (Rücklicht, Bremslicht, Blinker).
Also macht es tatsächlich Sinn, Service und Knoten unabhängig zu definieren.

Vielleicht kann @nikolauzi da ja noch mal ein bischen Licht in die Sache bringen ;)

Trotzdem muß man die Identität der Knoten und die Verortung der Services in den Knoten festlegen können.
 
Zuletzt bearbeitet:
Es genügt nicht, den Typ (Blinker) zu kodieren, der Knoten muß auch wissen, welcher Blinker er ist (links/rechts || vorne/mitte/hinten).
Ich würde mal ein komplettes Byte dafür einplanen (so wie es @nikolauzi ja auch macht.)

In dem Fall macht es Sinn, für jeden Knotentyp eine eigene Firmware zu erstellen.
Das geht auch per Skript mit einer Konstante per Kommandozeilenoption (-D für gcc).
Also z.B. gcc -DNODE_TYPE=note_type_blinker_vorne_links ...

Mit einem enum für die Knotentypen:

enum {
note_type_none = 0,
note_type_blinker_vorne_links,
...
} note_type;

und dann im Programm:
switch (note_type) {
case note_type_blinker_vorne_links: run_blinker_vorne_links(); break;
...

default: assert(0); break
}
Aber das ist vermutlich eh klar.
 
Sorry, das ich nochmal Off Topic quatsche.

Habe nur gerade nach Funkmodulen gesucht und etwas sehr interessantes gefunden.
Für knapp 4,40€ bekommt man ein Bluetooth 5.0 Low Energy Modul mit integriertem 32-Bit Cortex M3 Prozessor:
D.h. diese Module lassen sich direkt vom Smartphone aus steuern.
Man braucht also nichtmal eine Hauptplatine, Anzeigen, Bedienelemente oder ähnliches zu bauen sondern kann eine Android App schreiben und bekommt Visualisierung und Bedienelemente kostenlos!
Sowas könnte sich evtl. sogar verkaufen.. :unsure:
 
Die Funkmodule interessieren hier nicht ... Das Thema ist hier RS-485 und nur das bitte.
 
Richtig, Knoten ist die physische Hardware, hatte ich einfach einmalig mit einem EEPROM Eintrag je HW definiert. Es gibt nur eine SW, die anhand des EEPROM Eintrags erkennt, wo sie eingebaut ist und wie sie dann auf welche Services reagieren muß(y)(Z.B. 2812 Eindraht bedienen, Servo PWM generieren, Links blinken und linkes Bremslicht dabei ausschalten, etc.)
Die variable Übertragungsrate habe ich wegen dem RC Oszillator genommen, Quarz braucht deutlich mehr Strom.
Der STM8S braucht ohne Sleepmode ca. 3mA, was ich als ok erachte, das ganze Netz in Summe ca. 50mA, inkl. aktiver Statusanzeige am Tiller (5x2812) und Servo.
 
@nikolauzi: Magst Du noch was zur Verkabelung und den Steckern (oder anderen Verbindern) schreiben?
Sternförmig, oder Master in der Mitte einer linearen Verdrahtung? So furchtbar viele Anschlüsse am Datenbus hast Du ja nicht, Master und vier Knoten.
Werden die ganzen Endverbraucher an den Knoten angesteckt oder -geklemmt, oder hängen die auf 12V und werden im Knoten zur Masse durchgeschaltet (oder andersherum)?
 
Also mal eine kurze Zusammenfassung, was ich bei mir wie umgesetzt habe, als Diskussionsgrundlage:

Wenn ich versuche, mir das mal vorzustellen, sieht Dein System vielleicht so aus:
  • Es besteht aus einer guten Handvoll Knoten.
  • Jeder der Knoten bietet eine ganze Reihe verschiedener Services an.
  • Es gibt keine "kleinen" Knoten mit nur 1 oder 2 Services, z.B. wirst Du keinen einzelnen Knoten haben, der nur 1 Lampe schaltet.
  • Der Knoten beim Tiller fungiert als Master.
    • Er kümmert auch auch um Tasteneingaben.
  • Die Knoten haben eine ihnen über die Firmware zugeordnete Identität.
    • Der Master weiß, welche Knoten er hat und kann z.B. entsprechend Diagnosenachrichten verschicken.
    • Der Master weiß nicht, auf welchem Knoten ein bestimmter Service läuft. Er adressiert die Services direkt.
Da Du wenige Knoten zu haben scheinst, gehen von den einzelnen Knoten immer noch relativ viele Leitungen ab, die durchaus auch mal länger sein können.
Die Topologie des Netzes ist einfach, und es gibt nicht viele Verbindungsstellen, da es nicht viele Knoten gibt.

Korrigiere mich mich gerne, falls ich hier schon von falschen Annahmen ausgehe.
 
Zurück
Oben Unten