Geräteerkennung auf einfachem Bus

Ich stehe derzeit vor folgendem Problem: Es gibt ein System, das aus einem Master-Gerät und einer Reihe von Slave-Geräten besteht (alle diese Geräte haben winzige MCUs). Sie kommunizieren mit einem benutzerdefinierten Protokoll, das auf seriellen Kabeln basiert (sieht Modbus ziemlich ähnlich). Alle Slave-Geräte müssen innerhalb eines Busses eindeutige IDs haben, damit das Master-Gerät jeden dieser Slaves ansprechen kann. Derzeit bin ich gezwungen, diese IDs in jedes Slave-Gerät fest zu codieren. Mein Ziel ist es, alle diese Geräte mit derselben Firmware zu flashen, daher sollten keine fest codierten IDs verwendet werden, damit dies möglich ist. Ich denke an ein Master-Gerät, das all diesen Geräten eindeutige Adressen zuweisen kann, aber ich kann nicht herausfinden, wie das geht. Kann mir jemand eine Idee oder ein Konzept geben, wie ich mein Kommunikationsprotokoll erweitern kann, damit dies möglich ist? Vielleicht kann mir jemand ein Beispiel geben?

Dies ist natürlich ein sehr häufiges Konstruktionsproblem. Wenn es eine "heilige Gral"-Lösung gibt, bin ich mir nicht sicher, ob es viele einzigartige ID-ICs auf dem Markt geben würde. Würde mich aber über eine Lösung freuen.
Sie können ein vorserialisiertes EEPROM hinzufügen, wenn Sie nur wenig PCB-Fläche und einen I2C- oder SPI-Port zur Verfügung haben. So etwas wie ein 24AA02E48 .
Verarbeiten Ihre MCUs das ModBus-ähnliche Protokoll in Software? Wenn dies der Fall ist, können Sie ModBus beim Einschalten erst nach einer Aufzählungsphase seines eigenen Protokolls verwenden. Slaves benötigen eine eindeutige ID, setzen Sie also einen DS2401 48-Bit-Seriennummer-IC auf jeden. Dann implementieren Sie ein einfaches Protokoll mit Open-Drain-Slaves unter Verwendung von Read Fallaway (über 48 serielle Lesevorgänge geben Slaves eine 0 als Low, 1 als Hi-Z zurück, überprüfen dann die Leseleitung und setzen diese Runde aus, wenn sie sich von was unterscheidet Sie haben geschickt). Lesen Sie weiter 48-Bit-Zahlen vom Bus und weisen Sie Adressen zu, bis alles erledigt ist. Ich kann das erweitern, aber zuerst wird Ihr Hw/SW es ​​zulassen?

Antworten (4)

Um diese Art der dynamischen Adressierung auf einem gemeinsamen Bus durchzuführen, müssen Sie letztendlich eines von zwei Dingen haben:

  • ein sehr kleiner Adressraum, sodass Sie ihn effizient mit Brute-Force-Suche durchsuchen können
  • eine Art Kollisionserkennungs-/Managementsystem

Wenn Sie keines dieser beiden Dinge haben, müssen Sie die Adressen in den Master- und Slave-Geräten fest codieren.

Der Grund dafür ist, dass, wenn Sie einen Adressraum (der Größe N) haben, der zu groß ist, um effizient zu suchen, indem Sie alle N Adressen schrittweise durchlaufen, jeder optimierte Suchalgorithmus, der die Adresse in weniger als N Schritten finden könnte, die Möglichkeit beinhalten muss von mehr als einem Slave, der gleichzeitig eine Antwort sendet. Wenn die physikalische Schicht mit dieser Situation nicht umgehen kann, haben Sie leider Pech. Wenn die physikalische Schicht Kollisionen erkennen kann, gibt es viele Optionen, z. B. eine zufällige Wiederholungsverzögerung, wenn eine Kollision auftritt (Ethernet), oder die Verwendung von etwas wie CAN-Bus, bei dem Kollisionen kooperativ verwaltet werden.

Kollisionen werden anhand der Prüfsumme für jede Nachricht erkannt. Oder meinst du so etwas wie CSMA-Methoden?
@vadimchik Vorausgesetzt, der physische Bus (Treiber usw.) kann die Kollisionen bewältigen, könnten Sie ein System wie Ethernet implementieren. Viele Busse sind jedoch nicht für Kollisionen ausgelegt und können die Fahrer beschädigen.
Physikalisch sind alle Slave-TX-Pins Open-Drain-Pins, sodass Kollisionen die Hardware nicht beschädigen sollten
@Vadimchik Das Problem mit der Kollisionserkennung für diese Technik ist, dass die Kollision möglicherweise nicht erkannt wird. Wenn beide Slaves dasselbe Paket fast zur gleichen Zeit senden, was der Fall wäre, wenn Sie keine anständige Methode zum Erstellen eines zufälligen Pakets haben, überlagern sie sich auf der Signalleitung und der Master wird es nicht bemerken.
@Vadimchik Und das Erstellen verschiedener Zufallszahlen in einer Reihe von Mikros, die gleichzeitig gestartet wurden, ist keine einfache Angelegenheit.

Ich habe vor einigen Jahren ein System dafür entwickelt.

Es funktionierte wie im Schema unten. Ein gemeinsamer Kommunikationsring wurde eingerichtet.

Jeder Slave hat einen Logikschaltkreis, der anfänglich oder beim Zurücksetzen des Systems den Ring blockiert.

schematisch

Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan

Beim Start sendet das Master-Gerät ganz oben einen „Who_Is_There“-Befehl aus.

Befehlsstruktur [CODE][(ID1,ID1)][END]

Da die Schalter anfangs offen sind, hat nur der erste Slave diesen Befehl erhalten.

Der Slave kopiert das Befehlspaket und fügt der Liste die ID seines Funktionstyps hinzu und sendet dann den Befehl weiter. Der Slave erinnert sich an den Index des Standorts, dem er seine Typ-ID als seine Ringadresse hinzugefügt hat. Einmal gesendet, schließt der Slave seinen Ringschalter. Es ignoriert dann jeden weiteren "Who_Is_There"-Befehl bis zum nächsten Zurücksetzen.

Der nächste Sklave in der Reihe macht dasselbe ... und weiter unten in der Kette.

Schließlich erhält der Master den Befehl mit einer Liste von Gerätetypen in der Reihenfolge zurück, in der sie auf dem Ring gefunden wurden, und kennt somit die ID jedes Slaves.

Danach adressiert der Master einfach Pakete an den entsprechenden Slave. Da alle Schalter zu diesem Zeitpunkt geschlossen sind. Alle hören den Befehl, aber nur der Angesprochene antwortet.

Ferner: In meiner speziellen Anwendung basierte das System auf einer Backplane, wobei Platinen für eine bestimmte Produktkonfiguration bestückt werden können oder nicht. Daher wurden die Schaltelemente in die Backplane integriert, sodass der Steckplatz umgangen wurde, wenn das Gerät nicht bestückt war.

Eine Alternative besteht darin, jeden Befehl durch jedes Mikro zu leiten, was jedoch zu einer erheblichen Latenz und einem gewissen Overhead für jedes Mikro führt.

Interessante Lösung, aber leider gibt es keine Möglichkeit, das Busanschlussschema für diese Geräte zu ändern.
@Vadimchik, ja, ich verstehe, es ist etwas, das man von Anfang an einplanen muss. Ich habe diese Antwort eher als Hinweis für diejenigen hinzugefügt, die anfangen.

Wenn Sie anstelle eines echten Busses eine Daisy-Chain-Anordnung hätten, könnten Sie den Master mit dem Slave sprechen lassen, eine Adresse zuweisen und ihm dann einen Befehl senden, um den ausgehenden Port zum nächsten Slave zu aktivieren. Wiederholen, bis alle Slaves Adressen haben. So funktioniert die USB-Aufzählung im Grunde mit gestapelten Hubs.

Außerdem, welche Art von Hardware-Anordnung verwenden Sie? Sind die Slave-Boards, die in eine Backplane gesteckt werden? Wenn dies der Fall ist, können Sie dem Anschluss zusätzliche Pins mit unterschiedlichen Anordnungen von Pins hinzufügen, die an jedem Steckplatz geerdet sind, um als Identifikation zu fungieren, die von GPIOs auf dem Slave gelesen wird, um die Adresse des Slaves zu generieren.

Meine Hardware ist mit einem 4-adrigen Kabel verbunden: gnd, vcc und zwei Drähte, die wie Miso und Mosi wirken. Es gibt keine Möglichkeit, Slaves konsequent auszuschalten: In jedem Moment können sie ein- oder ausgeschaltet oder ein- oder ausgeschaltet werden.

Wenn Sie keine feste ID haben und die Hardware nicht ändern können, um die Verbindungen zu unterbrechen, benötigen Sie ziemlich genau einen Zufallszahlengenerator.

Das folgende System kann tun, was Sie möchten, wenn Sie eine Möglichkeit haben, in jedem Mikro unabhängig voneinander eine Zufallszahl zu generieren.

Geben Sie hier die Bildbeschreibung ein

Das Generieren des Zufallszahlenteils ist jedoch fast so schwierig wie das Finden Ihres ID-Teils, wenn die Mikros nicht mit einem analogen Signal verbunden sind, mit dem Sie Ihren Zufallszahlengenerator starten können.